#!perl -w use strict; use Test::More tests => 100; use Imager::Test qw(is_image); BEGIN { use_ok('Imager::File::ICO'); } -d 'testout' or mkdir 'testout', 0777; my $im = Imager->new; # type=>'ico' or 'cur' and read ico and cur since they're pretty much # the same ok($im->read(file => "testimg/rgba3232.ico", type=>"ico", ico_masked => 0), "read 32 bit") or print "# ", $im->errstr, "\n"; is($im->getwidth, 32, "check width"); is($im->getwidth, 32, "check height"); is($im->type, 'direct', "check type"); is($im->tags(name => 'ico_bits'), 32, "check ico_bits tag"); is($im->tags(name => 'i_format'), 'ico', "check i_format tag"); my $mask = '.* ..........................****** ..........................****** ..........................****** ..........................****** ...........................***** ............................**** ............................**** .............................*** .............................*** .............................*** .............................*** ..............................** ..............................** ...............................* ...............................* ................................ ................................ ................................ ................................ ................................ ................................ *............................... **.............................. **.............................. ***............................. ***............................. ****............................ ****............................ *****........................... *****........................... *****........................... *****...........................'; is($im->tags(name => 'ico_mask'), $mask, "check ico_mask_tag"); # compare the pixels # ppm can't store 4 channels SKIP: { my $work = $im->convert(preset=>'noalpha'); my $comp = Imager->new; $comp->read(file => "testimg/rgba3232.ppm") or skip "could not read 24-bit comparison file:". $comp->errstr, 1; is(Imager::i_img_diff($comp->{IMG}, $work->{IMG}), 0, "compare image data"); } ok($im->read(file => 'testimg/pal83232.ico', type=>'ico', ico_masked => 0), "read 8 bit") or print "# ", $im->errstr, "\n"; is($im->getwidth, 32, "check width"); is($im->getwidth, 32, "check height"); is($im->type, 'paletted', "check type"); is($im->colorcount, 256, "color count"); is($im->tags(name => 'ico_bits'), 8, "check ico_bits tag"); is($im->tags(name => 'i_format'), 'ico', "check i_format tag"); SKIP: { my $comp = Imager->new; $comp->read(file => "testimg/pal83232.ppm") or skip "could not read 8-bit comparison file:". $comp->errstr, 1; is(Imager::i_img_diff($comp->{IMG}, $im->{IMG}), 0, "compare image data"); } $im->write(file=>'testout/pal83232.ppm'); ok($im->read(file => 'testimg/pal43232.ico', type=>'ico', ico_masked => 0), "read 4 bit") or print "# ", $im->errstr, "\n"; is($im->getwidth, 32, "check width"); is($im->getwidth, 32, "check height"); is($im->type, 'paletted', "check type"); is($im->colorcount, 16, "color count"); is($im->tags(name => 'ico_bits'), 4, "check ico_bits tag"); is($im->tags(name => 'i_format'), 'ico', "check i_format tag"); SKIP: { my $comp = Imager->new; $comp->read(file => "testimg/pal43232.ppm") or skip "could not read 4-bit comparison file:". $comp->errstr, 1; is(Imager::i_img_diff($comp->{IMG}, $im->{IMG}), 0, "compare image data"); } $im->write(file=>'testout/pal43232.ppm'); ok($im->read(file => 'testimg/pal13232.ico', type=>'ico', ico_masked => 0), "read 1 bit") or print "# ", $im->errstr, "\n"; is($im->getwidth, 32, "check width"); is($im->getwidth, 32, "check height"); is($im->type, 'paletted', "check type"); is($im->colorcount, 2, "color count"); is($im->tags(name => 'cur_bits'), 1, "check ico_bits tag"); is($im->tags(name => 'i_format'), 'cur', "check i_format tag"); $im->write(file=>'testout/pal13232.ppm'); # combo was created with the GIMP, which has a decent mechanism for selecting # the output format # you get different size icon images by making different size layers. my @imgs = Imager->read_multi(file => 'testimg/combo.ico', type=>'ico', ico_masked => 0); is(scalar(@imgs), 3, "read multiple"); is($imgs[0]->getwidth, 48, "image 0 width"); is($imgs[0]->getheight, 48, "image 0 height"); is($imgs[1]->getwidth, 32, "image 1 width"); is($imgs[1]->getheight, 32, "image 1 height"); is($imgs[2]->getwidth, 16, "image 2 width"); is($imgs[2]->getheight, 16, "image 2 height"); is($imgs[0]->type, 'direct', "image 0 type"); is($imgs[1]->type, 'paletted', "image 1 type"); is($imgs[2]->type, 'paletted', "image 2 type"); is($imgs[1]->colorcount, 256, "image 1 colorcount"); is($imgs[2]->colorcount, 16, "image 2 colorcount"); is_deeply([ $imgs[0]->getpixel(x=>0, 'y'=>0)->rgba ], [ 231, 17, 67, 255 ], "check image data 0(0,0)"); is_deeply([ $imgs[1]->getpixel(x=>0, 'y'=>0)->rgba ], [ 231, 17, 67, 255 ], "check image data 1(0,0)"); is_deeply([ $imgs[2]->getpixel(x=>0, 'y'=>0)->rgba ], [ 231, 17, 67, 255 ], "check image data 2(0,0)"); is_deeply([ $imgs[0]->getpixel(x=>47, 'y'=>0)->rgba ], [ 131, 231, 17, 255 ], "check image data 0(47,0)"); is_deeply([ $imgs[1]->getpixel(x=>31, 'y'=>0)->rgba ], [ 131, 231, 17, 255 ], "check image data 1(31,0)"); is_deeply([ $imgs[2]->getpixel(x=>15, 'y'=>0)->rgba ], [ 131, 231, 17, 255 ], "check image data 2(15,0)"); is_deeply([ $imgs[0]->getpixel(x=>0, 'y'=>47)->rgba ], [ 17, 42, 231, 255 ], "check image data 0(0,47)"); is_deeply([ $imgs[1]->getpixel(x=>0, 'y'=>31)->rgba ], [ 17, 42, 231, 255 ], "check image data 1(0,31)"); is_deeply([ $imgs[2]->getpixel(x=>0, 'y'=>15)->rgba ], [ 17, 42, 231, 255 ], "check image data 2(0,15)"); is_deeply([ $imgs[0]->getpixel(x=>47, 'y'=>47)->rgba ], [ 17, 231, 177, 255 ], "check image data 0(47,47)"); is_deeply([ $imgs[1]->getpixel(x=>31, 'y'=>31)->rgba ], [ 17, 231, 177, 255 ], "check image data 1(31,31)"); is_deeply([ $imgs[2]->getpixel(x=>15, 'y'=>15)->rgba ], [ 17, 231, 177, 255 ], "check image data 2(15,15)"); $im = Imager->new(xsize=>32, ysize=>32); $im->box(filled=>1, color=>'FF0000'); $im->box(filled=>1, color=>'0000FF', xmin => 6, ymin=>0, xmax => 21, ymax=>15); $im->box(filled=>1, color=>'00FF00', xmin => 10, ymin=>16, xmax => 25, ymax=>31); ok($im->write(file=>'testout/t10_32.ico', type=>'ico'), "write 32-bit icon"); my $im2 = Imager->new; ok($im2->read(file=>'testout/t10_32.ico', type=>'ico', ico_masked => 0), "read it back in"); is(Imager::i_img_diff($im->{IMG}, $im2->{IMG}), 0, "check they're the same"); is($im->bits, $im2->bits, "check same bits"); { my $im = Imager->new(xsize => 32, ysize => 32); $im->box(filled=>1, color=>'#FF00FF'); my $data; ok(Imager->write_multi({ data => \$data, type=>'ico' }, $im, $im), "write multi icons"); ok(length $data, "and it wrote data"); my @im = Imager->read_multi(data => $data, ico_masked => 0); is(@im, 2, "got all the images back"); is(Imager::i_img_diff($im->{IMG}, $im[0]{IMG}), 0, "check first image"); is(Imager::i_img_diff($im->{IMG}, $im[1]{IMG}), 0, "check second image"); } { # 1 channel image my $im = Imager->new(xsize => 32, ysize => 32, channels => 1); $im->box(filled=>1, color => [ 128, 0, 0 ]); my $data; ok($im->write(data => \$data, type=>'ico'), "write 1 channel image"); my $im2 = Imager->new; ok($im2->read(data => $data, ico_masked => 0), "read it back"); is($im2->getchannels, 4, "check channels"); my $imrgb = $im->convert(preset => 'rgb') ->convert(preset => 'addalpha'); is(Imager::i_img_diff($imrgb->{IMG}, $im2->{IMG}), 0, "check image matches expected"); } { # 2 channel image my $base = Imager->new(xsize => 32, ysize => 32, channels => 2); $base->box(filled => 1, color => [ 64, 192, 0 ]); my $data; ok($base->write(data => \$data, type=>'ico'), "write 2 channel image"); my $read = Imager->new; ok($read->read(data => $data, ico_masked => 0), "read it back"); is($read->getchannels, 4, "check channels"); my $imrgb = $base->convert(preset => 'rgb'); is(Imager::i_img_diff($imrgb->{IMG}, $read->{IMG}), 0, "check image matches expected"); } { # 4 channel image my $base = Imager->new(xsize => 32, ysize => 32, channels => 4); $base->box(filled=>1, ymax => 15, color => [ 255, 0, 255, 128 ]); $base->box(filled=>1, ymin => 16, color => [ 0, 255, 255, 255 ]); my $data; ok($base->write(data => \$data, type=>'ico'), "write 4 channel image"); my $read = Imager->new; ok($read->read(data => $data, type=>'ico', ico_masked => 0), "read it back") or print "# ", $read->errstr, "\n"; is(Imager::i_img_diff($base->{IMG}, $read->{IMG}), 0, "check image matches expected"); } { # mask handling my $base = Imager->new(xsize => 16, ysize => 16, channels => 3); $base->box(filled=>1, xmin => 5, xmax => 10, color => '#0000FF'); $base->box(filled=>1, ymin => 5, ymax => 10, color => '#0000FF'); my $mask = <settag(name => 'ico_mask', value => $mask); my $saved_mask = $base->tags(name => 'ico_mask'); my $data; ok($base->write(data => \$data, type => 'ico'), "write with mask tag set"); my $read = Imager->new; ok($read->read(data => $data, ico_masked => 0), "read it back"); my $mask2 = $mask; $mask2 =~ tr/01/.*/; $mask2 =~ s/\n$//; $mask2 =~ tr/\r x//d; $mask2 =~ s/^(.{3,19})$/$1 . "." x (16 - length $1)/gem; my $read_mask = $read->tags(name => 'ico_mask'); is($read_mask, $mask2, "check mask is correct"); } { # mask too short to handle my $mask = "xx"; my $base = Imager->new(xsize => 16, ysize => 16, channels => 3); $base->box(filled=>1, xmin => 5, xmax => 10, color => '#0000FF'); $base->box(filled=>1, ymin => 5, ymax => 10, color => '#0000FF'); $base->settag(name => 'ico_mask', value => $mask); my $data; ok($base->write(data => \$data, type=>'ico'), "save icon with short mask tag"); my $read = Imager->new; ok($read->read(data => $data, ico_masked => 0), "read it back"); my $read_mask = $read->tags(name => 'ico_mask'); my $expected_mask = ".*" . ( "\n" . "." x 16 ) x 16; is($read_mask, $expected_mask, "check the mask"); # mask that doesn't match what we expect $base->settag(name => 'ico_mask', value => 'abcd'); ok($base->write(data => \$data, type => 'ico'), "write with bad format mask tag"); ok($read->read(data => $data, ico_masked => 0), "read it back"); $read_mask = $read->tags(name => 'ico_mask'); is($read_mask, $expected_mask, "check the mask"); # mask with invalid char $base->settag(name => 'ico_mask', value => ".*\n....xxx.."); ok($base->write(data => \$data, type => 'ico'), "write with unexpected chars in mask"); ok($read->read(data => $data, ico_masked => 0), "read it back"); $read_mask = $read->tags(name => 'ico_mask'); is($read_mask, $expected_mask, "check the mask"); } { # check handling of greyscale paletted my $base = Imager->new(xsize => 16, ysize => 16, channels => 1, type => 'paletted'); my @grays = map Imager::Color->new($_), "000000", "666666", "CCCCCC", "FFFFFF"; ok($base->addcolors(colors => \@grays), "add some colors"); $base->box(filled => 1, color => $grays[1], xmax => 7, ymax => 7); $base->box(filled => 1, color => $grays[1], xmax => 7, ymin => 8); $base->box(filled => 1, color => $grays[1], xmin => 8, ymax => 7); $base->box(filled => 1, color => $grays[1], xmin => 8, ymax => 8); my $data; ok($base->write(data => \$data, type => 'ico'), "write grayscale paletted"); my $read = Imager->new; ok($read->read(data => $data, ico_masked => 0), "read it back") or print "# ", $read->errstr, "\n"; is($read->type, 'paletted', "check type"); is($read->getchannels, 3, "check channels"); my $as_rgb = $base->convert(preset => 'rgb'); is(Imager::i_img_diff($base->{IMG}, $read->{IMG}), 0, "check the image"); } { # check default mask processing # # the query at http://www.cpanforum.com/threads/5958 made it fairly # obvious that the way Imager handled the mask in 0.59 was confusing # when compared with loading other images with some sort of # secondary alpha channel (eg. gif) # So from 0.60 the mask is applied as an alpha channel by default. # make sure that application works. # the strange mask checks the optimization paths of the mask application my $mask = <new(xsize => 4, ysize => 5, type => 'paletted'); $im->addcolors(colors => [ '#FF0000' ]); $im->box(filled => 1, color => '#FF0000'); $im->settag(name => 'ico_mask', value => $mask); my $imcopy = $im->convert(preset=>'addalpha'); my $red_alpha = Imager::Color->new(255, 0, 0, 0); $imcopy->setpixel( 'x' => [ qw/0 3 0 1 2 3 2/ ], 'y' => [ qw/0 0 1 1 2 2 4/ ], color => $red_alpha); my $data; ok($im->write(data => \$data, type => 'ico'), "save icon + mask"); my $im2 = Imager->new; ok($im2->read(data => $data), "read ico with defaults"); 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"); }