From 65a150e7877af228fe05b9b22497709aa4f9133f Mon Sep 17 00:00:00 2001 From: Leonardo Hernández Hernández Date: Sun, 2 Oct 2022 22:49:05 -0500 Subject: webp: intial support for WebP images, using libwebp --- main.c | 7 ++++++ meson.build | 12 +++++++-- meson_options.txt | 1 + webp.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ webp.h | 6 +++++ 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 webp.c create mode 100644 webp.h diff --git a/main.c b/main.c index e3bdaae..1e3c237 100644 --- a/main.c +++ b/main.c @@ -29,6 +29,9 @@ #if defined(WBG_HAVE_JPG) #include "jpg.h" #endif +#if defined(WBG_HAVE_WEBP) + #include "webp.h" +#endif /* Top-level globals */ static struct wl_display *display; @@ -365,6 +368,10 @@ main(int argc, const char *const *argv) #if defined(WBG_HAVE_PNG) if (image == NULL) image = png_load(fp, image_path); +#endif +#if defined(WBG_HAVE_WEBP) + if (image == NULL) + image = webp_load(fp, image_path); #endif if (image == NULL) { fprintf(stderr, "error: %s: failed to load\n", image_path); diff --git a/meson.build b/meson.build index 47c6155..4668cd7 100644 --- a/meson.build +++ b/meson.build @@ -49,8 +49,9 @@ endif pixman = dependency('pixman-1') png = dependency('libpng', required: get_option('png')) jpg = dependency('libjpeg', required: get_option('jpeg')) +webp = dependency('libwebp', required: get_option('webp')) -if not png.found() and not jpg.found() +if not png.found() and not jpg.found() and not webp.found() error('you must enable at least one image format') endif @@ -60,6 +61,9 @@ endif if jpg.found() add_project_arguments('-DWBG_HAVE_JPG=1', language:'c') endif +if webp.found() + add_project_arguments('-DWBG_HAVE_WEBP=1', language:'c') +endif wayland_protocols = dependency('wayland-protocols') wayland_client = dependency('wayland-client') @@ -106,6 +110,9 @@ endif if jpg.found() image_format_sources += ['jpg.c', 'jpg.h'] endif +if webp.found() + image_format_sources += ['webp.c', 'webp.h'] +endif executable( 'wbg', @@ -115,13 +122,14 @@ executable( 'stride.h', image_format_sources, wl_proto_src + wl_proto_headers, version, - dependencies: [pixman, png, jpg, wayland_client, tllist], + dependencies: [pixman, png, jpg, webp, wayland_client, tllist], install: true) summary( { 'PNG support': png.found(), 'JPEG support': jpg.found(), + 'WebP support': webp.found(), }, bool_yn: true ) diff --git a/meson_options.txt b/meson_options.txt index 6818e93..db77d13 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,3 @@ option('png', type: 'feature') option('jpeg', type: 'feature') +option('webp', type: 'feature') diff --git a/webp.c b/webp.c new file mode 100644 index 0000000..82aa493 --- /dev/null +++ b/webp.c @@ -0,0 +1,73 @@ +#include "webp.h" +#include +#include + +#include + +#define LOG_MODULE "webp" +#define LOG_ENABLE_DBG 0 +#include "log.h" +#include "stride.h" + +pixman_image_t * +webp_load(FILE *fp, const char *path) +{ + uint8_t *file_data = NULL; + uint8_t *image_data = NULL; + size_t image_size; + pixman_image_t *pix = NULL; + pixman_format_code_t format; + int width, height, stride; + + if (fseek(fp, 0, SEEK_END) < 0) { + LOG_ERRNO("%s: failed to seek to end of file", path); + return NULL; + } + image_size = ftell(fp); + if (fseek(fp, 0, SEEK_SET) < 0) { + LOG_ERRNO("%s: failed to seek to beginning of file", path); + return NULL; + } + + if (!(file_data = WebPMalloc(image_size + 1))) { + goto err; + } + + clearerr(fp); + fread(file_data, image_size, 1, fp); + if (ferror(fp)) { + LOG_ERRNO("%s: failed to read", path); + goto err; + } + file_data[image_size] = '\0'; + + /* Verify it is a webp image */ + if (!WebPGetInfo(file_data, image_size, NULL, NULL)) { + LOG_ERR("%s: not a WebP file", path); + goto err; + } + + image_data = WebPDecodeRGBA(file_data, image_size, &width, &height); + if (image_data == NULL) { + goto err; + } + format = PIXMAN_x8b8g8r8; + stride = stride_for_format_and_width(format, width); + + pix = pixman_image_create_bits_no_clear( + format, width, height, (uint32_t *)image_data, stride); + + if (pix == NULL) { + LOG_ERR("%s: failed to instantiate pixman image", path); + goto err; + } + + WebPFree(file_data); + return pix; + +err: + WebPFree(file_data); + WebPFree(image_data); + + return NULL; +} diff --git a/webp.h b/webp.h new file mode 100644 index 0000000..2638cd2 --- /dev/null +++ b/webp.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +pixman_image_t *webp_load(FILE *fp, const char *path); -- cgit v1.2.3