Add preliminary direct support for WebP

This commit is contained in:
Přemysl Eric Janouch 2021-12-11 18:25:25 +01:00
parent b868e76a15
commit caca14036c
Signed by: p
GPG Key ID: A0420B94F92B9493
4 changed files with 82 additions and 2 deletions

View File

@ -2,7 +2,8 @@ fastiv
====== ======
'fastiv' is a fast image viewer, supporting BMP, PNG, GIF, JPEG, and optionally 'fastiv' is a fast image viewer, supporting BMP, PNG, GIF, JPEG, and optionally
raw photos, HEIC, AVIF, SVG, X11 cursors and TIFF, or whatever gdk-pixbuf loads. raw photos, HEIC, AVIF, WebP, SVG, X11 cursors and TIFF, or whatever gdk-pixbuf
loads.
It still has some road to go, but it's already become quite usable, It still has some road to go, but it's already become quite usable,
and it has received basic polishing. and it has received basic polishing.
@ -25,7 +26,7 @@ Building and Running
Build dependencies: Meson, pkg-config + Build dependencies: Meson, pkg-config +
Runtime dependencies: gtk+-3.0, glib>=2.64, pixman-1, shared-mime-info, Runtime dependencies: gtk+-3.0, glib>=2.64, pixman-1, shared-mime-info,
spng>=0.7.0, libturbojpeg + spng>=0.7.0, libturbojpeg +
Optional dependencies: LibRaw, librsvg-2.0, xcursor, libheif, libtiff, Optional dependencies: LibRaw, librsvg-2.0, xcursor, libwebp, libheif, libtiff,
gdk-pixbuf-2.0 gdk-pixbuf-2.0
$ git clone --recursive https://git.janouch.name/p/fastiv.git $ git clone --recursive https://git.janouch.name/p/fastiv.git

View File

@ -33,6 +33,9 @@
#ifdef HAVE_XCURSOR #ifdef HAVE_XCURSOR
#include <X11/Xcursor/Xcursor.h> #include <X11/Xcursor/Xcursor.h>
#endif // HAVE_XCURSOR #endif // HAVE_XCURSOR
#ifdef HAVE_LIBWEBP
#include <webp/decode.h>
#endif // HAVE_LIBWEBP
#ifdef HAVE_LIBHEIF #ifdef HAVE_LIBHEIF
#include <libheif/heif.h> #include <libheif/heif.h>
#endif // HAVE_LIBHEIF #endif // HAVE_LIBHEIF
@ -1110,6 +1113,67 @@ open_xcursor(const gchar *data, gsize len, GError **error)
} }
#endif // HAVE_XCURSOR -------------------------------------------------------- #endif // HAVE_XCURSOR --------------------------------------------------------
#ifdef HAVE_LIBWEBP //---------------------------------------------------------
static cairo_surface_t *
open_libwebp(const gchar *data, gsize len, GError **error)
{
// It is wholly zero-initialized by libwebp.
WebPDecoderConfig config = {};
if (!WebPInitDecoderConfig(&config)) {
set_error(error, "libwebp version mismatch");
return NULL;
}
// TODO(p): Differentiate between a bad WebP, and not a WebP.
VP8StatusCode err = 0;
if ((err = WebPGetFeatures((const uint8_t *) data, len, &config.input))) {
set_error(error, "WebP decoding error");
return NULL;
}
cairo_surface_t *result = NULL;
cairo_surface_t *surface = cairo_image_surface_create(
config.input.has_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
config.input.width, config.input.height);
cairo_status_t surface_status = cairo_surface_status(surface);
if (surface_status != CAIRO_STATUS_SUCCESS) {
set_error(error, cairo_status_to_string(surface_status));
goto fail;
}
config.options.use_threads = true;
config.output.width = config.input.width;
config.output.height = config.input.height;
config.output.is_external_memory = true;
config.output.u.RGBA.rgba = cairo_image_surface_get_data(surface);
config.output.u.RGBA.stride = cairo_image_surface_get_stride(surface);
config.output.u.RGBA.size =
config.output.u.RGBA.stride * cairo_image_surface_get_height(surface);
if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
config.output.colorspace = MODE_bgrA;
else
config.output.colorspace = MODE_Argb;
if ((err = WebPDecode((const uint8_t *) data, len, &config))) {
set_error(error, "WebP decoding error");
goto fail;
}
// TODO(p): Extract metadata, support animations (has_animation).
result = surface;
fail:
if (!result)
cairo_surface_destroy(surface);
WebPFreeDecBuffer(&config.output);
return result;
}
#endif // HAVE_LIBWEBP --------------------------------------------------------
#ifdef HAVE_LIBHEIF //--------------------------------------------------------- #ifdef HAVE_LIBHEIF //---------------------------------------------------------
static cairo_surface_t * static cairo_surface_t *
@ -1683,6 +1747,14 @@ fastiv_io_open_from_data(const char *data, size_t len, const gchar *path,
g_clear_error(error); g_clear_error(error);
} }
#endif // HAVE_XCURSOR -------------------------------------------------------- #endif // HAVE_XCURSOR --------------------------------------------------------
#ifdef HAVE_LIBWEBP //---------------------------------------------------------
if ((surface = open_libwebp(data, len, error)))
break;
if (error) {
g_debug("%s", (*error)->message);
g_clear_error(error);
}
#endif // HAVE_LIBWEBP --------------------------------------------------------
#ifdef HAVE_LIBHEIF //--------------------------------------------------------- #ifdef HAVE_LIBHEIF //---------------------------------------------------------
if ((surface = open_libheif(data, len, path, error))) if ((surface = open_libheif(data, len, path, error)))
break; break;

View File

@ -17,6 +17,8 @@ endif
libraw = dependency('libraw', required : get_option('libraw')) libraw = dependency('libraw', required : get_option('libraw'))
librsvg = dependency('librsvg-2.0', required : get_option('librsvg')) librsvg = dependency('librsvg-2.0', required : get_option('librsvg'))
xcursor = dependency('xcursor', required : get_option('xcursor')) xcursor = dependency('xcursor', required : get_option('xcursor'))
libwebp = dependency('libwebp', required : get_option('libwebp'))
libwebpdecoder = dependency('libwebpdecoder', required : get_option('libwebp'))
libheif = dependency('libheif', required : get_option('libheif')) libheif = dependency('libheif', required : get_option('libheif'))
libtiff = dependency('libtiff-4', required : get_option('libtiff')) libtiff = dependency('libtiff-4', required : get_option('libtiff'))
gdkpixbuf = dependency('gdk-pixbuf-2.0', required : get_option('gdk-pixbuf')) gdkpixbuf = dependency('gdk-pixbuf-2.0', required : get_option('gdk-pixbuf'))
@ -29,6 +31,8 @@ dependencies = [
libraw, libraw,
librsvg, librsvg,
xcursor, xcursor,
libwebp,
libwebpdecoder,
libheif, libheif,
libtiff, libtiff,
gdkpixbuf, gdkpixbuf,
@ -41,6 +45,7 @@ conf.set_quoted('PROJECT_VERSION', meson.project_version())
conf.set('HAVE_LIBRAW', libraw.found()) conf.set('HAVE_LIBRAW', libraw.found())
conf.set('HAVE_LIBRSVG', librsvg.found()) conf.set('HAVE_LIBRSVG', librsvg.found())
conf.set('HAVE_XCURSOR', xcursor.found()) conf.set('HAVE_XCURSOR', xcursor.found())
conf.set('HAVE_LIBWEBP', libwebp.found())
conf.set('HAVE_LIBHEIF', libheif.found()) conf.set('HAVE_LIBHEIF', libheif.found())
conf.set('HAVE_LIBTIFF', libtiff.found()) conf.set('HAVE_LIBTIFF', libtiff.found())
conf.set('HAVE_GDKPIXBUF', gdkpixbuf.found()) conf.set('HAVE_GDKPIXBUF', gdkpixbuf.found())

View File

@ -4,6 +4,8 @@ option('librsvg', type : 'feature', value : 'auto',
description : 'Build with SVG support, requires librsvg') description : 'Build with SVG support, requires librsvg')
option('xcursor', type : 'feature', value : 'auto', option('xcursor', type : 'feature', value : 'auto',
description : 'Build with Xcursor support, requires libXcursor') description : 'Build with Xcursor support, requires libXcursor')
option('libwebp', type : 'feature', value : 'auto',
description : 'Build with WEBP support, requires libwebp')
option('libheif', type : 'feature', value : 'auto', option('libheif', type : 'feature', value : 'auto',
description : 'Build with HEIF/AVIF support, requires libheif') description : 'Build with HEIF/AVIF support, requires libheif')
option('libtiff', type : 'feature', value : 'auto', option('libtiff', type : 'feature', value : 'auto',