- 24-bit color .ICO/.CUR files can now be read.
authorTony Cook <tony@develop=help.com>
Wed, 28 May 2008 04:27:34 +0000 (04:27 +0000)
committerTony Cook <tony@develop=help.com>
Wed, 28 May 2008 04:27:34 +0000 (04:27 +0000)
Changes
ICO/imicon.c
ICO/msicon.c
ICO/t/t10icon.t
ICO/testimg/rgb1616.ico [new file with mode: 0644]

diff --git a/Changes b/Changes
index 3c7bfa7..eb59404 100644 (file)
--- a/Changes
+++ b/Changes
@@ -3,6 +3,8 @@ Imager release history.  Older releases can be found in Changes.old
 Imager 0.66 - unreleased
 ===========
 
+ - 24-bit color .ICO/.CUR files can now be read.
+
 Bug fixes:
 
  - an optimization skipping 0 src alpha values could cause the
index c132f68..2246592 100644 (file)
@@ -46,13 +46,15 @@ read_one_icon(ico_reader_t *file, int index, int masked) {
     i_color *line_buf;
     i_color *outp;
     ico_color_t *inp = image->image_data;
+    int channels = masked || image->bit_count == 32 ? 4 : 3;
 
-    if (!i_int_check_image_file_limits(image->width, image->height, 4, 1)) {
+    if (!i_int_check_image_file_limits(image->width, image->height, channels, 1)) {
       ico_image_release(image);
       return NULL;
     }
 
-    result = i_img_8_new(image->width, image->height, 4);
+    
+    result = i_img_8_new(image->width, image->height, channels);
     if (!result) {
       ico_image_release(image);
       return NULL;
index e8e2d89..0b878be 100644 (file)
@@ -10,6 +10,8 @@ int read_packed(io_glue *ig, const char *format, ...);
 static int 
 read_palette(ico_reader_t *file, ico_image_t *image, int *error);
 static int 
+read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error);
+static int 
 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error);
 static int 
 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error);
@@ -256,7 +258,8 @@ ico_image_read(ico_reader_t *file, int index, int *error) {
     return NULL;
   }
 
-  if (bit_count != 1 && bit_count != 4 && bit_count != 8 && bit_count != 32) {
+  if (bit_count != 1 && bit_count != 4 && bit_count != 8
+      && bit_count != 24 && bit_count != 32) {
     *error = ICOERR_Unknown_Bits;
     return 0;
   }
@@ -291,6 +294,21 @@ ico_image_read(ico_reader_t *file, int index, int *error) {
       return NULL;
     }
   }
+  else if (bit_count == 24) {
+    result->palette_size = 0;
+
+    result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
+    if (!result->image_data) {
+      free(result);
+      *error = ICOERR_Out_Of_Memory;
+      return NULL;
+    }
+    if (!read_24bit_data(file, result, error)) {
+      free(result->image_data);
+      free(result);
+      return NULL;
+    }
+  }
   else {
     int read_result;
 
@@ -780,6 +798,56 @@ read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
   return 1;
 }
 
+/*
+=item read_24bit_data
+
+Reads 24 bit image data.
+
+=cut
+*/
+
+static
+int
+read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
+  int line_bytes = image->width * 3;
+  unsigned char *buffer;
+  int y;
+  int x;
+  unsigned char *inp;
+  ico_color_t *outp;
+
+  line_bytes = (line_bytes + 3) / 4 * 4;
+
+  buffer = malloc(line_bytes);
+
+  if (!buffer) {
+    *error = ICOERR_Out_Of_Memory;
+    return 0;
+  }
+
+  for (y = image->height - 1; y >= 0; --y) {
+    if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
+      free(buffer);
+      *error = ICOERR_Short_File;
+      return 0;
+    }
+    outp = image->image_data;
+    outp += y * image->width;
+    inp = buffer;
+    for (x = 0; x < image->width; ++x) {
+      outp->b = inp[0];
+      outp->g = inp[1];
+      outp->r = inp[2];
+      outp->a = 255;
+      ++outp;
+      inp += 3;
+    }
+  }
+  free(buffer);
+
+  return 1;
+}
+
 /*
 =item read_8bit_data
 
index bd2d4fe..707bc4b 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 98;
+use Test::More tests => 100;
 use Imager::Test qw(is_image);
 
 BEGIN { use_ok('Imager::File::ICO'); }
@@ -361,3 +361,13 @@ EOS
   is($im2->type, 'direct', 'expect a direct image');
   is_image($im2, $imcopy, 'check against expected');
 }
+
+{
+  # read 24-bit images
+  my $im = Imager->new;
+  ok($im->read(file => 'testimg/rgb1616.ico'), "read 24-bit data image")
+    or print "# ", $im->errstr, "\n";
+  my $vs = Imager->new(xsize => 16, ysize => 16);
+  $vs->box(filled => 1, color => '#333366');
+  is_image($im, $vs, "check we got the right colors");
+}
diff --git a/ICO/testimg/rgb1616.ico b/ICO/testimg/rgb1616.ico
new file mode 100644 (file)
index 0000000..59bfe2a
Binary files /dev/null and b/ICO/testimg/rgb1616.ico differ