[gdk-pixbuf] ico: Fix support for 256x256 icons



commit 3997cbb736ec67dd1b5a4205ab7aea3d5aecae1f
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Oct 24 15:19:49 2014 +0200

    ico: Fix support for 256x256 icons
    
    In both loading and saving them. The ico format uses "0" as the width
    or height to mean 256:
    https://en.wikipedia.org/wiki/ICO_%28file_format%29#Icon_resource_structure
    
    Also add a test for that.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=674724

 gdk-pixbuf/io-ico.c |   33 ++++++++++++++++-----------------
 tests/pixbuf-save.c |   33 +++++++++++++++++++++++++++++++++
 tests/test-common.c |    2 +-
 3 files changed, 50 insertions(+), 18 deletions(-)
---
diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c
index 7d8ce31..e4faef5 100644
--- a/gdk-pixbuf/io-ico.c
+++ b/gdk-pixbuf/io-ico.c
@@ -269,6 +269,8 @@ static void DecodeHeader(guchar *Data, gint Bytes,
        for (I=0;I<IconCount;I++) {
                entry = g_new0 (struct ico_direntry_data, 1);
                entry->ImageScore = (Ptr[11] << 24) + (Ptr[10] << 16) + (Ptr[9] << 8) + (Ptr[8]);
+               if (entry->ImageScore == 0)
+                       entry->ImageScore = 256;
                entry->x_hot = (Ptr[5] << 8) + Ptr[4];
                entry->y_hot = (Ptr[7] << 8) + Ptr[6];
                entry->DIBoffset = (Ptr[15]<<24)+(Ptr[14]<<16)+
@@ -349,23 +351,14 @@ static void DecodeHeader(guchar *Data, gint Bytes,
                
        State->Header.width =
            (int)(BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]);
-       if (State->Header.width == 0) {
-               g_set_error_literal (error,
-                                     GDK_PIXBUF_ERROR,
-                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
-                                     _("Icon has zero width"));
-               return;
-       }
+       if (State->Header.width == 0)
+               State->Header.width = 256;
+
        State->Header.height =
            (int)((BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) + (BIH[8]))/2;
            /* /2 because the BIH height includes the transparency mask */
-       if (State->Header.height == 0) {
-               g_set_error_literal (error,
-                                     GDK_PIXBUF_ERROR,
-                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
-                                     _("Icon has zero height"));
-               return;
-       }
+       if (State->Header.height == 0)
+               State->Header.height = 256;
        State->Header.depth = (BIH[15] << 8) + (BIH[14]);
 
        State->Type = State->Header.depth;      
@@ -993,7 +986,7 @@ fill_entry (IconEntry *icon,
        guchar *p, *pixels, *and, *xor;
        gint n_channels, v, x, y;
 
-       if (icon->width > 255 || icon->height > 255) {
+       if (icon->width > 256 || icon->height > 256) {
                g_set_error_literal (error,
                                      GDK_PIXBUF_ERROR,
                                      GDK_PIXBUF_ERROR_BAD_OPTION,
@@ -1132,8 +1125,14 @@ write_icon (FILE *f, GSList *entries)
                size = 40 + icon->height * (icon->and_rowstride + icon->xor_rowstride);
                
                /* directory entry */
-               bytes[0] = icon->width;
-               bytes[1] = icon->height;
+               if (icon->width == 256)
+                       bytes[0] = 0;
+               else
+                       bytes[0] = icon->width;
+               if (icon->height == 256)
+                       bytes[1] = 0;
+               else
+                       bytes[1] = icon->height;
                bytes[2] = icon->n_colors;
                bytes[3] = 0;
                write8 (f, bytes, 4);
diff --git a/tests/pixbuf-save.c b/tests/pixbuf-save.c
index 72a7aea..61ef07b 100644
--- a/tests/pixbuf-save.c
+++ b/tests/pixbuf-save.c
@@ -98,6 +98,38 @@ test_save_roundtrip (void)
 }
 
 static void
+test_save_ico (void)
+{
+  GError *error = NULL;
+  GdkPixbuf *ref, *ref2;
+  GdkPixbuf *pixbuf;
+
+  if (!format_supported ("ico") || !format_supported ("png"))
+    {
+      g_test_skip ("format not supported");
+      return;
+    }
+
+  ref = gdk_pixbuf_new_from_file (g_test_get_filename (G_TEST_DIST, "test-image.png", NULL), &error);
+  g_assert_no_error (error);
+
+  ref2 = gdk_pixbuf_scale_simple (ref, 256, 256, GDK_INTERP_NEAREST);
+  g_object_unref (ref);
+  ref = ref2;
+
+  gdk_pixbuf_save (ref, "pixbuf-save-roundtrip", "ico", &error, NULL);
+  g_assert_no_error (error);
+
+  pixbuf = gdk_pixbuf_new_from_file ("pixbuf-save-roundtrip", &error);
+  g_assert_no_error (error);
+
+  g_assert (pixbuf_equal (pixbuf, ref));
+
+  g_object_unref (pixbuf);
+  g_object_unref (ref);
+}
+
+static void
 test_save_options (void)
 {
   GdkPixbuf *ref;
@@ -142,6 +174,7 @@ main (int argc, char **argv)
 
   g_test_add_func ("/pixbuf/save/roundtrip", test_save_roundtrip);
   g_test_add_func ("/pixbuf/save/options", test_save_options);
+  g_test_add_func ("/pixbuf/save/ico", test_save_ico);
 
   return g_test_run ();
 }
diff --git a/tests/test-common.c b/tests/test-common.c
index c7673e3..a7107a1 100644
--- a/tests/test-common.c
+++ b/tests/test-common.c
@@ -33,7 +33,7 @@ format_supported (const gchar *filename)
   GSList *formats, *l;
   gboolean retval;
   const gchar *names[] = { "png", "jpeg", "bmp", "gif", "ras",
-    "tga", "xpm", "xbm" };
+    "tga", "xpm", "xbm", "ico" };
   gint i;
 
   for (i = 0; i < G_N_ELEMENTS (names); i++)


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