From 29f5a35364029f936719cb45885af58bbaf102ec Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Mon, 6 Nov 2023 18:08:36 +0000 Subject: [PATCH] Fix #1076: webp images show up as black https://github.com/BestImageViewer/geeqie/issues/1076 - Include https://github.com/aruiz/webp-pixbuf-loader.git as a subproject - Patch the sources to fix this bug - This commit can be removed when the origin sources are updated - Animated webp images will be displayed --- AppImageBuilder-aarch64.yml | 2 + AppImageBuilder-x86_64.yml | 2 + meson.build | 4 + scripts/meson.build | 2 + scripts/patch-loaders-cache.sh | 44 +++++ scripts/update-pixbuf-loaders-cache.sh | 34 ++++ src/image-load-webp.cc | 152 ------------------ src/image-load-webp.h | 29 ---- src/image-load.cc | 11 -- src/meson.build | 6 +- .../webp-pixbuf-loader/meson-build.diff | 17 ++ .../webp-pixbuf-loader/pull-73.diff | 45 ++++++ subprojects/webp-pixbuf-loader.wrap | 6 + 13 files changed, 160 insertions(+), 194 deletions(-) create mode 100755 scripts/patch-loaders-cache.sh create mode 100755 scripts/update-pixbuf-loaders-cache.sh delete mode 100644 src/image-load-webp.cc delete mode 100644 src/image-load-webp.h create mode 100644 subprojects/packagefiles/webp-pixbuf-loader/meson-build.diff create mode 100644 subprojects/packagefiles/webp-pixbuf-loader/pull-73.diff create mode 100644 subprojects/webp-pixbuf-loader.wrap diff --git a/AppImageBuilder-aarch64.yml b/AppImageBuilder-aarch64.yml index 81735b95..5cebef43 100644 --- a/AppImageBuilder-aarch64.yml +++ b/AppImageBuilder-aarch64.yml @@ -6,6 +6,8 @@ script: - which mksquashfs || apt install squashfs-tools AppDir: + after_runtime: | + ./scripts/patch-loaders-cache.sh path: ./AppDir app_info: id: geeqie diff --git a/AppImageBuilder-x86_64.yml b/AppImageBuilder-x86_64.yml index 3837df39..de2e05ea 100644 --- a/AppImageBuilder-x86_64.yml +++ b/AppImageBuilder-x86_64.yml @@ -6,6 +6,8 @@ script: - which mksquashfs || apt install squashfs-tools AppDir: + after_runtime: | + ./scripts/patch-loaders-cache.sh path: /home/runner/work/geeqie/geeqie/AppDir/ app_info: id: geeqie diff --git a/meson.build b/meson.build index 51bbdcaf..052eb0b0 100644 --- a/meson.build +++ b/meson.build @@ -768,3 +768,7 @@ if not option.disabled() else summary({'lua' : ['Test runs:', false]}, section : 'Testing', bool_yn : true) endif + +if conf_data.has('HAVE_WEBP') + meson.add_install_script('./scripts/update-pixbuf-loaders-cache.sh') +endif diff --git a/scripts/meson.build b/scripts/meson.build index 305ba369..57032026 100644 --- a/scripts/meson.build +++ b/scripts/meson.build @@ -25,8 +25,10 @@ script_sources += files('authors.sh', 'lua-test.sh', 'modify-downloaded-icons.sh', 'new-release.sh', +'patch-loaders-cache.sh', 'template-desktop.sh', 'translators.sh', 'untranslated-text.sh', +'update-pixbuf-loaders-cache.sh', 'web-help.sh') diff --git a/scripts/patch-loaders-cache.sh b/scripts/patch-loaders-cache.sh new file mode 100755 index 00000000..53c2c504 --- /dev/null +++ b/scripts/patch-loaders-cache.sh @@ -0,0 +1,44 @@ +#!/bin/sh +#********************************************************************** +# Copyright (C) 2023 - The Geeqie Team +# +# Author: Colin Clark +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#********************************************************************** + +## @file +## @brief Update pixbuf loaders.cache file +## +## Required only for webp-pixbuf-loader subproject, and +## is run only when an AppImage is being created +## + +loader=$(find ./AppDir -name libpixbufloader-webp.so) +loaders_cache=$(find ./AppDir -name loaders.cache) +dest=$(dirname "$loaders_cache" | sed s/local//) +loaders_cache_dest=$(echo "$loaders_cache" | sed s/local//) + +cat << EOF >> "$loaders_cache" +"libpixbufloader-webp.so" +"webp" 5 "gdk-pixbuf" "The WebP image format" "LGPL" +"image/webp" "audio/x-riff" "" +"webp" "" +"RIFFsizeWEBP" " xxxx " 100 + +EOF + +cp -n "$loaders_cache" "$loaders_cache_dest" +cp -n "$loader" "$dest""/loaders" diff --git a/scripts/update-pixbuf-loaders-cache.sh b/scripts/update-pixbuf-loaders-cache.sh new file mode 100755 index 00000000..3c1d6452 --- /dev/null +++ b/scripts/update-pixbuf-loaders-cache.sh @@ -0,0 +1,34 @@ +#!/bin/sh +#********************************************************************** +# Copyright (C) 2023 - The Geeqie Team +# +# Author: Colin Clark +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#********************************************************************** + +## @file +## @brief Update pixbuf loaders.cache file +## +## Required only for webp-pixbuf-loader subproject, and +## only when Geeqie is being installed +## + +loader=$(find /usr/local -name libpixbufloader-webp.so) +dest=$(pkg-config gdk-pixbuf-2.0 --variable=gdk_pixbuf_moduledir) + +sudo cp "$loader" "$dest" + +sudo "$(pkg-config gdk-pixbuf-2.0 --variable=gdk_pixbuf_query_loaders)" --update-cache diff --git a/src/image-load-webp.cc b/src/image-load-webp.cc deleted file mode 100644 index e9d767f7..00000000 --- a/src/image-load-webp.cc +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 20019 - The Geeqie Team - * - * Author: Colin Clark - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "main.h" - -#include "image-load.h" -#include "image-load-webp.h" - -#ifdef HAVE_WEBP -#include - -typedef struct _ImageLoaderWEBP ImageLoaderWEBP; -struct _ImageLoaderWEBP { - ImageLoaderBackendCbAreaUpdated area_updated_cb; - ImageLoaderBackendCbSize size_cb; - ImageLoaderBackendCbAreaPrepared area_prepared_cb; - gpointer data; - GdkPixbuf *pixbuf; - guint requested_width; - guint requested_height; - gboolean abort; -}; - -static void free_buffer(guchar *pixels, gpointer) -{ - g_free(pixels); -} - -static gboolean image_loader_webp_load(gpointer loader, const guchar *buf, gsize count, GError **) -{ - auto ld = static_cast(loader); - gboolean res_info; - gint width, height; - guint8* data; - VP8StatusCode status_code; - WebPBitstreamFeatures features; - - res_info = WebPGetInfo(buf, count, &width, &height); - if (!res_info) - { - log_printf("warning: webp reader error\n"); - return FALSE; - } - - status_code = WebPGetFeatures(buf, count, &features); - if (status_code != VP8_STATUS_OK) - { - log_printf("warning: webp reader error\n"); - return FALSE; - } - - if (features.has_alpha) - { - data = WebPDecodeRGBA(buf, count, &width, &height); - } - else - { - data = WebPDecodeRGB(buf, count, &width, &height); - } - - ld->pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, features.has_alpha, 8, width, height, width * (features.has_alpha ? 4 : 3), free_buffer, NULL); - - ld->area_updated_cb(loader, 0, 0, width, height, ld->data); - - return TRUE; -} - -static gpointer image_loader_webp_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) -{ - auto loader = g_new0(ImageLoaderWEBP, 1); - loader->area_updated_cb = area_updated_cb; - loader->size_cb = size_cb; - loader->area_prepared_cb = area_prepared_cb; - loader->data = data; - return (gpointer) loader; -} - -static void image_loader_webp_set_size(gpointer loader, int width, int height) -{ - auto ld = static_cast(loader); - ld->requested_width = width; - ld->requested_height = height; -} - -static GdkPixbuf* image_loader_webp_get_pixbuf(gpointer loader) -{ - auto ld = static_cast(loader); - return ld->pixbuf; -} - -static gchar* image_loader_webp_get_format_name(gpointer) -{ - return g_strdup("webp"); -} - -static gchar** image_loader_webp_get_format_mime_types(gpointer) -{ - static const gchar *mime[] = {"image/webp", nullptr}; - return g_strdupv(const_cast(mime)); -} - -static gboolean image_loader_webp_close(gpointer, GError **) -{ - return TRUE; -} - -static void image_loader_webp_abort(gpointer loader) -{ - auto ld = static_cast(loader); - ld->abort = TRUE; -} - -static void image_loader_webp_free(gpointer loader) -{ - auto ld = static_cast(loader); - if (ld->pixbuf) g_object_unref(ld->pixbuf); - g_free(ld); -} - -void image_loader_backend_set_webp(ImageLoaderBackend *funcs) -{ - funcs->loader_new = image_loader_webp_new; - funcs->set_size = image_loader_webp_set_size; - funcs->load = image_loader_webp_load; - funcs->write = NULL; - funcs->get_pixbuf = image_loader_webp_get_pixbuf; - funcs->close = image_loader_webp_close; - funcs->abort = image_loader_webp_abort; - funcs->free = image_loader_webp_free; - funcs->get_format_name = image_loader_webp_get_format_name; - funcs->get_format_mime_types = image_loader_webp_get_format_mime_types; -} - -#endif -/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-webp.h b/src/image-load-webp.h deleted file mode 100644 index 7e4c3a93..00000000 --- a/src/image-load-webp.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 20019 - The Geeqie Team - * - * Author: Colin Clark - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef IMAGE_LOAD_WEBP_H -#define IMAGE_LOAD_WEBP_H - -#ifdef HAVE_WEBP -void image_loader_backend_set_webp(ImageLoaderBackend *funcs); -#endif - -#endif -/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load.cc b/src/image-load.cc index 6901d54b..3e763b63 100644 --- a/src/image-load.cc +++ b/src/image-load.cc @@ -32,7 +32,6 @@ #include "image-load-libraw.h" #include "image-load-psd.h" #include "image-load-svgz.h" -#include "image-load-webp.h" #include "image-load-zxscr.h" #include "misc.h" #include "ui-fileops.h" @@ -687,16 +686,6 @@ static void image_loader_setup_loader(ImageLoader *il) } else #endif -#ifdef HAVE_WEBP - if (il->bytes_total >= 12 && - (memcmp(il->mapped_file, "RIFF", 4) == 0) && - (memcmp(il->mapped_file + 8, "WEBP", 4) == 0)) - { - DEBUG_1("Using custom webp loader"); - image_loader_backend_set_webp(&il->backend); - } - else -#endif #ifdef HAVE_DJVU if (il->bytes_total >= 16 && (memcmp(il->mapped_file, "AT&TFORM", 8) == 0) && diff --git a/src/meson.build b/src/meson.build index f23dbf7d..3f9d8df0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -124,8 +124,6 @@ main_sources = files('advanced-exif.cc', 'image-load-svgz.h', 'image-load-tiff.cc', 'image-load-tiff.h', -'image-load-webp.cc', -'image-load-webp.h', 'image-load-zxscr.cc', 'image-load-zxscr.h', 'image-overlay.cc', @@ -266,6 +264,10 @@ if conf_data.has('HAVE_LCMS') project_sources += ClayRGB1998_icc_h endif +if conf_data.has('HAVE_WEBP') + webp_pixbuf_loader_proj = subproject('webp-pixbuf-loader') +endif + geeqie_exe = executable('geeqie', project_sources, dependencies : [ gtk_dep, diff --git a/subprojects/packagefiles/webp-pixbuf-loader/meson-build.diff b/subprojects/packagefiles/webp-pixbuf-loader/meson-build.diff new file mode 100644 index 00000000..5f467a19 --- /dev/null +++ b/subprojects/packagefiles/webp-pixbuf-loader/meson-build.diff @@ -0,0 +1,17 @@ +diff --git a/meson.build b/meson.build +index c46f11b..3b7d93a 100644 +--- a/meson.build ++++ b/meson.build +@@ -7,9 +7,9 @@ if gdk_pb_moddir == '' + gdk_pb_moddir = gdkpb.get_variable(pkgconfig: 'gdk_pixbuf_moduledir', pkgconfig_define: ['prefix', get_option('prefix')]) + endif + +-webp = dependency('libwebp', version: '>=1.3.2') +-webpdemux = dependency('libwebpdemux', version: '>=1.3.2') +-webpmux = dependency('libwebpmux', version: '>=1.3.2') ++webp = dependency('libwebp', version: '>=1.2.2') ++webpdemux = dependency('libwebpdemux', version: '>=1.2.2') ++webpmux = dependency('libwebpmux', version: '>=1.2.2') + + pbl_webp = shared_module('pixbufloader-webp', + sources: ['io-webp.c', 'io-webp-anim.c', 'io-webp-anim-iter.c'], diff --git a/subprojects/packagefiles/webp-pixbuf-loader/pull-73.diff b/subprojects/packagefiles/webp-pixbuf-loader/pull-73.diff new file mode 100644 index 00000000..519b67aa --- /dev/null +++ b/subprojects/packagefiles/webp-pixbuf-loader/pull-73.diff @@ -0,0 +1,45 @@ +diff --git a/io-webp.c b/io-webp.c +index c67e0a9..de2f83a 100644 +--- a/io-webp.c ++++ b/io-webp.c +@@ -143,6 +143,8 @@ stop_load (gpointer data, GError **error) + { + if (context->prepare_func) + context->prepare_func (pb, GDK_PIXBUF_ANIMATION (anim), context->user_data); ++ if (context->update_func) ++ context->update_func (pb, 0, 0, context->width, context->height, context->user_data); + ret = TRUE; + } + +@@ -174,6 +176,9 @@ stop_load (gpointer data, GError **error) + return FALSE; + } + ++ if (context->prepare_func) ++ context->prepare_func (pb, NULL, context->user_data); ++ + if (icc_data) + { + gdk_pixbuf_set_option (pb, "icc-profile", icc_data); +@@ -187,10 +192,8 @@ stop_load (gpointer data, GError **error) + context->buffer->len, &config); + if (status == VP8_STATUS_OK) + { +- if (context->prepare_func) +- context->prepare_func (pb, NULL, context->user_data); +- +- g_clear_object (&pb); ++ if (context->update_func) ++ context->update_func (pb, 0, 0, context->width, context->height, context->user_data); + + ret = TRUE; + } +@@ -198,6 +201,8 @@ stop_load (gpointer data, GError **error) + g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, + "WebP decoder failed with VP8 status code: %d", status); + } ++ ++ g_clear_object (&pb); + } + + if (context->buffer) diff --git a/subprojects/webp-pixbuf-loader.wrap b/subprojects/webp-pixbuf-loader.wrap new file mode 100644 index 00000000..a88055d4 --- /dev/null +++ b/subprojects/webp-pixbuf-loader.wrap @@ -0,0 +1,6 @@ +[wrap-git] +url = https://github.com/aruiz/webp-pixbuf-loader.git +revision = head +depth = 1 +directory = webp-pixbuf-loader +diff_files = webp-pixbuf-loader/pull-73.diff, webp-pixbuf-loader/meson-build.diff -- 2.20.1