From: Tony Cook Date: Sat, 8 Nov 2014 02:41:29 +0000 (+1100) Subject: [RT #99507] don't apply the icon mask to images with an alpha channel X-Git-Tag: v1.001~11 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/f17a0a60401911645f605c88d76fdf70891bf692 [RT #99507] don't apply the icon mask to images with an alpha channel but do it if the caller asks nicely --- diff --git a/ICO/ICO.pm b/ICO/ICO.pm index 2bc85306..aeffd79d 100644 --- a/ICO/ICO.pm +++ b/ICO/ICO.pm @@ -4,7 +4,7 @@ use Imager; use vars qw($VERSION @ISA); BEGIN { - $VERSION = "0.03"; + $VERSION = "0.04"; require XSLoader; XSLoader::load('Imager::File::ICO', $VERSION); @@ -18,7 +18,11 @@ Imager->register_reader my ($im, $io, %hsh) = @_; my $masked = exists $hsh{ico_masked} ? $hsh{ico_masked} : 1; - $im->{IMG} = i_readico_single($io, $hsh{page} || 0, $masked); + my $alpha_masked = + exists $hsh{ico_alpha_masked} ? $hsh{ico_alpha_masked} : 0; + + $im->{IMG} = i_readico_single($io, $hsh{page} || 0, $masked, + $alpha_masked); unless ($im->{IMG}) { $im->_set_error(Imager->_error_as_msg); @@ -52,7 +56,10 @@ Imager->register_reader my ($im, $io, %hsh) = @_; my $masked = exists $hsh{ico_masked} ? $hsh{ico_masked} : 1; - $im->{IMG} = i_readico_single($io, $hsh{page} || 0, $masked); + my $alpha_masked = + exists $hsh{ico_alpha_masked} ? $hsh{ico_alpha_masked} : 0; + $im->{IMG} = i_readico_single($io, $hsh{page} || 0, $masked, + $alpha_masked); unless ($im->{IMG}) { $im->_set_error(Imager->_error_as_msg); diff --git a/ICO/ICO.xs b/ICO/ICO.xs index 333c6fbb..3a155656 100644 --- a/ICO/ICO.xs +++ b/ICO/ICO.xs @@ -14,21 +14,23 @@ MODULE = Imager::File::ICO PACKAGE = Imager::File::ICO PROTOTYPES: DISABLE Imager::ImgRaw -i_readico_single(ig, index, masked = 0) +i_readico_single(ig, index, masked = 0, alpha_masked = 0) Imager::IO ig int index bool masked + bool alpha_masked void -i_readico_multi(ig, masked = 0) +i_readico_multi(ig, masked = 0, alpha_masked = 0) Imager::IO ig bool masked + bool alpha_masked PREINIT: i_img **imgs; int count; int i; PPCODE: - imgs = i_readico_multi(ig, &count, masked); + imgs = i_readico_multi(ig, &count, masked, alpha_masked); if (imgs) { EXTEND(SP, count); for (i = 0; i < count; ++i) { diff --git a/ICO/imicon.c b/ICO/imicon.c index cb622cf6..529610d7 100644 --- a/ICO/imicon.c +++ b/ICO/imicon.c @@ -13,7 +13,7 @@ ico_push_error(int error) { static i_img * -read_one_icon(ico_reader_t *file, int index, int masked) { +read_one_icon(ico_reader_t *file, int index, int masked, int alpha_masked) { ico_image_t *image; int error; i_img *result; @@ -25,7 +25,7 @@ read_one_icon(ico_reader_t *file, int index, int masked) { return NULL; } - if (masked) { + if (masked && (image->bit_count != 32 || alpha_masked)) { /* check to make sure we should do the masking, if the mask has nothing set we don't mask */ int pos; @@ -195,7 +195,7 @@ read_one_icon(ico_reader_t *file, int index, int masked) { } i_img * -i_readico_single(io_glue *ig, int index, int masked) { +i_readico_single(io_glue *ig, int index, int masked, int alpha_masked) { ico_reader_t *file; i_img *result; int error; @@ -211,14 +211,14 @@ i_readico_single(io_glue *ig, int index, int masked) { /* the index is range checked by msicon.c - don't duplicate it here */ - result = read_one_icon(file, index, masked); + result = read_one_icon(file, index, masked, alpha_masked); ico_reader_close(file); return result; } i_img ** -i_readico_multi(io_glue *ig, int *count, int masked) { +i_readico_multi(io_glue *ig, int *count, int masked, int alpha_masked) { ico_reader_t *file; int index; int error; @@ -237,7 +237,7 @@ i_readico_multi(io_glue *ig, int *count, int masked) { *count = 0; for (index = 0; index < ico_image_count(file); ++index) { - i_img *im = read_one_icon(file, index, masked); + i_img *im = read_one_icon(file, index, masked, alpha_masked); if (!im) break; diff --git a/ICO/imicon.h b/ICO/imicon.h index 7e26f4a8..114d3307 100644 --- a/ICO/imicon.h +++ b/ICO/imicon.h @@ -4,9 +4,9 @@ #include "imext.h" extern i_img * -i_readico_single(io_glue *ig, int index, int masked); +i_readico_single(io_glue *ig, int index, int masked, int alpha_masked); extern i_img ** -i_readico_multi(io_glue *ig, int *count, int masked); +i_readico_multi(io_glue *ig, int *count, int masked, int alpha_masked); extern int i_writeico_wiol(i_io_glue_t *ig, i_img *im); diff --git a/ICO/t/t10icon.t b/ICO/t/t10icon.t index 454a4625..2c08c357 100644 --- a/ICO/t/t10icon.t +++ b/ICO/t/t10icon.t @@ -1,7 +1,7 @@ #!perl -w use strict; -use Test::More tests => 106; -use Imager::Test qw(is_image test_image); +use Test::More tests => 111; +use Imager::Test qw(is_image isnt_image test_image); BEGIN { use_ok('Imager::File::ICO'); } @@ -415,3 +415,26 @@ EOS } } +{ # RT #99507 + # we now ignore the mask by default when reading a 32-bit image + my $im = Imager->new(xsize => 2, ysize => 2, channels => 4); + $im->setpixel(x => 0, y => 0, color => "#FF0000"); + $im->setpixel(x => 1, y => 1, color => "#00FF00"); + my $mask = <write(data => \$data, + type => "ico", + ico_mask => $mask), "write with dodgy mask"); + my $im2 = Imager->new(data => \$data, filetype => "ico"); + ok($im2, "read it back"); + is_image($im2, $im, "should match original, despite bad mask"); + my $im3 = Imager->new(data => \$data, filetype => "ico", ico_alpha_masked => 1); + ok($im3, "read it back with ico_alpha_masked => 1"); + my $cmp = $im->copy; + $cmp->setpixel(x => 0, y => 0, color => [ 255, 0, 0, 0 ]); + isnt_image($im3, $cmp, "bad mask makes some pixels transparent"); +} diff --git a/lib/Imager/Files.pod b/lib/Imager/Files.pod index 243fe752..7b9a0c8a 100644 --- a/lib/Imager/Files.pod +++ b/lib/Imager/Files.pod @@ -1613,9 +1613,10 @@ control reading of ICO/CUR files: =item * -ico_masked - if true, the default, then the icon/cursors mask is -applied as an alpha channel to the image. This may result in a -paletted image being returned as a direct color image. Default: 1 +C - if true, the default, then the icon/cursors mask is +applied as an alpha channel to the image, unless that image already +has an alpha channel. This may result in a paletted image being +returned as a direct color image. Default: 1 # retrieve the image as stored, without using the mask as an alpha # channel @@ -1625,6 +1626,15 @@ paletted image being returned as a direct color image. Default: 1 This was introduced in Imager 0.60. Previously reading ICO images acted as if C 0>. +=item * + +C - if true, then the icon/cursor mask is applied as +an alpha channel to images that already have an alpha mask. Note that +this will only make pixels transparent, not opaque. Default: 0. + +Note: If you get different results between C being +set to 0 and 1, your mask may broke when used with the Win32 API. + =back C is set when reading a cursor.