Commit | Line | Data |
---|---|---|
faa9b3e7 | 1 | #!perl -w |
66614d6e TC |
2 | use strict; |
3 | use lib 't'; | |
2691d220 | 4 | use Test::More tests => 101; |
b89b3153 | 5 | use Imager qw(:all); |
4c2d6970 TC |
6 | $^W=1; # warnings during command-line tests |
7 | $|=1; # give us some progress in the test harness | |
e2cb7e23 | 8 | init_log("testout/t106tiff.log",1); |
b89b3153 | 9 | |
66614d6e TC |
10 | my $green=i_color_new(0,255,0,255); |
11 | my $blue=i_color_new(0,0,255,255); | |
12 | my $red=i_color_new(255,0,0,255); | |
b89b3153 | 13 | |
66614d6e | 14 | my $img=Imager::ImgRaw::new(150,150,3); |
b89b3153 TC |
15 | |
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]); | |
20 | ||
21 | my $timg = Imager::ImgRaw::new(20, 20, 4); | |
22 | my $trans = i_color_new(255, 0, 0, 127); | |
23 | i_box_filled($timg, 0, 0, 20, 20, $green); | |
24 | i_box_filled($timg, 2, 2, 18, 18, $trans); | |
25 | ||
66614d6e TC |
26 | SKIP: |
27 | { | |
28 | unless (i_has_format("tiff")) { | |
29 | my $im = Imager->new; | |
30 | ok(!$im->read(file=>"testimg/comp4.tif"), "should fail to read tif"); | |
31 | is($im->errstr, "format 'tiff' not supported", "check no tiff message"); | |
32 | $im = Imager->new(xsize=>2, ysize=>2); | |
33 | ok(!$im->write(file=>"testout/notiff.tif"), "should fail to write tiff"); | |
34 | is($im->errstr, 'format not supported', "check no tiff message"); | |
2691d220 | 35 | skip("no tiff support", 97); |
99616a52 | 36 | } |
66614d6e | 37 | |
faa9b3e7 TC |
38 | Imager::i_tags_add($img, "i_xres", 0, "300", 0); |
39 | Imager::i_tags_add($img, "i_yres", 0, undef, 250); | |
40 | # resolutionunit is centimeters | |
41 | Imager::i_tags_add($img, "tiff_resolutionunit", 0, undef, 3); | |
fd9a31d2 | 42 | Imager::i_tags_add($img, "tiff_software", 0, "t106tiff.t", 0); |
5c829fcf | 43 | open(FH,">testout/t106.tiff") || die "cannot open testout/t106.tiff for writing\n"; |
b89b3153 TC |
44 | binmode(FH); |
45 | my $IO = Imager::io_new_fd(fileno(FH)); | |
66614d6e | 46 | ok(i_writetiff_wiol($img, $IO), "write low level"); |
b89b3153 TC |
47 | close(FH); |
48 | ||
e2cb7e23 | 49 | open(FH,"testout/t106.tiff") or die "cannot open testout/t106.tiff\n"; |
b89b3153 TC |
50 | binmode(FH); |
51 | $IO = Imager::io_new_fd(fileno(FH)); | |
66614d6e TC |
52 | my $cmpimg = i_readtiff_wiol($IO, -1); |
53 | ok($cmpimg, "read low-level"); | |
b89b3153 TC |
54 | |
55 | close(FH); | |
56 | ||
57 | print "# tiff average mean square pixel difference: ",sqrt(i_img_diff($img,$cmpimg))/150*150,"\n"; | |
b89b3153 | 58 | |
66614d6e | 59 | ok(!i_img_diff($img, $cmpimg), "compare written and read image"); |
4c2d6970 | 60 | |
faa9b3e7 TC |
61 | # check the tags are ok |
62 | my %tags = map { Imager::i_tags_get($cmpimg, $_) } | |
63 | 0 .. Imager::i_tags_count($cmpimg) - 1; | |
66614d6e TC |
64 | ok(abs($tags{i_xres} - 300) < 0.5, "i_xres in range"); |
65 | ok(abs($tags{i_yres} - 250) < 0.5, "i_yres in range"); | |
66 | is($tags{tiff_resolutionunit}, 3, "tiff_resolutionunit"); | |
67 | is($tags{tiff_software}, 't106tiff.t', "tiff_software"); | |
f00e06a0 TC |
68 | is($tags{tiff_photometric}, 2, "tiff_photometric"); # PHOTOMETRIC_RGB is 2 |
69 | is($tags{tiff_bitspersample}, 8, "tiff_bitspersample"); | |
faa9b3e7 | 70 | |
b89b3153 TC |
71 | $IO = Imager::io_new_bufchain(); |
72 | ||
66614d6e | 73 | ok(Imager::i_writetiff_wiol($img, $IO), "write to buffer chain"); |
b89b3153 TC |
74 | my $tiffdata = Imager::io_slurp($IO); |
75 | ||
e2cb7e23 | 76 | open(FH,"testout/t106.tiff"); |
607b851c | 77 | binmode FH; |
b89b3153 TC |
78 | my $odata; |
79 | { local $/; | |
80 | $odata = <FH>; | |
81 | } | |
82 | ||
66614d6e | 83 | is($odata, $tiffdata, "same data in file as in memory"); |
d2dfdcc9 TC |
84 | |
85 | # test Micksa's tiff writer | |
86 | # a shortish fax page | |
87 | my $faximg = Imager::ImgRaw::new(1728, 2000, 1); | |
88 | my $black = i_color_new(0,0,0,255); | |
89 | my $white = i_color_new(255,255,255,255); | |
90 | # vaguely test-patterny | |
91 | i_box_filled($faximg, 0, 0, 1728, 2000, $white); | |
92 | i_box_filled($faximg, 100,100,1628, 200, $black); | |
93 | my $width = 1; | |
94 | my $pos = 100; | |
95 | while ($width+$pos < 1628) { | |
96 | i_box_filled($faximg, $pos, 300, $pos+$width-1, 400, $black); | |
97 | $pos += $width + 20; | |
98 | $width += 2; | |
99 | } | |
100 | open FH, "> testout/t106tiff_fax.tiff" | |
101 | or die "Cannot create testout/t106tiff_fax.tiff: $!"; | |
102 | binmode FH; | |
103 | $IO = Imager::io_new_fd(fileno(FH)); | |
66614d6e | 104 | ok(i_writetiff_wiol_faxable($faximg, $IO, 1), "write faxable, low level"); |
d2dfdcc9 | 105 | close FH; |
4c2d6970 TC |
106 | |
107 | # test the OO interface | |
108 | my $ooim = Imager->new; | |
66614d6e TC |
109 | ok($ooim->read(file=>'testout/t106.tiff'), "read OO"); |
110 | ok($ooim->write(file=>'testout/t106_oo.tiff'), "write OO"); | |
4c2d6970 TC |
111 | |
112 | # OO with the fax image | |
113 | my $oofim = Imager->new; | |
66614d6e TC |
114 | ok($oofim->read(file=>'testout/t106tiff_fax.tiff'), |
115 | "read fax OO"); | |
faa9b3e7 TC |
116 | |
117 | # this should have tags set for the resolution | |
118 | %tags = map @$_, $oofim->tags; | |
66614d6e TC |
119 | is($tags{i_xres}, 204, "fax i_xres"); |
120 | is($tags{i_yres}, 196, "fax i_yres"); | |
121 | ok(!$tags{i_aspect_only}, "i_aspect_only"); | |
faa9b3e7 | 122 | # resunit_inches |
66614d6e | 123 | is($tags{tiff_resolutionunit}, 2, "tiff_resolutionunit"); |
f00e06a0 TC |
124 | is($tags{tiff_bitspersample}, 1, "tiff_bitspersample"); |
125 | is($tags{tiff_photometric}, 1, "tiff_photometric"); | |
faa9b3e7 | 126 | |
66614d6e TC |
127 | ok($oofim->write(file=>'testout/t106_oo_fax.tiff', class=>'fax'), |
128 | "write OO, faxable"); | |
4c2d6970 TC |
129 | |
130 | # the following should fail since there's no type and no filename | |
131 | my $oodata; | |
66614d6e | 132 | ok(!$ooim->write(data=>\$oodata), "write with no type and no filename to guess with"); |
4c2d6970 TC |
133 | |
134 | # OO to data | |
66614d6e TC |
135 | ok($ooim->write(data=>\$oodata, type=>'tiff'), "write to data") |
136 | or print "# ",$ooim->errstr, "\n"; | |
137 | is($oodata, $tiffdata, "check data matches between memory and file"); | |
4c2d6970 TC |
138 | |
139 | # make sure we can write non-fine mode | |
66614d6e | 140 | ok($oofim->write(file=>'testout/t106_oo_faxlo.tiff', class=>'fax', fax_fine=>0), "write OO, fax standard mode"); |
5bb828f1 TC |
141 | |
142 | # paletted reads | |
143 | my $img4 = Imager->new; | |
5bb828f1 TC |
144 | ok($img4->read(file=>'testimg/comp4.tif'), "reading 4-bit paletted"); |
145 | ok($img4->type eq 'paletted', "image isn't paletted"); | |
146 | print "# colors: ", $img4->colorcount,"\n"; | |
147 | ok($img4->colorcount <= 16, "more than 16 colors!"); | |
148 | #ok($img4->write(file=>'testout/t106_was4.ppm'), | |
149 | # "Cannot write img4"); | |
150 | # I know I'm using BMP before it's test, but comp4.tif started life | |
151 | # as comp4.bmp | |
152 | my $bmp4 = Imager->new; | |
153 | ok($bmp4->read(file=>'testimg/comp4.bmp'), "reading 4-bit bmp!"); | |
66614d6e | 154 | my $diff = i_img_diff($img4->{IMG}, $bmp4->{IMG}); |
5bb828f1 TC |
155 | print "# diff $diff\n"; |
156 | ok($diff == 0, "image mismatch"); | |
157 | my $img8 = Imager->new; | |
158 | ok($img8->read(file=>'testimg/comp8.tif'), "reading 8-bit paletted"); | |
159 | ok($img8->type eq 'paletted', "image isn't paletted"); | |
160 | print "# colors: ", $img8->colorcount,"\n"; | |
161 | #ok($img8->write(file=>'testout/t106_was8.ppm'), | |
162 | # "Cannot write img8"); | |
163 | ok($img8->colorcount == 256, "more colors than expected"); | |
164 | my $bmp8 = Imager->new; | |
165 | ok($bmp8->read(file=>'testimg/comp8.bmp'), "reading 8-bit bmp!"); | |
166 | $diff = i_img_diff($img8->{IMG}, $bmp8->{IMG}); | |
167 | print "# diff $diff\n"; | |
168 | ok($diff == 0, "image mismatch"); | |
169 | my $bad = Imager->new; | |
170 | ok($bad->read(file=>'testimg/comp4bad.tif'), "bad image not returned"); | |
171 | ok(scalar $bad->tags(name=>'i_incomplete'), "incomplete tag not set"); | |
f62b2d84 | 172 | ok($img8->write(file=>'testout/t106_pal8.tif'), "writing 8-bit paletted"); |
230e675b TC |
173 | my $cmp8 = Imager->new; |
174 | ok($cmp8->read(file=>'testout/t106_pal8.tif'), | |
f62b2d84 | 175 | "reading 8-bit paletted"); |
230e675b | 176 | #print "# ",$cmp8->errstr,"\n"; |
f62b2d84 TC |
177 | ok($cmp8->type eq 'paletted', "pal8 isn't paletted"); |
178 | ok($cmp8->colorcount == 256, "pal8 bad colorcount"); | |
179 | $diff = i_img_diff($img8->{IMG}, $cmp8->{IMG}); | |
180 | print "# diff $diff\n"; | |
181 | ok($diff == 0, "written image doesn't match read"); | |
182 | ok($img4->write(file=>'testout/t106_pal4.tif'), "writing 4-bit paletted"); | |
183 | ok(my $cmp4 = Imager->new->read(file=>'testout/t106_pal4.tif'), | |
184 | "reading 4-bit paletted"); | |
185 | ok($cmp4->type eq 'paletted', "pal4 isn't paletted"); | |
186 | ok($cmp4->colorcount == 16, "pal4 bad colorcount"); | |
187 | $diff = i_img_diff($img4->{IMG}, $cmp4->{IMG}); | |
188 | print "# diff $diff\n"; | |
189 | ok($diff == 0, "written image doesn't match read"); | |
10461f9a TC |
190 | |
191 | my $work; | |
192 | my $seekpos; | |
193 | sub io_writer { | |
194 | my ($what) = @_; | |
195 | if ($seekpos > length $work) { | |
196 | $work .= "\0" x ($seekpos - length $work); | |
197 | } | |
198 | substr($work, $seekpos, length $what) = $what; | |
199 | $seekpos += length $what; | |
200 | ||
201 | 1; | |
202 | } | |
203 | sub io_reader { | |
204 | my ($size, $maxread) = @_; | |
205 | #print "io_reader($size, $maxread) pos $seekpos\n"; | |
206 | my $out = substr($work, $seekpos, $maxread); | |
207 | $seekpos += length $out; | |
208 | $out; | |
209 | } | |
210 | sub io_reader2 { | |
211 | my ($size, $maxread) = @_; | |
212 | #print "io_reader2($size, $maxread) pos $seekpos\n"; | |
213 | my $out = substr($work, $seekpos, $size); | |
214 | $seekpos += length $out; | |
215 | $out; | |
216 | } | |
217 | use IO::Seekable; | |
218 | sub io_seeker { | |
219 | my ($offset, $whence) = @_; | |
220 | #print "io_seeker($offset, $whence)\n"; | |
221 | if ($whence == SEEK_SET) { | |
222 | $seekpos = $offset; | |
223 | } | |
224 | elsif ($whence == SEEK_CUR) { | |
225 | $seekpos += $offset; | |
226 | } | |
227 | else { # SEEK_END | |
228 | $seekpos = length($work) + $offset; | |
229 | } | |
230 | #print "-> $seekpos\n"; | |
231 | $seekpos; | |
232 | } | |
233 | my $did_close; | |
234 | sub io_closer { | |
235 | ++$did_close; | |
236 | } | |
237 | ||
238 | # read via cb | |
239 | $work = $tiffdata; | |
240 | $seekpos = 0; | |
241 | my $IO2 = Imager::io_new_cb(undef, \&io_reader, \&io_seeker, undef); | |
242 | ok($IO2, "new readcb obj"); | |
243 | my $img5 = i_readtiff_wiol($IO2, -1); | |
244 | ok($img5, "read via cb"); | |
245 | ok(i_img_diff($img5, $img) == 0, "read from cb diff"); | |
246 | ||
247 | # read via cb2 | |
248 | $work = $tiffdata; | |
249 | $seekpos = 0; | |
250 | my $IO3 = Imager::io_new_cb(undef, \&io_reader2, \&io_seeker, undef); | |
251 | ok($IO3, "new readcb2 obj"); | |
252 | my $img6 = i_readtiff_wiol($IO3, -1); | |
253 | ok($img6, "read via cb2"); | |
254 | ok(i_img_diff($img6, $img) == 0, "read from cb2 diff"); | |
255 | ||
256 | # write via cb | |
257 | $work = ''; | |
258 | $seekpos = 0; | |
259 | my $IO4 = Imager::io_new_cb(\&io_writer, \&io_reader, \&io_seeker, | |
260 | \&io_closer); | |
261 | ok($IO4, "new writecb obj"); | |
262 | ok(i_writetiff_wiol($img, $IO4), "write to cb"); | |
263 | ok($work eq $odata, "write cb match"); | |
264 | ok($did_close, "write cb did close"); | |
332033c5 | 265 | open D1, ">testout/d1.tiff" or die; |
10461f9a TC |
266 | print D1 $work; |
267 | close D1; | |
332033c5 | 268 | open D2, ">testout/d2.tiff" or die; |
10461f9a TC |
269 | print D2 $tiffdata; |
270 | close D2; | |
271 | ||
272 | # write via cb2 | |
273 | $work = ''; | |
274 | $seekpos = 0; | |
275 | $did_close = 0; | |
276 | my $IO5 = Imager::io_new_cb(\&io_writer, \&io_reader, \&io_seeker, | |
277 | \&io_closer, 1); | |
278 | ok($IO5, "new writecb obj 2"); | |
279 | ok(i_writetiff_wiol($img, $IO5), "write to cb2"); | |
280 | ok($work eq $odata, "write cb2 match"); | |
281 | ok($did_close, "write cb2 did close"); | |
282 | ||
332033c5 | 283 | open D3, ">testout/d3.tiff" or die; |
10461f9a TC |
284 | print D3 $work; |
285 | close D3; | |
286 | ||
287 | # multi-image write/read | |
288 | my @imgs; | |
289 | push(@imgs, map $ooim->copy(), 1..3); | |
290 | for my $i (0..$#imgs) { | |
291 | $imgs[$i]->addtag(name=>"tiff_pagename", value=>"Page ".($i+1)); | |
292 | } | |
293 | my $rc = Imager->write_multi({file=>'testout/t106_multi.tif'}, @imgs); | |
294 | ok($rc, "writing multiple images to tiff"); | |
295 | my @out = Imager->read_multi(file=>'testout/t106_multi.tif'); | |
296 | ok(@out == @imgs, "reading multiple images from tiff"); | |
297 | @out == @imgs or print "# ",scalar @out, " ",Imager->errstr,"\n"; | |
298 | for my $i (0..$#imgs) { | |
299 | ok(i_img_diff($imgs[$i]{IMG}, $out[$i]{IMG}) == 0, | |
300 | "comparing image $i"); | |
301 | my ($tag) = $out[$i]->tags(name=>'tiff_pagename'); | |
302 | ok($tag eq "Page ".($i+1), | |
303 | "tag doesn't match original image"); | |
304 | } | |
305 | ||
be371490 TC |
306 | # writing even more images to tiff - we weren't handling more than five |
307 | # correctly on read | |
308 | @imgs = map $ooim->copy(), 1..40; | |
0cb68c19 | 309 | $rc = Imager->write_multi({file=>'testout/t106_multi2.tif'}, @imgs); |
be371490 TC |
310 | ok($rc, "writing 40 images to tiff"); |
311 | @out = Imager->read_multi(file=>'testout/t106_multi2.tif'); | |
312 | ok(@imgs == @out, "reading 40 images from tiff"); | |
313 | # force some allocation activity - helps crash here if it's the problem | |
314 | @out = @imgs = (); | |
315 | ||
10461f9a TC |
316 | # multi-image fax files |
317 | ok(Imager->write_multi({file=>'testout/t106_faxmulti.tiff', class=>'fax'}, | |
318 | $oofim, $oofim), "write multi fax image"); | |
319 | @imgs = Imager->read_multi(file=>'testout/t106_faxmulti.tiff'); | |
320 | ok(@imgs == 2, "reading multipage fax"); | |
321 | ok(Imager::i_img_diff($imgs[0]{IMG}, $oofim->{IMG}) == 0, | |
322 | "compare first fax image"); | |
323 | ok(Imager::i_img_diff($imgs[1]{IMG}, $oofim->{IMG}) == 0, | |
324 | "compare second fax image"); | |
8c3af7b3 TC |
325 | |
326 | my ($format) = $imgs[0]->tags(name=>'i_format'); | |
327 | ok(defined $format && $format eq 'tiff', "check i_format tag"); | |
ffeb4a67 | 328 | |
3cff89e2 TC |
329 | my $unit = $imgs[0]->tags(name=>'tiff_resolutionunit'); |
330 | ok(defined $unit && $unit == 2, "check tiff_resolutionunit tag"); | |
331 | my $unitname = $imgs[0]->tags(name=>'tiff_resolutionunit_name'); | |
332 | ok(defined $unitname && $unitname eq 'inch', | |
333 | "check tiff_resolutionunit_name tag"); | |
334 | ||
ffeb4a67 TC |
335 | my $warned = Imager->new; |
336 | ok($warned->read(file=>"testimg/tiffwarn.tif"), "read tiffwarn.tif"); | |
337 | my ($warning) = $warned->tags(name=>'i_warning'); | |
338 | ok(defined $warning && $warning =~ /unknown field with tag 28712/, | |
339 | "check that warning tag set and correct"); | |
8f8bd9aa TC |
340 | |
341 | { # support for reading a given page | |
342 | # first build a simple test image | |
343 | my $im1 = Imager->new(xsize=>50, ysize=>50); | |
344 | $im1->box(filled=>1, color=>$blue); | |
345 | $im1->addtag(name=>'tiff_pagename', value => "Page One"); | |
346 | my $im2 = Imager->new(xsize=>60, ysize=>60); | |
347 | $im2->box(filled=>1, color=>$green); | |
348 | $im2->addtag(name=>'tiff_pagename', value=>"Page Two"); | |
349 | ||
350 | # read second page | |
351 | my $page_file = 'testout/t106_pages.tif'; | |
352 | ok(Imager->write_multi({ file=> $page_file}, $im1, $im2), | |
353 | "build simple multiimage for page tests"); | |
354 | my $imwork = Imager->new; | |
355 | ok($imwork->read(file=>$page_file, page=>1), | |
356 | "read second page"); | |
357 | is($im2->getwidth, $imwork->getwidth, "check width"); | |
358 | is($im2->getwidth, $imwork->getheight, "check height"); | |
359 | is(i_img_diff($imwork->{IMG}, $im2->{IMG}), 0, | |
360 | "check image content"); | |
361 | my ($page_name) = $imwork->tags(name=>'tiff_pagename'); | |
362 | is($page_name, 'Page Two', "check tag we set"); | |
363 | ||
364 | # try an out of range page | |
365 | ok(!$imwork->read(file=>$page_file, page=>2), | |
366 | "check out of range page"); | |
367 | is($imwork->errstr, "could not switch to page 2", "check message"); | |
368 | } | |
2691d220 TC |
369 | |
370 | { # test writing returns an error message correctly | |
371 | # open a file read only and try to write to it | |
372 | open TIFF, "> testout/t106_empty.tif" or die; | |
373 | close TIFF; | |
374 | open TIFF, "< testout/t106_empty.tif" | |
375 | or skip "Cannot open testout/t106_empty.tif for reading", 8; | |
376 | binmode TIFF; | |
377 | my $im = Imager->new(xsize=>100, ysize=>100); | |
378 | ok(!$im->write(fh => \*TIFF, type=>'tiff'), | |
379 | "fail to write to read only handle"); | |
380 | cmp_ok($im->errstr, '=~', 'Could not create TIFF object: Error writing TIFF header: write\(\)', | |
381 | "check error message"); | |
382 | ok(!Imager->write_multi({ type => 'tiff', fh => \*TIFF }, $im), | |
383 | "fail to write multi to read only handle"); | |
384 | cmp_ok(Imager->errstr, '=~', 'Could not create TIFF object: Error writing TIFF header: write\(\)', | |
385 | "check error message"); | |
386 | ok(!$im->write(fh => \*TIFF, type=>'tiff', class=>'fax'), | |
387 | "fail to write to read only handle (fax)"); | |
388 | cmp_ok($im->errstr, '=~', 'Could not create TIFF object: Error writing TIFF header: write\(\)', | |
389 | "check error message"); | |
390 | ok(!Imager->write_multi({ type => 'tiff', fh => \*TIFF, class=>'fax' }, $im), | |
391 | "fail to write multi to read only handle (fax)"); | |
392 | cmp_ok(Imager->errstr, '=~', 'Could not create TIFF object: Error writing TIFF header: write\(\)', | |
393 | "check error message"); | |
394 | } | |
395 | ||
396 | { # test reading returns an error correctly - use test script as an | |
397 | # invalid TIFF file | |
398 | my $im = Imager->new; | |
399 | ok(!$im->read(file=>'t/t106tiff.t', type=>'tiff'), | |
400 | "fail to read script as image"); | |
401 | is($im->errstr, | |
402 | "Error opening file: Not a TIFF file, bad magic number 8483 (0x2123)", | |
403 | "check error message"); | |
404 | my @ims = Imager->read_multi(file =>'t/t106tiff.t', type=>'tiff'); | |
405 | ok(!@ims, "fail to read_multi script as image"); | |
406 | is($im->errstr, | |
407 | "Error opening file: Not a TIFF file, bad magic number 8483 (0x2123)", | |
408 | "check error message"); | |
409 | } | |
b89b3153 | 410 | } |