From c668f2cbc8ff3db4526d86b21cc8e9852bafdf5e Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Wed, 28 May 2008 04:27:34 +0000 Subject: [PATCH] - 24-bit color .ICO/.CUR files can now be read. --- Changes | 2 ++ ICO/imicon.c | 6 ++-- ICO/msicon.c | 70 +++++++++++++++++++++++++++++++++++++++- ICO/t/t10icon.t | 12 ++++++- ICO/testimg/rgb1616.ico | Bin 0 -> 894 bytes 5 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 ICO/testimg/rgb1616.ico diff --git a/Changes b/Changes index 3c7bfa7e..eb594048 100644 --- 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 diff --git a/ICO/imicon.c b/ICO/imicon.c index c132f68a..2246592c 100644 --- a/ICO/imicon.c +++ b/ICO/imicon.c @@ -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; diff --git a/ICO/msicon.c b/ICO/msicon.c index e8e2d89b..0b878be2 100644 --- a/ICO/msicon.c +++ b/ICO/msicon.c @@ -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 diff --git a/ICO/t/t10icon.t b/ICO/t/t10icon.t index bd2d4fe5..707bc4b8 100644 --- a/ICO/t/t10icon.t +++ b/ICO/t/t10icon.t @@ -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 index 0000000000000000000000000000000000000000..59bfe2af5d5d339fc2fd7ed19354394506a70514 GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?x!0%^v^qi8e)Mr;T$FwAkJ1OotV C9@_o@ literal 0 HcmV?d00001 -- 2.39.5