[rt #69599] correctly handle 256 x 256 ICO files
authorTony Cook <tony@develop-help.com>
Sat, 12 Nov 2011 05:43:18 +0000 (16:43 +1100)
committerTony Cook <tony@develop-help.com>
Sat, 12 Nov 2011 05:43:18 +0000 (16:43 +1100)
Changes
ICO/imicon.c
ICO/msicon.c
ICO/t/t10icon.t
ICO/testimg/pal256.ico [new file with mode: 0644]
MANIFEST

diff --git a/Changes b/Changes
index 038f793..1cd74a6 100644 (file)
--- a/Changes
+++ b/Changes
@@ -10,6 +10,9 @@ Imager release history.  Older releases can be found in Changes.old
 
  - actually include the Imager::Test tests in the dist
 
+ - correctly read and write 256x256 pixel ICO files
+   https://rt.cpan.org/Ticket/Display.html?id=69599
+
 Imager 0.86 - 31 Oct 2011
 ===========
 
index 2246592..cb622cf 100644 (file)
@@ -256,7 +256,7 @@ i_readico_multi(io_glue *ig, int *count, int masked) {
 
 static int
 validate_image(i_img *im) {
-  if (im->xsize > 255 || im->ysize > 255) {
+  if (im->xsize > 256 || im->ysize > 256) {
     i_push_error(0, "image too large for ico file");
     return 0;
   }
index 6847504..7d31690 100644 (file)
@@ -182,8 +182,9 @@ ico_reader_open(i_io_glue_t *ig, int *error) {
       image->hotspot_y = hotspot_y;
     }
 
-    image->width = width;
-    image->height = height;
+    /* a width or height of zero here indicates a width/height of 256 */
+    image->width = width ? width : 256;
+    image->height = height ? height : 256;
     image->offset = image_offset;
     image->size = bytes_in_res;
   }
@@ -482,9 +483,11 @@ ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
     ico_image_t const *image = images + i;
     int bits, colors;
     int size = ico_image_size(image, &bits, &colors);
+    int width_byte = image->width == 256 ? 0 : image->width;
+    int height_byte = image->height == 256 ? 0 : image->height;
 
     if (type == ICON_ICON) {
-      if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
+      if (!write_packed(ig, "bbbbwwdd", width_byte, height_byte,
                        colors, 0, 1, bits, (unsigned long)size, 
                        (unsigned long)current_offset)) {
        *error = ICOERR_Write_Failure;
@@ -504,7 +507,7 @@ ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
       else if (hotspot_y >= image->height)
        hotspot_y = image->height - 1;
 
-      if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
+      if (!write_packed(ig, "bbbbwwdd", width_byte, height_byte,
                        colors, 0, hotspot_x, hotspot_y, (unsigned long)size, 
                        (unsigned long)current_offset)) {
        *error = ICOERR_Write_Failure;
@@ -1044,11 +1047,11 @@ ico_write_validate(ico_image_t const *images, int image_count, int *error) {
   for (i = 0; i < image_count; ++i) {
     ico_image_t const *image = images + i;
 
-    if (image->width < 1 || image->width > 255) {
+    if (image->width < 1 || image->width > 256) {
       *error = ICOERR_Invalid_Width;
       return 0;
     }
-    if (image->height < 1 || image->height > 255) {
+    if (image->height < 1 || image->height > 256) {
       *error = ICOERR_Invalid_Height;
       return 0;
     }
index 25b1917..454a462 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 102;
+use Test::More tests => 106;
 use Imager::Test qw(is_image test_image);
 
 BEGIN { use_ok('Imager::File::ICO'); }
@@ -385,3 +385,33 @@ EOS
     like($im->errstr, qr/synthetic close failure/,
         "check error message");
 }
+
+{ # RT #69599
+  {
+    my $ico = Imager->new(file => "testimg/pal256.ico", filetype => "ico");
+    ok($ico, "read a 256x256 pixel wide/high icon")
+      or diag "Could not read 256x256 pixel icon: ",Imager->errstr;
+  }
+  SKIP:
+  {
+    my $im = test_image();
+    my $sc = $im->scale(xpixels => 256, ypixels => 256, type => "nonprop")
+      or diag("Cannot scale: " . $im->errstr);
+    $sc
+      or skip("Cannot produce scaled image", 3);
+    my $alpha = $sc->convert(preset => "addalpha")
+      or diag "Cannot add alpha channel: " . $sc->errstr ;
+    
+    my $data;
+    ok($alpha->write(data => \$data, type => "ico"),
+       "save 256x256 image")
+      or diag("Cannot save 256x256 icon:" . $alpha->errstr);
+    my $read = Imager->new(data => $data, filetype => "ico");
+    ok($read, "read 256x256 pixel image back in")
+      or diag(Imager->errstr);
+    $read
+      or skip("Couldn't read to compare", 1);
+    is_image($read, $alpha, "check we read what we wrote");
+  }
+}
+
diff --git a/ICO/testimg/pal256.ico b/ICO/testimg/pal256.ico
new file mode 100644 (file)
index 0000000..9e2ee95
Binary files /dev/null and b/ICO/testimg/pal256.ico differ
index d2bd8c0..74e493b 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -115,6 +115,7 @@ ICO/t/t72cursing.t
 ICO/t/t73curmult.t
 ICO/testimg/combo.ico
 ICO/testimg/pal13232.ico
+ICO/testimg/pal256.ico
 ICO/testimg/pal43232.cur
 ICO/testimg/pal43232.ico
 ICO/testimg/pal43232.ppm