More debugging for auto probing of image types.
[imager.git] / t / t50basicoo.t
CommitLineData
10461f9a 1#!perl -w
02d1d628
AMH
2######################### We start with some black magic to print on failure.
3
10461f9a
TC
4# this used to do the check for the load of Imager, but I want to be able
5# to count tests, which means I need to load Imager first
6# since many of the early tests already do this, we don't really need to
02d1d628 7
10461f9a 8use strict;
02d1d628 9use Imager;
10461f9a 10use IO::Seekable;
e2cb7e23 11
feba68a3
TC
12my $buggy_giflib_file = "buggy_giflib.txt";
13
10461f9a 14Imager::init("log"=>"testout/t50basicoo.log");
02d1d628 15
10461f9a
TC
16# single image/file types
17my @types = qw( jpeg png raw ppm gif tiff bmp tga );
02d1d628 18
10461f9a
TC
19# multiple image/file formats
20my @mtypes = qw(tiff gif);
21
22my %hsh=%Imager::formats;
23
24my $test_num = 0;
25my $count;
26for my $type (@types) {
27 $count += 31 if $hsh{$type};
28}
29for my $type (@mtypes) {
30 $count += 7 if $hsh{$type};
31}
02d1d628 32
10461f9a 33print "1..$count\n";
02d1d628
AMH
34
35print "# avaliable formats:\n";
36for(keys %hsh) { print "# $_\n"; }
37
38#print Dumper(\%hsh);
39
10461f9a 40my $img = Imager->new();
e2cb7e23 41
10461f9a 42my %files;
e2cb7e23
AMH
43@files{@types} = ({ file => "testout/t101.jpg" },
44 { file => "testout/t102.png" },
10461f9a
TC
45 { file => "testout/t103.raw", xsize=>150, ysize=>150
46 #, type=>"raw" # TODO: was this there for a reason?
47 },
e2cb7e23
AMH
48 { file => "testout/t104.ppm" },
49 { file => "testout/t105.gif" },
10461f9a
TC
50 { file => "testout/t106.tiff" },
51 { file => "testout/t107_24bit.bmp" },
52 { file => "testout/t108_24bit.tga" }, );
53my %writeopts =
54 (
97c4effc
TC
55 gif=> { make_colors=>'webmap', translate=>'closest', gifquant=>'gen',
56 gif_delay=>20 },
10461f9a 57 );
e2cb7e23 58
10461f9a 59for my $type (@types) {
e2cb7e23 60 next unless $hsh{$type};
10461f9a 61 print "# type $type\n";
e2cb7e23
AMH
62 my %opts = %{$files{$type}};
63 my @a = map { "$_=>${opts{$_}}" } keys %opts;
64 print "#opening Format: $type, options: @a\n";
10461f9a
TC
65 ok($img->read( %opts ), "reading from file", $img);
66 #or die "failed: ",$img->errstr,"\n";
67
68 my %mopts = %opts;
69 delete $mopts{file};
70
71 # read from a file handle
72 my $fh = IO::File->new($opts{file}, "r");
73 if (ok($fh, "opening $opts{file}")) {
74 binmode $fh;
75 my $fhimg = Imager->new;
27c373c9 76 Imager::log_entry("Reading file: $opts{file}\n", -1);
10461f9a
TC
77 my $fhrc = $fhimg->read(fh=>$fh, %mopts);
78 if (ok(!$fhrc, "check that type is required")) {
79 ok ($fhimg->errstr =~ /type parameter missing/, "check for no type error");
80 }
81 else {
82 skip("previous test failed");
83 }
84 if (ok($fhimg->read(fh=>$fh, %mopts, type=>$type), "read from fh")) {
85 ok(Imager::i_img_diff($img->{IMG}, $fhimg->{IMG}) == 0,
86 "image comparison after fh read");
87 }
88 else {
89 skip("no image to compare");
90 }
91 ok($fh->seek(0, SEEK_SET), "seek after read");
92
93 # read from a fd
94 my $fdimg = Imager->new;
95 if (ok($fdimg->read(fd=>fileno($fh), %mopts, type=>$type),
96 "read from fd")) {
97 ok(Imager::i_img_diff($img->{IMG}, $fdimg->{IMG}) == 0,
98 "image comparistion after fd read");
99 }
100 else {
101 skip("no image to compare");
102 }
103 ok($fh->seek(0, SEEK_SET), "seek after fd read");
104 ok($fh->close, "close fh after reads");
105 }
106 else {
107 skip("couldn't open the damn file: $!", 7);
108 }
109
110 if ($type ne 'gif' || Imager::i_giflib_version() >= 4) {
111 # read from a memory buffer
112 open DATA, "< $opts{file}"
113 or die "Cannot open $opts{file}: $!";
114 binmode DATA;
115 my $data = do { local $/; <DATA> };
116 close DATA;
117 my $bimg = Imager->new;
118
119 if (ok($bimg->read(data=>$data, %mopts, type=>$type), "read from buffer",
120 $img)) {
121 ok(Imager::i_img_diff($img->{IMG}, $bimg->{IMG}) == 0,
122 "comparing buffer read image");
123 }
124 else {
125 skip("nothing to compare");
126 }
127
128 # read from callbacks, both with minimum and maximum reads
129 my $buf = $data;
130 my $seekpos = 0;
131 my $reader_min =
132 sub {
133 my ($size, $maxread) = @_;
134 my $out = substr($buf, $seekpos, $size);
135 $seekpos += length $out;
136 $out;
137 };
138 my $reader_max =
139 sub {
140 my ($size, $maxread) = @_;
141 my $out = substr($buf, $seekpos, $maxread);
142 $seekpos += length $out;
143 $out;
144 };
145 my $seeker =
146 sub {
147 my ($offset, $whence) = @_;
148 #print "io_seeker($offset, $whence)\n";
149 if ($whence == SEEK_SET) {
150 $seekpos = $offset;
151 }
152 elsif ($whence == SEEK_CUR) {
153 $seekpos += $offset;
154 }
155 else { # SEEK_END
156 $seekpos = length($buf) + $offset;
157 }
158 #print "-> $seekpos\n";
159 $seekpos;
160 };
161 my $cbimg = Imager->new;
162 ok($cbimg->read(callback=>$reader_min, seekcb=>$seeker, type=>$type, %mopts),
163 "read from callback min", $cbimg);
164 ok(Imager::i_img_diff($cbimg->{IMG}, $img->{IMG}) == 0,
165 "comparing mincb image");
166 $seekpos = 0;
167 ok($cbimg->read(callback=>$reader_max, seekcb=>$seeker, type=>$type, %mopts),
168 "read from callback max", $cbimg);
169 ok(Imager::i_img_diff($cbimg->{IMG}, $img->{IMG}) == 0,
170 "comparing maxcb image");
171 }
172 else {
173 skip("giflib < 4 doesn't support callbacks", 6);
174 }
02d1d628
AMH
175}
176
10461f9a
TC
177for my $type (@types) {
178 next unless $hsh{$type};
179
180 print "# write tests for $type\n";
181 # test writes
182 next unless $hsh{$type};
183 my $file = "testout/t50out.$type";
184 my $wimg = Imager->new;
185 # if this doesn't work, we're so screwed up anyway
186
187 ok($wimg->read(file=>"testout/t104.ppm"),
188 "cannot read base file", $wimg);
189
190 # first to a file
191 print "# writing $type to a file\n";
192 my %extraopts;
193 %extraopts = %{$writeopts{$type}} if $writeopts{$type};
194 ok($wimg->write(file=>$file, %extraopts),
195 "writing $type to a file $file", $wimg);
196
197 print "# writing $type to a FH\n";
198 # to a FH
199 my $fh = IO::File->new($file, "w+")
200 or die "Could not create $file: $!";
201 binmode $fh;
202 ok($wimg->write(fh=>$fh, %extraopts, type=>$type),
203 "writing $type to a FH", $wimg);
204 ok($fh->seek(0, SEEK_END) > 0,
205 "seek after writing $type to a FH");
206 ok(print($fh "SUFFIX\n"),
207 "write to FH after writing $type");
208 ok($fh->close, "closing FH after writing $type");
209
feba68a3
TC
210 if ($type ne 'gif' ||
211 (Imager::i_giflib_version() >= 4 && !-e $buggy_giflib_file)) {
10461f9a
TC
212 if (ok(open(DATA, "< $file"), "opening data source")) {
213 binmode DATA;
214 my $data = do { local $/; <DATA> };
215 close DATA;
216
217 # writing to a buffer
218 print "# writing $type to a buffer\n";
219 my $buf = '';
220 ok($wimg->write(data=>\$buf, %extraopts, type=>$type),
221 "writing $type to a buffer", $wimg);
222 $buf .= "SUFFIX\n";
223 open DATA, "> testout/t50_buf.$type"
224 or die "Cannot create $type buffer file: $!";
225 binmode DATA;
226 print DATA $buf;
227 close DATA;
228 ok($data eq $buf, "comparing file data to buffer");
229
230 $buf = '';
231 my $seekpos = 0;
232 my $did_close;
233 my $writer =
234 sub {
235 my ($what) = @_;
236 if ($seekpos > length $buf) {
237 $buf .= "\0" x ($seekpos - length $buf);
238 }
239 substr($buf, $seekpos, length $what) = $what;
240 $seekpos += length $what;
241 $did_close = 0; # the close must be last
242 1;
243 };
244 my $reader_min =
245 sub {
246 my ($size, $maxread) = @_;
247 my $out = substr($buf, $seekpos, $size);
248 $seekpos += length $out;
249 $out;
250 };
251 my $reader_max =
252 sub {
253 my ($size, $maxread) = @_;
254 my $out = substr($buf, $seekpos, $maxread);
255 $seekpos += length $out;
256 $out;
257 };
258 use IO::Seekable;
259 my $seeker =
260 sub {
261 my ($offset, $whence) = @_;
262 #print "io_seeker($offset, $whence)\n";
263 if ($whence == SEEK_SET) {
264 $seekpos = $offset;
265 }
266 elsif ($whence == SEEK_CUR) {
267 $seekpos += $offset;
268 }
269 else { # SEEK_END
270 $seekpos = length($buf) + $offset;
271 }
272 #print "-> $seekpos\n";
273 $seekpos;
274 };
275
276 my $closer = sub { ++$did_close; };
277
278 print "# writing $type via callbacks (mb=1)\n";
279 ok($wimg->write(writecb=>$writer, seekcb=>$seeker, closecb=>$closer,
280 readcb=>$reader_min,
281 %extraopts, type=>$type, maxbuffer=>1),
282 "writing $type to callback (mb=1)", $wimg);
283
284 ok($did_close, "checking closecb called");
285 $buf .= "SUFFIX\n";
286 ok($data eq $buf, "comparing callback output to file data");
287 print "# writing $type via callbacks (no mb)\n";
288 $buf = '';
289 $did_close = 0;
290 $seekpos = 0;
291 # we don't use the closecb here - used to make sure we don't get
292 # a warning/error on an attempt to call an undef close sub
293 ok($wimg->write(writecb=>$writer, seekcb=>$seeker, readcb=>$reader_min,
294 %extraopts, type=>$type),
295 "writing $type to callback (no mb)", $wimg);
296 $buf .= "SUFFIX\n";
297 ok($data eq $buf, "comparing callback output to file data");
298 }
299 else {
300 skip("couldn't open data source", 7);
301 }
302 }
303 else {
feba68a3
TC
304 if (-e $buggy_giflib_file) {
305 skip("see $buggy_giflib_file", 8);
306 }
307 else {
308 skip("giflib < 4 doesn't support callbacks", 8);
309 }
10461f9a
TC
310 }
311}
312
313my $img2 = $img->crop(width=>50, height=>50);
895dbd34 314$img2 -> write(file=> 'testout/t50.ppm', type=>'pnm');
02d1d628
AMH
315
316undef($img);
317
10461f9a
TC
318# multi image/file tests
319print "# multi-image write tests\n";
320for my $type (@mtypes) {
321 next unless $hsh{$type};
322 print "# $type\n";
323
324 my $file = "testout/t50out.$type";
325 my $wimg = Imager->new;
326
327 # if this doesn't work, we're so screwed up anyway
328 ok($wimg->read(file=>"testout/t50out.$type"),
329 "reading base file", $wimg);
330
331 ok(my $wimg2 = $wimg->copy, "copying base image", $wimg);
332 ok($wimg2->flip(dir=>'h'), "flipping base image", $wimg2);
333
334 my @out = ($wimg, $wimg2);
335 my %extraopts;
336 %extraopts = %{$writeopts{$type}} if $writeopts{$type};
337 ok(Imager->write_multi({ file=>"testout/t50_multi.$type", %extraopts },
338 @out),
339 "writing multiple to a file", "Imager");
340
341 # make sure we get the same back
342 my @images = Imager->read_multi(file=>"testout/t50_multi.$type");
343 if (ok(@images == @out, "checking read image count")) {
344 for my $i (0 .. $#out) {
345 my $diff = Imager::i_img_diff($out[$i]{IMG}, $images[$i]{IMG});
346 print "# diff $diff\n";
347 ok($diff == 0, "comparing image $i");
348 }
349 }
350 else {
351 skip("wrong number of images read", 2);
352 }
353}
354
355
e2cb7e23 356Imager::malloc_state();
02d1d628 357
10461f9a
TC
358#print "ok 2\n";
359
360sub ok {
361 my ($ok, $msg, $img) = @_;
362
363 ++$test_num;
364 if ($ok) {
365 print "ok $test_num # $msg\n";
366 }
367 else {
368 my $err;
369 $err = $img->errstr if $img;
370 # VMS (if we ever support it) wants the whole line in one print
371 my $line = "not ok $test_num # line ".(caller)[2].": $msg";
372 $line .= ": $err" if $err;
373 print $line, "\n";
374 }
375
376 $ok;
377}
378
379sub skip {
380 my ($why, $skipcount) = @_;
381
382 $skipcount ||= 1;
383 for (1.. $skipcount) {
384 ++$test_num;
385 print "ok $test_num # skipped $why\n";
386 }
387}