[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1033975: unblock: webp-pixbuf-loader/0.2.1-1



On 06/04/2023 08:50, Sebastian Ramacher wrote:
Control: tags -1 moreinfo

On 2023-04-05 12:46:52 +0200, David Heidelberg wrote:
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: webp-pixbuf-loader@packages.debian.org
Control: affects -1 + src:webp-pixbuf-loader

Please unblock package webp-pixbuf-loader

[ Reason ]
Version 0.0.5 contains multiple bugs and 0.2.0 [1] I pushed was solution
to these problems. Sadly meanwhile 0.2.1 [2] was release with another fix,
which we pushed, but it didn't got into timeframe for 10 days acceptance.
Please provide some information on the issues that were fixed which does
not require us to read upstream changelogs. And since webp-pixbuf-loader
is a key package, the main question for me is whether those bugs could
be fixed with a targetted fix on top of 0.0.5-5 instead.

Hello Sebastian.

Two main bugs present in 0.0.5 solved by moving tovards to 0.2.1 is:

- Exchanging animation for static image leaks memory
- Fixes endianess bug while reading values from buffer

As you see, the webp-pixbuf-loader isn't huge project and backporting fixes from recent version would be a piece of cake on top of 0.2.1, on other hand having to backport on 0.0.5, I would be afraid to introduce more issues and also would be pretty time consuming.

David

P.S. Whole project changelog, see there is multiple README/CI/build/tests work, so only few commits regarding to the functionality. Also the project has much better tests now, so that should also be ensuring, that later in bookworm cycle it won't get broken by hotfixes.

```
decd327 (tag: 0.2.1) tests: move test samples to data subfolder
d0e1568 tests: add NULL GError test for all codepaths
7af088d tests: commit missing meson changes for icc profile test
f708996 io-webp.c: add ICC profile storage support
eaa4ea0 (tag: 0.2.0) io-webp.c: add function to check supported format options 48d9524 io-webp.c: simplify string to 0-100 int conversion for quality option
2e1c547 README: add missing CI badges
a0f8a92 README: add CI badges
2f950fd (tag: 0.1.2) ci: add macos build
19e18d7 tests: add save test and rework test infrastructure
17b87ec io-webp.c: bring back save functionality
c84d336 (tag: 0.1.1) io-webp.c: configure decoder output to write in pixbuf
219ae4c io-webp.c: simplify method naming and order implementations
bf0fca2 io-webp.c: remove WRITABLE flag
0dcbc1e (tag: 0.1.0) Update license headers
c80df7a meson: improve warnings for query_loaders script
3624980 ci: install valgrind through apt
2d67225 ci: add valgrind leak checks
7c891f9 tests: fix double free in t4.c
982d28b Simplified implementation of both static and animated webp implementation
1169cbc docs: add homebrew installation note
f91f79c (tag: 0.0.7) meson: enforcing all endian related includes breaks msys2 builds
39deda6 Show an error if no endian related header is found
88c1f65 Do not run query-loaders upon install, show a warning that it has to be run instead
0f78520 meson: make update cache dir optional
10667e3 meson: break loop if one of the endianness headers is found
7805f51 Fix building on *BSD OS's and Solaris
9482c8f meson: fix link arguments for tests
61fb6ed tests: t3.c refactor and minimize test code
cad173d tests: revert t3.c refactoring to fix windows build failure
ea511d0 ci: print logs on test errors
909b52e Build plugin as shared module instead
cf9ad75 tests: refactor animation test code into a single simplified test
26e9ebf Add Windows CI
652ebc0 tests: Refactor t4.c to remove unneeded code
43d3d77 meson: do not retrieve system triad on non Linux systems
90b1f41 tests: remove deprecation warnings for GTimeVal
43c6624 meson: allow nested variable definition for the gdk pixbuf module path for relocatable installations e2ddddf io-webp.c: Remove memory leak from use of heap allocated save_context
faf4eba tests: Remove unnecessary GError
08aa6ed ci: Remove fedora.yml workflow
702ad40 ci: Add Fedora workflow
1e1cad7 (tag: 0.0.6) ci: use ninja -C for the build dir
ee74005 ci: use latest ubuntu to get up to date meson
9bbbc46 Add checkout step
e3ef3ea ci: Fix workflow path
eb06324 Add initial GitHub Actions CI script
64f2b2f Update build instructions in README.md
cfac732 meson: automatically detect gdk-pixbuf-query-loaders path on Debian
d4c2057 Removing travis file as free plans do not cover us anymore
4e84549 io-webp.io: Fixes endianess bug while reading values from buffer
```


[1] https://github.com/aruiz/webp-pixbuf-loader/releases/tag/0.2.0
[2] https://github.com/aruiz/webp-pixbuf-loader/releases/tag/0.2.1

[ Impact ]

Buggy user experience on old codebase, multiple critical and not resolved bugs.

[ Tests ]
The package has autopkgtests, which has been extended in 0.2.0 and
0.2.1.

[ Risks ]
Package itself is very small and after codebase rework, the fixes are
incremental and self-explaining covered with tests.

[ Checklist ]
   [ ] all changes are documented in the d/changelog
   [x] I reviewed all changes and I approve them
   [p] attach debdiff against the package in testing

[ Other info ]
I attach diff against the previously sent 0.2.0, since that was targeted
to get into bookworm. If requested, I can send debdiff against 0.0.5.
The debdiff between testing and the version in unstable is the relevant
one.

Cheers

```
--- webp-pixbuf-loader-0.2.0/debian/changelog	2023-02-26 11:55:51.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/debian/changelog	2023-03-04 01:30:48.000000000 +0100
@@ -1,3 +1,11 @@
+webp-pixbuf-loader (0.2.1-1) UNRELEASED; urgency=medium
+
+  [ David Heidelberg ]
+  * New upstream version 0.2.1 (Closes: #1032334)
+  * d/tests: extend tests by two new upstream tests
+
+ -- David Heidelberg <david@ixit.cz>  Sat, 04 Mar 2023 01:30:48 +0100
+
  webp-pixbuf-loader (0.2.0-1) unstable; urgency=medium
* New upstream version 0.2.0
diff -Nru webp-pixbuf-loader-0.2.0/debian/tests/determinism-test webp-pixbuf-loader-0.2.1/debian/tests/determinism-test
--- webp-pixbuf-loader-0.2.0/debian/tests/determinism-test	2023-02-26 11:55:51.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/debian/tests/determinism-test	2023-03-04 01:30:48.000000000 +0100
@@ -4,7 +4,7 @@
set -eu -gdk-pixbuf-thumbnailer -s 128 tests/t1.webp test1.png
+gdk-pixbuf-thumbnailer -s 128 tests/data/t1.webp test1.png
  file -i test1.png | grep -qFw image/png
-gdk-pixbuf-thumbnailer -s 128 tests/t1.webp test2.png
+gdk-pixbuf-thumbnailer -s 128 tests/data/t1.webp test2.png
  cmp -s test1.png test2.png
diff -Nru webp-pixbuf-loader-0.2.0/debian/tests/upstream-tests webp-pixbuf-loader-0.2.1/debian/tests/upstream-tests
--- webp-pixbuf-loader-0.2.0/debian/tests/upstream-tests	2023-02-26 11:55:51.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/debian/tests/upstream-tests	2023-03-04 01:30:48.000000000 +0100
@@ -4,8 +4,10 @@
set -ex -TEST_FILE="./tests/t1.webp" ./obj*/tests/t1
-TEST_FILE="./tests/t2.webp" ./obj*/tests/t2
-TEST_FILE="./tests/t3.webp" ./obj*/tests/t3
-TEST_FILE="./tests/t1.webp" ./obj*/tests/t4
-TEST_FILE="./tests/t2.webp" ./obj*/tests/t_save
+TEST_FILE="./tests/data/t1.webp" ./obj*/tests/t1
+TEST_FILE="./tests/data/t2.webp" ./obj*/tests/t2
+TEST_FILE="./tests/data/t3.webp" ./obj*/tests/t3
+TEST_FILE="./tests/data/t1.webp" ./obj*/tests/t4
+TEST_FILE="./tests/data/t2.webp" ./obj*/tests/t_save
+TEST_FILE="./tests/data/t2.webp" ./obj*/tests/t_icc
+TEST_FILE="./tests/data/t2.webp" ./obj*/tests/t_null_error
diff -Nru webp-pixbuf-loader-0.2.0/io-webp.c webp-pixbuf-loader-0.2.1/io-webp.c
--- webp-pixbuf-loader-0.2.0/io-webp.c	2023-02-23 23:30:45.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/io-webp.c	2023-03-04 00:36:54.000000000 +0100
@@ -12,6 +12,7 @@
#include "io-webp.h"
  #include "io-webp-anim.h"
+#include <webp/mux.h>
static gpointer
  begin_load (GdkPixbufModuleSizeFunc     size_func,
@@ -192,7 +193,7 @@
  write_file (const uint8_t *data, size_t data_size, const WebPPicture *const pic)
  {
    FILE *const out = (FILE *) pic->custom_ptr;
-  return data_size ? (fwrite (data, data_size, 1, out) == 1) : 1;
+  return data_size == fwrite (data, sizeof (guchar), data_size, out) ? TRUE : FALSE;
  }
/* Encoder write callback to accumulate output data in a GByteArray */
@@ -207,7 +208,7 @@
  static gboolean
  is_save_option_supported (const gchar *option_key)
  {
-  char *options[3] = { "quality", "preset", NULL };
+  char *options[4] = { "quality", "preset", "icc-profile", NULL };
    for (char **o = options; *o; o++)
      {
        if (g_strcmp0 (*o, option_key) == 0)
@@ -216,6 +217,40 @@
    return FALSE;
  }
+/* Creates a new image data buffer with the ICC profile data in it */
+WebPData
+add_icc_data (WebPData *image_data, WebPData *icc_data, GError **error)
+{
+  WebPMux *mux = WebPMuxCreate (image_data, FALSE);
+
+  if (mux == NULL)
+    {
+      g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED,
+                   "Could not create WebPMux instance");
+      return (WebPData){ 0 };
+    }
+
+  if (WebPMuxSetChunk (mux, "ICCP", icc_data, FALSE) != WEBP_MUX_OK)
+    {
+      g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED,
+                   "Could not set ICC profile data WebP using Muxer");
+      WebPMuxDelete (mux);
+      return (WebPData){ 0 };
+    }
+
+  WebPData output = { 0 };
+  if (WebPMuxAssemble (mux, &output) != WEBP_MUX_OK)
+    {
+      g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED,
+                   "Could not assemble WebP data using Muxer");
+      WebPMuxDelete (mux);
+      return (WebPData){ 0 };
+    }
+
+  WebPMuxDelete (mux);
+  return output;
+}
+
  static gboolean
  save_webp (GdkPixbuf        *pixbuf,
             gchar           **keys,
@@ -227,6 +262,10 @@
  {
    WebPPicture picture;
    WebPConfig  config;
+  uint8_t    *icc_data     = NULL;
+  gsize       icc_data_len = 0;
+
+  g_clear_error (error);
if (! WebPPictureInit (&picture) || ! WebPConfigInit (&config))
      {
@@ -242,14 +281,18 @@
while (*kiter)
          {
-          if (strncmp (*kiter, "quality", 7) == 0)
+          if (g_strcmp0 (*kiter, "quality") == 0)
              {
                guint64 quality;
                if (! g_ascii_string_to_unsigned (*viter, 10, 0, 100, &quality, error))
                  return FALSE;
                config.quality = (float) quality;
              }
-          else if (strncmp (*kiter, "preset", 6) == 0)
+          else if (g_strcmp0 (*kiter, "icc-profile") == 0)
+            {
+              icc_data = g_base64_decode (*viter, &icc_data_len);
+            }
+          else if (g_strcmp0 (*kiter, "preset") == 0)
              {
                gchar     *PRESET_KEYS[7] = { "default", "picture", "photo",
                                              "drawing", "icon",    "text",
@@ -314,12 +357,14 @@
        return FALSE;
      }
- if (save_func)
+  gboolean uses_array = save_func || icc_data;
+
+  if (uses_array)
      {
        picture.writer     = write_array;
        picture.custom_ptr = (void *) g_byte_array_new ();
      }
-  else if (f)
+  else if (f && ! icc_data)
      {
        picture.writer     = write_file;
        picture.custom_ptr = (void *) f;
@@ -336,26 +381,45 @@
      {
        g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION,
                     "Could not encode WebP data");
-      if (save_func && picture.custom_ptr)
+      if ((save_func || icc_data) && picture.custom_ptr)
          g_byte_array_free ((GByteArray *) picture.custom_ptr, TRUE);
        WebPPictureFree (&picture);
        return FALSE;
      }
- if (save_func)
+  gpointer custom_ptr = picture.custom_ptr;
+  WebPPictureFree (&picture);
+
+  if (uses_array)
      {
-      GByteArray *arr = (GByteArray *) picture.custom_ptr;
-      save_func ((const gchar *) arr->data, arr->len, error, user_data);
-      g_byte_array_free (arr, TRUE);
+      WebPData data; // NOTE We can't do field initialization since we can't get length after free
+      data.size  = ((GByteArray *) custom_ptr)->len;
+      data.bytes = g_byte_array_free ((GByteArray *) custom_ptr, FALSE);
- if (*error)
+      if (icc_data)
          {
-          WebPPictureFree (&picture);
-          return FALSE;
+          WebPData icc_wpdata = { .bytes = icc_data, .size = icc_data_len };
+
+          WebPData output = add_icc_data (&data, &icc_wpdata, error);
+          g_clear_pointer (&icc_data, g_free);
+          g_free ((gpointer) data.bytes);
+
+          if (output.bytes == NULL)
+            return FALSE;
+
+          data = output;
          }
+
+      gboolean ret = FALSE;
+      if (save_func)
+        ret = save_func ((const gchar *) data.bytes, data.size, error, user_data);
+      else if (f)
+        ret = fwrite (data.bytes, sizeof (guchar), data.size, f) == data.size ? TRUE : FALSE;
+
+      WebPDataClear (&data);
+      return ret;
      }
- WebPPictureFree (&picture);
    return TRUE;
  }
diff -Nru webp-pixbuf-loader-0.2.0/meson.build webp-pixbuf-loader-0.2.1/meson.build
--- webp-pixbuf-loader-0.2.0/meson.build	2023-02-23 23:30:45.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/meson.build	2023-03-04 00:36:54.000000000 +0100
@@ -8,10 +8,11 @@
webp = dependency('libwebp', version: '>0.4.3')
  webpdemux = dependency('libwebpdemux', version: '>0.4.3')
+webpmux = dependency('libwebpmux', version: '>0.4.3')
pbl_webp = shared_module('pixbufloader-webp',
                           sources: ['io-webp.c', 'io-webp-anim.c', 'io-webp-anim-iter.c'],
-                         dependencies: [gdkpb, webp, webpdemux],
+                         dependencies: [gdkpb, webp, webpdemux, webpmux],
                           # Workaround for https://gitlab.gnome.org/GNOME/glib/issues/1413
                           name_suffix: host_machine.system() == 'darwin' ? 'so' : [],
                           install: true,
Binary files /tmp/X5m3CJJqgJ/webp-pixbuf-loader-0.2.0/tests/data/t1.webp and /tmp/NfIwvAZLnM/webp-pixbuf-loader-0.2.1/tests/data/t1.webp differ
Binary files /tmp/X5m3CJJqgJ/webp-pixbuf-loader-0.2.0/tests/data/t2.webp and /tmp/NfIwvAZLnM/webp-pixbuf-loader-0.2.1/tests/data/t2.webp differ
Binary files /tmp/X5m3CJJqgJ/webp-pixbuf-loader-0.2.0/tests/data/t3.webp and /tmp/NfIwvAZLnM/webp-pixbuf-loader-0.2.1/tests/data/t3.webp differ
diff -Nru webp-pixbuf-loader-0.2.0/tests/gtk3-animation-sample.c webp-pixbuf-loader-0.2.1/tests/gtk3-animation-sample.c
--- webp-pixbuf-loader-0.2.0/tests/gtk3-animation-sample.c	2023-02-23 23:30:45.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/tests/gtk3-animation-sample.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,97 +0,0 @@
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <gtk/gtk.h>
-
-/* This test is not an automated test.
- * It is intended to allow one to eye-ball webp animated images
- * in a debug environment, to see if there are problems with
- * image reproduction, timing, etc.
- */
-
-typedef struct _AnimationStructure
-{
-  GtkWindow              *window;
-  GdkPixbufAnimation     *anim;
-  GdkPixbufAnimationIter *anim_iter;
-  GtkWidget              *image;
-  int                     delay;
-} AnimationStructure;
-
-gboolean
-delete_objects (GtkWidget *widget, GdkEvent *event, gpointer data)
-{
-  AnimationStructure *ani = (AnimationStructure *) data;
-  if (ani->anim)
-    g_object_unref (ani->anim);
-
-  g_free (ani);
-  return FALSE;
-}
-
-static void
-activate (GtkApplication *app, gpointer user_data)
-{
-  GtkWidget          *window;
-  GtkWidget          *label;
-  AnimationStructure *ani = (AnimationStructure *) user_data;
-
-  window         = gtk_application_window_new (app);
-  GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-  label          = gtk_label_new ("Test WebP Animation");
-  gtk_container_add (GTK_CONTAINER (box), label);
-
-  GtkWidget *image = NULL;
-
-  /*GdkPixbuf *staticPixbuf = NULL;
-    staticPixbuf = gdk_pixbuf_animation_get_static_image (ani->anim);
-    image = gtk_image_new_from_pixbuf (staticPixbuf);
-  */
-
-  image = gtk_image_new_from_animation (ani->anim);
-  gtk_container_add (GTK_CONTAINER (box), image);
-  gtk_container_add (GTK_CONTAINER (window), box);
-  gtk_window_set_title (GTK_WINDOW (window), "Test");
-  gtk_window_set_default_size (GTK_WINDOW (window), 500, 500);
-  g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (delete_objects), ani);
-  gtk_widget_show_all (window);
-} /* end of function activate */
-
-gint
-main (gint argc, gchar **argv)
-{
-  GError *error = NULL;
-  gchar **env   = g_get_environ ();
-  g_warning ("%s", g_environ_getenv (env, "TEST_FILE"));
-  gtk_init (&argc, &argv);
-
-  /* setup animation. */
-  GdkPixbufAnimation     *anim      = NULL;
-  GdkPixbufAnimationIter *anim_iter = NULL;
-  anim = gdk_pixbuf_animation_new_from_file (g_environ_getenv (env, "TEST_"
-                                                                    "FILE"),
-                                             &error);
-  gboolean isStatic = gdk_pixbuf_animation_is_static_image (anim);
-  if (! isStatic)
-    {
-      GtkApplication *app;
-
-      G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      GTimeVal curTime;
-      g_get_current_time (&curTime);
-      G_GNUC_END_IGNORE_DEPRECATIONS
-
-      AnimationStructure *ani = g_new0 (AnimationStructure, 1);
-      ani->anim               = anim;
-
-      anim_iter      = gdk_pixbuf_animation_get_iter (anim, &curTime);
-      int delay      = gdk_pixbuf_animation_iter_get_delay_time (anim_iter);
-      ani->anim_iter = anim_iter;
-      ani->delay     = delay;
-      app            = gtk_application_new (NULL, G_APPLICATION_FLAGS_NONE);
-      g_signal_connect (app, "activate", G_CALLBACK (activate), ani);
-      (void) g_application_run (G_APPLICATION (app), argc, argv);
-      g_object_unref (app);
-    }
-
-  g_strfreev (env);
-  return 0;
-}
diff -Nru webp-pixbuf-loader-0.2.0/tests/meson.build webp-pixbuf-loader-0.2.1/tests/meson.build
--- webp-pixbuf-loader-0.2.0/tests/meson.build	2023-02-23 23:30:45.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/tests/meson.build	2023-03-04 00:36:54.000000000 +0100
@@ -5,6 +5,8 @@
  t3 = executable('t3', 't3.c', dependencies : [gdkpb, webp, webpdemux])
  t4 = executable('t4', 't4.c', dependencies : [gdkpb, webp, webpdemux])
  t_save = executable('t_save', 't_save.c', dependencies : [gdkpb, webp, webpdemux])
+t_icc  = executable('t_icc',  't_icc.c',  dependencies : [gdkpb, webp, webpdemux, webpmux])
+t_null_error = executable('t_null_error',  't_null_error.c',  dependencies : [gdkpb, webp, webpdemux])
loaders_data = configuration_data()
  loaders_data.set('MODULE_PATH', fs.as_posix(pbl_webp.full_path()))
@@ -13,10 +15,12 @@
                           configuration : loaders_data)
test_env = ['GDK_PIXBUF_MODULE_FILE=' + meson.current_build_dir() / 'loaders.cache']
-test_file_base = 'TEST_FILE=' + meson.current_source_dir()
+test_file_base = 'TEST_FILE=' + meson.current_source_dir() / 'data'
test('load 1x1 image', t1, env : test_env + [ test_file_base / 't1.webp'])
  test('load 200x200 image', t2, env : test_env + [ test_file_base / 't2.webp'])
  test('load animation',     t3, env : test_env + [ test_file_base / 't3.webp'])
  test('get file info',      t4, env : test_env + [ test_file_base / 't1.webp'])
-test('save data',      t_save, env : test_env + [ test_file_base / 't2.webp'])
\ No newline at end of file
+test('save data',         t_save, env : test_env + [ test_file_base / 't2.webp'])
+test('icc data',           t_icc, env : test_env + [ test_file_base / 't2.webp'])
+test('NULL GError', t_null_error, env : test_env + [ test_file_base / 't2.webp'])
\ No newline at end of file
Binary files /tmp/X5m3CJJqgJ/webp-pixbuf-loader-0.2.0/tests/t1.webp and /tmp/NfIwvAZLnM/webp-pixbuf-loader-0.2.1/tests/t1.webp differ
Binary files /tmp/X5m3CJJqgJ/webp-pixbuf-loader-0.2.0/tests/t2.webp and /tmp/NfIwvAZLnM/webp-pixbuf-loader-0.2.1/tests/t2.webp differ
Binary files /tmp/X5m3CJJqgJ/webp-pixbuf-loader-0.2.0/tests/t3.webp and /tmp/NfIwvAZLnM/webp-pixbuf-loader-0.2.1/tests/t3.webp differ
diff -Nru webp-pixbuf-loader-0.2.0/tests/t_icc.c webp-pixbuf-loader-0.2.1/tests/t_icc.c
--- webp-pixbuf-loader-0.2.0/tests/t_icc.c	1970-01-01 01:00:00.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/tests/t_icc.c	2023-03-04 00:36:54.000000000 +0100
@@ -0,0 +1,79 @@
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glib/gstdio.h>
+#include <webp/decode.h>
+#include <webp/mux.h>
+
+static gchar *
+create_filename ()
+{
+  GString *pathbuild = g_string_new (g_get_tmp_dir ());
+  gchar   *id        = g_uuid_string_random ();
+  g_string_append_printf (pathbuild, "%s%s.webp", G_DIR_SEPARATOR_S, id);
+  g_free (id);
+  return g_string_free (pathbuild, FALSE);
+}
+
+void
+test_webp_icc_output (guchar *buffer, gsize buf_size, const gchar *base64_string)
+{
+  WebPData data   = { .bytes = buffer, .size = buf_size };
+  WebPData output = { 0 };
+  WebPMux *mux    = WebPMuxCreate (&data, FALSE);
+  WebPMuxGetChunk (mux, "ICCP", &output);
+  WebPMuxDelete (mux);
+
+  g_assert (output.bytes != NULL);
+  gchar *encoded_icc = g_base64_encode (output.bytes, output.size);
+  g_assert (encoded_icc != NULL);
+  g_assert_cmpstr (encoded_icc, ==, base64_string);
+
+  g_free (encoded_icc);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+  GError *error = NULL;
+  gchar **env   = g_get_environ ();
+
+  GdkPixbuf *pixbuf
+      = gdk_pixbuf_new_from_file (g_environ_getenv (env, "TEST_FILE"), &error);
+  if (error)
+    g_error ("%s", error->message);
+
+  g_assert (! gdk_pixbuf_get_has_alpha (pixbuf));
+
+  g_assert (gdk_pixbuf_get_width (pixbuf) == 200);
+  g_assert (gdk_pixbuf_get_height (pixbuf) == 200);
+
+  g_strfreev (env);
+
+  /* Test on disk contents */
+  gchar *path = create_filename ();
+  gdk_pixbuf_save (pixbuf, path, "webp", &error, "icc-profile", "MQo=", NULL);
+  if (error)
+    g_error ("%s", error->message);
+
+  gchar *buffer;
+  gsize  buf_size;
+  g_file_get_contents (path, &buffer, &buf_size, &error);
+  if (error)
+    g_error ("%s", error->message);
+
+  test_webp_icc_output ((guchar *) buffer, buf_size, "MQo=");
+  g_remove (path);
+  g_clear_pointer (&buffer, g_free);
+  g_clear_pointer (&path, g_free);
+
+  /* Test on memory contents */
+  gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &buf_size, "webp", &error,
+                             "icc-profile", "MQo=", NULL);
+  if (error)
+    g_error ("%s", error->message);
+
+  test_webp_icc_output ((guchar *) buffer, buf_size, "MQo=");
+
+  g_free (buffer);
+  g_object_unref (pixbuf);
+  return 0;
+}
diff -Nru webp-pixbuf-loader-0.2.0/tests/t_null_error.c webp-pixbuf-loader-0.2.1/tests/t_null_error.c
--- webp-pixbuf-loader-0.2.0/tests/t_null_error.c	1970-01-01 01:00:00.000000000 +0100
+++ webp-pixbuf-loader-0.2.1/tests/t_null_error.c	2023-03-04 00:36:54.000000000 +0100
@@ -0,0 +1,50 @@
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glib/gstdio.h>
+
+static gchar *
+create_filename ()
+{
+  GString *pathbuild = g_string_new (g_get_tmp_dir ());
+  gchar   *id        = g_uuid_string_random ();
+  g_string_append_printf (pathbuild, "%s%s.webp", G_DIR_SEPARATOR_S, id);
+  g_free (id);
+  return g_string_free (pathbuild, FALSE);
+}
+
+gboolean
+save_func (const gchar *buffer, gsize count, GError **error, gpointer data)
+{
+  return TRUE;
+}
+
+void
+test_pixbufv (GdkPixbuf *pixbuf, gchar **keys, gchar **values)
+{
+  GStatBuf tmpstat = { 0 };
+  gchar   *path    = create_filename ();
+  g_assert (gdk_pixbuf_savev (pixbuf, path, "webp", keys, values, NULL));
+  g_stat (path, &tmpstat);
+  g_remove (path);
+  g_free (path);
+
+  g_assert (gdk_pixbuf_save_to_callbackv (pixbuf, save_func, NULL, "webp", keys, values, NULL));
+}
+
+int
+main ()
+{
+  gchar **env = g_get_environ ();
+
+  GdkPixbuf *pixbuf
+      = gdk_pixbuf_new_from_file (g_environ_getenv (env, "TEST_FILE"), NULL);
+  g_assert (pixbuf != NULL);
+  g_clear_pointer (&env, g_strfreev);
+
+  gchar *keys[2]   = { "icc-profile", NULL };
+  gchar *values[2] = { "MQo=", NULL };
+
+  test_pixbufv (pixbuf, NULL, NULL);
+  test_pixbufv (pixbuf, keys, values);
+
+  g_object_unref (pixbuf);
+}
\ No newline at end of file

```

unblock webp-pixbuf-loader/0.2.1-1

--
David Heidelberg
Consultant Software Engineer


Reply to: