5 use Test::More tests => 86;
7 init_log("testout/t101jpeg.log",1);
9 my $green=i_color_new(0,255,0,255);
10 my $blue=i_color_new(0,0,255,255);
11 my $red=i_color_new(255,0,0,255);
13 my $img=Imager::ImgRaw::new(150,150,3);
14 my $cmpimg=Imager::ImgRaw::new(150,150,3);
16 i_box_filled($img,70,25,130,125,$green);
17 i_box_filled($img,20,25,80,125,$blue);
18 i_arc($img,75,75,30,0,361,$red);
19 i_conv($img,[0.1, 0.2, 0.4, 0.2, 0.1]);
21 i_has_format("jpeg") && print "# has jpeg\n";
22 if (!i_has_format("jpeg")) {
23 # previously we'd crash if we tried to save/read an image via the OO
24 # interface when there was no jpeg support
28 ok(!$im->read(file=>"testimg/base.jpg"), "should fail to read jpeg");
29 cmp_ok($im->errstr, '=~', qr/format 'jpeg' not supported/, "check no jpeg message");
30 $im = Imager->new(xsize=>2, ysize=>2);
31 ok(!$im->write(file=>"testout/nojpeg.jpg"), "should fail to write jpeg");
32 cmp_ok($im->errstr, '=~', qr/format not supported/, "check no jpeg message");
33 skip("no jpeg support", 82);
36 open(FH,">testout/t101.jpg") || die "cannot open testout/t101.jpg for writing\n";
38 my $IO = Imager::io_new_fd(fileno(FH));
39 ok(i_writejpeg_wiol($img,$IO,30), "write jpeg low level");
42 open(FH, "testout/t101.jpg") || die "cannot open testout/t101.jpg\n";
44 $IO = Imager::io_new_fd(fileno(FH));
45 ($cmpimg,undef) = i_readjpeg_wiol($IO);
48 my $diff = sqrt(i_img_diff($img,$cmpimg))/150*150;
49 print "# jpeg average mean square pixel difference: ",$diff,"\n";
50 ok($cmpimg, "read jpeg low level");
52 ok($diff < 10000, "difference between original and jpeg within bounds");
54 Imager::i_log_entry("Starting 4\n", 1);
55 my $imoo = Imager->new;
56 ok($imoo->read(file=>'testout/t101.jpg'), "read jpeg OO");
58 ok($imoo->write(file=>'testout/t101_oo.jpg'), "write jpeg OO");
59 Imager::i_log_entry("Starting 5\n", 1);
60 my $oocmp = Imager->new;
61 ok($oocmp->read(file=>'testout/t101_oo.jpg'), "read jpeg OO for comparison");
63 $diff = sqrt(i_img_diff($imoo->{IMG},$oocmp->{IMG}))/150*150;
64 print "# OO image difference $diff\n";
65 ok($diff < 10000, "difference between original and jpeg within bounds");
68 open FH, "< testout/t101.jpg" or die "Cannot open testout/t101.jpg: $!";
70 ok(!$imoo->write(fd=>fileno(FH), type=>'jpeg'), 'failure handling');
72 print "# ",$imoo->errstr,"\n";
74 # check that the i_format tag is set
75 my @fmt = $imoo->tags(name=>'i_format');
76 is($fmt[0], 'jpeg', 'i_format tag');
78 { # check file limits are checked
79 my $limit_file = "testout/t101.jpg";
80 ok(Imager->set_file_limits(reset=>1, width=>149), "set width limit 149");
82 ok(!$im->read(file=>$limit_file),
83 "should fail read due to size limits");
84 print "# ",$im->errstr,"\n";
85 like($im->errstr, qr/image width/, "check message");
87 ok(Imager->set_file_limits(reset=>1, height=>149), "set height limit 149");
88 ok(!$im->read(file=>$limit_file),
89 "should fail read due to size limits");
90 print "# ",$im->errstr,"\n";
91 like($im->errstr, qr/image height/, "check message");
93 ok(Imager->set_file_limits(reset=>1, width=>150), "set width limit 150");
94 ok($im->read(file=>$limit_file),
95 "should succeed - just inside width limit");
96 ok(Imager->set_file_limits(reset=>1, height=>150), "set height limit 150");
97 ok($im->read(file=>$limit_file),
98 "should succeed - just inside height limit");
100 # 150 x 150 x 3 channel image uses 67500 bytes
101 ok(Imager->set_file_limits(reset=>1, bytes=>67499),
102 "set bytes limit 67499");
103 ok(!$im->read(file=>$limit_file),
104 "should fail - too many bytes");
105 print "# ",$im->errstr,"\n";
106 like($im->errstr, qr/storage size/, "check error message");
107 ok(Imager->set_file_limits(reset=>1, bytes=>67500),
108 "set bytes limit 67500");
109 ok($im->read(file=>$limit_file),
110 "should succeed - just inside bytes limit");
111 Imager->set_file_limits(reset=>1);
116 # we don't test them all
119 exif_date_time_original => "2005:11:25 00:00:00",
121 exif_image_description => "Imager Development Notes",
122 exif_make => "Canon",
123 exif_model => "CanoScan LiDE 35",
124 exif_resolution_unit => 2,
125 exif_resolution_unit_name => "inches",
126 exif_user_comment => " Part of notes from reworking i_arc() and friends.",
127 exif_white_balance => 0,
128 exif_white_balance_name => "Auto white balance",
132 Imager::i_exif_enabled()
133 or skip("no exif support", scalar keys %expected_tags);
135 my $im = Imager->new;
136 $im->read(file=>"testimg/exiftest.jpg")
137 or skip("Could not read test image:".$im->errstr, scalar keys %expected_tags);
139 for my $key (keys %expected_tags) {
140 is($expected_tags{$key}, $im->tags(name => $key),
141 "test value of exif tag $key");
146 # tests that the density values are set and read correctly
147 # tests jpeg_comment too
152 jpeg_density_unit => 2,
157 jpeg_density_unit => 2,
160 i_aspect_only => undef,
171 jpeg_density_unit => 1,
172 i_aspect_only => undef,
183 jpeg_density_unit => 1,
184 i_aspect_only => undef,
198 jpeg_density_unit => 0,
204 jpeg_comment => 'test comment'
209 print "# test density tags\n";
210 # I don't care about the content
211 my $base_im = Imager->new(xsize => 10, ysize => 10);
212 for my $test (@density_tests) {
213 my ($filename, $out_tags, $expect_tags) = @$test;
214 $expect_tags ||= $out_tags;
216 my $work = $base_im->copy;
217 for my $key (keys %$out_tags) {
218 $work->addtag(name => $key, value => $out_tags->{$key});
221 ok($work->write(file=>"testout/$filename", type=>'jpeg'),
224 my $check = Imager->new;
225 ok($check->read(file=> "testout/$filename"),
229 for my $key (keys %$expect_tags) {
230 $tags{$key} = $check->tags(name=>$key);
232 is_deeply($expect_tags, \%tags, "check tags for $filename");
237 # the test image has a zero-length user_comment field
238 # the code would originally attempt to convert '\0' to ' '
239 # for the first 8 bytes, even if the string was less than
241 my $im = Imager->new;
242 ok($im->read(file => 'testimg/209_yonge.jpg', type=>'jpeg'),
243 "test read of image with invalid exif_user_comment");
244 is($im->tags(name=>'exif_user_comment'), '',
245 "check exif_user_comment set correctly");
248 { # test parseiptc handling no IPTC data correctly
250 local $SIG{__WARN__} =
255 my $im = Imager->new;
256 ok($im->read(file => 'testout/t101.jpg', type=>'jpeg'),
257 "read jpeg with no IPTC data");
258 ok(!defined $im->{IPTCRAW}, "no iptc data");
259 my %iptc = $im->parseiptc;
260 ok(!$saw_warn, "should be no warnings");
264 # attempting to write a 4 channel image to a bufchain would
266 # it should fail still
267 my $im = Imager->new(xsize => 10, ysize => 10, channels => 4);
269 ok(!$im->write(data => \$data, type => 'jpeg'),
270 "should fail to write but shouldn't crash");
271 is($im->errstr, "only 1 or 3 channels images can be saved as JPEG",
272 "check the error message");
276 # If a jpeg with EXIF data containing an (invalid) IFD entry with a
277 # type of zero is read then Imager crashes with a Floating point
279 # testimg/zerojpeg.jpg was manually modified from exiftest.jpg to
280 # reproduce the problem.
281 Imager::i_exif_enabled()
282 or skip("no exif support", 1);
283 my $im = Imager->new;
284 ok($im->read(file=>'testimg/zerotype.jpg'), "shouldn't crash");
288 { # code coverage - make sure wiol_skip_input_data is called
289 open BASEDATA, "< testimg/exiftest.jpg"
290 or skip "can't open base data", 1;
292 my $data = do { local $/; <BASEDATA> };
295 substr($data, 3, 1) eq "\xE1"
296 or skip "base data isn't as expected", 1;
297 # inserting a lot of marker data here means we take the branch in
298 # wiol_skip_input_data that refills the buffer
299 my $marker = "\xFF\xE9"; # APP9 marker
300 $marker .= pack("n", 8192) . "x" x 8190;
301 $marker x= 10; # make it take up a lot of space
302 substr($data, 2, 0) = $marker;
303 my $im = Imager->new;
304 ok($im->read(data => $data), "read with a skip of data");
308 { # code coverage - take the branch that provides a fake EOI
309 open BASEDATA, "< testimg/exiftest.jpg"
310 or skip "can't open base data", 1;
312 my $data = do { local $/; <BASEDATA> };
314 substr($data, -1000) = '';
316 my $im = Imager->new;
317 ok($im->read(data => $data), "read with image data truncated");
320 { # code coverage - make sure wiol_empty_output_buffer is called
321 my $im = Imager->new(xsize => 1000, ysize => 1000);
322 for my $x (0 .. 999) {
323 $im->line(x1 => $x, y1 => 0, x2 => $x, y2 => 999,
324 color => Imager::Color->new(rand 256, rand 256, rand 256));
327 ok($im->write(data => \$data, type=>'jpeg', jpegquality => 100),
328 "write big file to ensure wiol_empty_output_buffer is called");
330 # code coverage - write failure path in wiol_empty_output_buffer
331 ok(!$im->write(callback => sub { return },
332 type => 'jpeg', jpegquality => 100),
334 and print "# ", $im->errstr, "\n";
337 { # code coverage - virtual image branch in i_writejpeg_wiol()
338 my $im = $imoo->copy;
339 my $immask = $im->masked;
340 ok($immask, "made a virtual image (via masked)");
341 ok($immask->virtual, "check it's virtual");
343 ok($immask->write(data => \$mask_data, type => 'jpeg'),
344 "write masked version");
346 ok($im->write(data => \$base_data, type=>'jpeg'),
347 "write normal version");
348 is($base_data, $mask_data, "check the data written matches");
352 { # code coverage - IPTC data
354 my $iptc = "\x04\x04" .
355 "\034\002x My Caption"
356 . "\034\002P Tony Cook"
357 . "\034\002i Dummy Headline!"
358 . "\034\002n No Credit Given";
360 my $app13 = "\xFF\xED" . pack("n", 2 + length $iptc) . $iptc;
362 open BASEDATA, "< testimg/exiftest.jpg"
363 or skip "can't open base data", 1;
365 my $data = do { local $/; <BASEDATA> };
367 substr($data, 2, 0) = $app13;
369 my $im = Imager->new;
370 ok($im->read(data => $data), "read with app13 data");
371 my %iptc = $im->parseiptc;
372 is($iptc{caption}, 'My Caption', 'check iptc caption');
373 is($iptc{photogr}, 'Tony Cook', 'check iptc photogr');
374 is($iptc{headln}, 'Dummy Headline!', 'check iptc headln');
375 is($iptc{credit}, 'No Credit Given', 'check iptc credit');
378 { # handling of CMYK jpeg
379 # http://rt.cpan.org/Ticket/Display.html?id=20416
380 my $im = Imager->new;
381 ok($im->read(file => 'testimg/scmyk.jpg'), 'read a CMYK jpeg');
382 is($im->getchannels, 3, "check channel count");
383 my $col = $im->getpixel(x => 0, 'y' => 0);
384 ok($col, "got the 'black' pixel");
385 # this is jpeg, so we can't compare colors exactly
386 # older versions returned this pixel at a light color, but
387 # it's black in the image
388 my ($r, $g, $b) = $col->rgba;
389 cmp_ok($r, '<', 10, 'black - red low');
390 cmp_ok($g, '<', 10, 'black - green low');
391 cmp_ok($b, '<', 10, 'black - blue low');
392 $col = $im->getpixel(x => 15, 'y' => 0);
393 ok($col, "got the dark blue");
394 ($r, $g, $b) = $col->rgba;
395 cmp_ok($r, '<', 10, 'dark blue - red low');
396 cmp_ok($g, '<', 10, 'dark blue - green low');
397 cmp_ok($b, '>', 110, 'dark blue - blue middle (bottom)');
398 cmp_ok($b, '<', 130, 'dark blue - blue middle (top)');
399 $col = $im->getpixel(x => 0, 'y' => 15);
400 ok($col, "got the red");
401 ($r, $g, $b) = $col->rgba;
402 cmp_ok($r, '>', 245, 'red - red high');
403 cmp_ok($g, '<', 10, 'red - green low');
404 cmp_ok($b, '<', 10, 'red - blue low');