use $Config{path_sep} instead of working it out on our own
[imager.git] / t / t104ppm.t
1 #!perl -w
2 use Imager ':all';
3 use Test::More tests => 191;
4 use strict;
5 use Imager::Test qw(test_image_raw test_image_16 is_color3 is_color1 is_image);
6
7 init_log("testout/t104ppm.log",1);
8
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);
12
13 my $img    = test_image_raw();
14
15 my $fh = openimage(">testout/t104.ppm");
16 my $IO = Imager::io_new_fd(fileno($fh));
17 ok(i_writeppm_wiol($img, $IO), "write pnm low")
18   or die "Cannot write testout/t104.ppm\n";
19 close($fh);
20
21 $IO = Imager::io_new_bufchain();
22 ok(i_writeppm_wiol($img, $IO), "write to bufchain")
23   or die "Cannot write to bufchain";
24 my $data = Imager::io_slurp($IO);
25
26 $fh = openimage("testout/t104.ppm");
27 $IO = Imager::io_new_fd( fileno($fh) );
28 my $cmpimg = i_readpnm_wiol($IO,-1);
29 ok($cmpimg, "read image we wrote")
30   or die "Cannot read testout/t104.ppm\n";
31 close($fh);
32
33 is(i_img_diff($img, $cmpimg), 0, "compare written and read images");
34
35 my $rdata = slurp("testout/t104.ppm");
36 is($data, $rdata, "check data read from file and bufchain data");
37
38 # build a grayscale image
39 my $gimg = Imager::ImgRaw::new(150, 150, 1);
40 my $gray = i_color_new(128, 0, 0, 255);
41 my $dgray = i_color_new(64, 0, 0, 255);
42 my $white = i_color_new(255, 0, 0, 255);
43 i_box_filled($gimg, 20, 20, 130, 130, $gray);
44 i_box_filled($gimg, 40, 40, 110, 110, $dgray);
45 i_arc($gimg, 75, 75, 30, 0, 361, $white);
46
47 open FH, "> testout/t104_gray.pgm" or die "Cannot create testout/t104_gray.pgm: $!\n";
48 binmode FH;
49 $IO = Imager::io_new_fd(fileno(FH));
50 ok(i_writeppm_wiol($gimg, $IO), "write grayscale");
51 close FH;
52
53 open FH, "< testout/t104_gray.pgm" or die "Cannot open testout/t104_gray.pgm: $!\n";
54 binmode FH;
55 $IO = Imager::io_new_fd(fileno(FH));
56 my $gcmpimg = i_readpnm_wiol($IO, -1);
57 ok($gcmpimg, "read grayscale");
58 is(i_img_diff($gimg, $gcmpimg), 0, 
59    "compare written and read greyscale images");
60
61 my $ooim = Imager->new;
62 ok($ooim->read(file=>"testimg/simple.pbm"), "read simple pbm, via OO");
63
64 check_gray(Imager::i_get_pixel($ooim->{IMG}, 0, 0), 0);
65 check_gray(Imager::i_get_pixel($ooim->{IMG}, 0, 1), 255);
66 check_gray(Imager::i_get_pixel($ooim->{IMG}, 1, 0), 255);
67 check_gray(Imager::i_get_pixel($ooim->{IMG}, 1, 1), 0);
68 is($ooim->type, 'paletted', "check pbm read as paletted");
69 is($ooim->tags(name=>'pnm_type'), 1, "check pnm_type tag");
70
71 {
72   # https://rt.cpan.org/Ticket/Display.html?id=7465
73   # the pnm reader ignores the maxval that it reads from the pnm file
74   my $maxval = Imager->new;
75   ok($maxval->read(file=>"testimg/maxval.ppm"),
76      "read testimg/maxval.ppm");
77   
78   # this image contains three pixels, with each sample from 0 to 63
79   # the pixels are (63, 63, 63), (32, 32, 32) and (31, 31, 0)
80   
81   # check basic parameters
82   is($maxval->getchannels, 3, "channel count");
83   is($maxval->getwidth, 3, "width");
84   is($maxval->getheight, 1, "height");
85   
86   # check the pixels
87   ok(my ($white, $grey, $green) = $maxval->getpixel('x'=>[0,1,2], 'y'=>[0,0,0]), "fetch pixels");
88   is_color3($white, 255, 255, 255, "white pixel");
89   is_color3($grey,  130, 130, 130, "grey  pixel");
90   is_color3($green, 125, 125, 0,   "green pixel");
91   is($maxval->tags(name=>'pnm_type'), 6, "check pnm_type tag on maxval");
92
93   # and do the same for ASCII images
94   my $maxval_asc = Imager->new;
95   ok($maxval_asc->read(file=>"testimg/maxval_asc.ppm"),
96      "read testimg/maxval_asc.ppm");
97   
98   # this image contains three pixels, with each sample from 0 to 63
99   # the pixels are (63, 63, 63), (32, 32, 32) and (31, 31, 0)
100   
101   # check basic parameters
102   is($maxval_asc->getchannels, 3, "channel count");
103   is($maxval_asc->getwidth, 3, "width");
104   is($maxval_asc->getheight, 1, "height");
105
106   is($maxval->tags(name=>'pnm_type'), 6, "check pnm_type tag on maxval");
107   
108   # check the pixels
109   ok(my ($white_asc, $grey_asc, $green_asc) = $maxval_asc->getpixel('x'=>[0,1,2], 'y'=>[0,0,0]), "fetch pixels");
110   is_color3($white_asc, 255, 255, 255, "white asc pixel");
111   is_color3($grey_asc,  130, 130, 130, "grey  asc pixel");
112   is_color3($green_asc, 125, 125, 0,   "green asc pixel");
113 }
114
115 { # previously we didn't validate maxval at all, make sure it's
116   # validated now
117   my $maxval0 = Imager->new;
118   ok(!$maxval0->read(file=>'testimg/maxval_0.ppm'),
119      "should fail to read maxval 0 image");
120   print "# ", $maxval0->errstr, "\n";
121   like($maxval0->errstr, qr/maxval is zero - invalid pnm file/,
122        "error expected from reading maxval_0.ppm");
123
124   my $maxval65536 = Imager->new;
125   ok(!$maxval65536->read(file=>'testimg/maxval_65536.ppm'),
126      "should fail reading maxval 65536 image");
127   print "# ",$maxval65536->errstr, "\n";
128   like($maxval65536->errstr, qr/maxval of 65536 is over 65535 - invalid pnm file/,
129        "error expected from reading maxval_65536.ppm");
130
131   # maxval of 256 is valid, and handled as of 0.56
132   my $maxval256 = Imager->new;
133   ok($maxval256->read(file=>'testimg/maxval_256.ppm'),
134      "should succeed reading maxval 256 image");
135   is_color3($maxval256->getpixel(x => 0, 'y' => 0),
136             0, 0, 0, "check black in maxval_256");
137   is_color3($maxval256->getpixel(x => 0, 'y' => 1),
138             255, 255, 255, "check white in maxval_256");
139   is($maxval256->bits, 16, "check bits/sample on maxval 256");
140
141   # make sure we handle maxval > 255 for ascii
142   my $maxval4095asc = Imager->new;
143   ok($maxval4095asc->read(file=>'testimg/maxval_4095_asc.ppm'),
144      "read maxval_4095_asc.ppm");
145   is($maxval4095asc->getchannels, 3, "channels");
146   is($maxval4095asc->getwidth, 3, "width");
147   is($maxval4095asc->getheight, 1, "height");
148   is($maxval4095asc->bits, 16, "check bits/sample on maxval 4095");
149
150   ok(my ($white, $grey, $green) = $maxval4095asc->getpixel('x'=>[0,1,2], 'y'=>[0,0,0]), "fetch pixels");
151   is_color3($white, 255, 255, 255, "white 4095 pixel");
152   is_color3($grey,  128, 128, 128, "grey  4095 pixel");
153   is_color3($green, 127, 127, 0,   "green 4095 pixel");
154 }
155
156 { # check i_format is set when reading a pnm file
157   # doesn't really matter which file.
158   my $maxval = Imager->new;
159   ok($maxval->read(file=>"testimg/maxval.ppm"),
160       "read test file");
161   my ($type) = $maxval->tags(name=>'i_format');
162   is($type, 'pnm', "check i_format");
163 }
164
165 { # check file limits are checked
166   my $limit_file = "testout/t104.ppm";
167   ok(Imager->set_file_limits(reset=>1, width=>149), "set width limit 149");
168   my $im = Imager->new;
169   ok(!$im->read(file=>$limit_file),
170      "should fail read due to size limits");
171   print "# ",$im->errstr,"\n";
172   like($im->errstr, qr/image width/, "check message");
173
174   ok(Imager->set_file_limits(reset=>1, height=>149), "set height limit 149");
175   ok(!$im->read(file=>$limit_file),
176      "should fail read due to size limits");
177   print "# ",$im->errstr,"\n";
178   like($im->errstr, qr/image height/, "check message");
179
180   ok(Imager->set_file_limits(reset=>1, width=>150), "set width limit 150");
181   ok($im->read(file=>$limit_file),
182      "should succeed - just inside width limit");
183   ok(Imager->set_file_limits(reset=>1, height=>150), "set height limit 150");
184   ok($im->read(file=>$limit_file),
185      "should succeed - just inside height limit");
186   
187   # 150 x 150 x 3 channel image uses 67500 bytes
188   ok(Imager->set_file_limits(reset=>1, bytes=>67499),
189      "set bytes limit 67499");
190   ok(!$im->read(file=>$limit_file),
191      "should fail - too many bytes");
192   print "# ",$im->errstr,"\n";
193   like($im->errstr, qr/storage size/, "check error message");
194   ok(Imager->set_file_limits(reset=>1, bytes=>67500),
195      "set bytes limit 67500");
196   ok($im->read(file=>$limit_file),
197      "should succeed - just inside bytes limit");
198   Imager->set_file_limits(reset=>1);
199 }
200
201 {
202   # check we correctly sync with the data stream
203   my $im = Imager->new;
204   ok($im->read(file => 'testimg/pgm.pgm', type => 'pnm'),
205      "read pgm.pgm")
206     or print "# cannot read pgm.pgm: ", $im->errstr, "\n";
207   print "# ", $im->getsamples('y' => 0), "\n";
208   is_color1($im->getpixel(x=>0, 'y' => 0), 254, "check top left");
209 }
210
211 { # check error messages set correctly
212   my $im = Imager->new;
213   ok(!$im->read(file=>'t/t104ppm.t', type=>'pnm'),
214      'should fail to read script as an image file');
215   is($im->errstr, 'unable to read pnm image: bad header magic, not a PNM file',
216      "check error message");
217 }
218
219 {
220   # RT #30074
221   # give 4/2 channel images a background color when saving to pnm
222   my $im = Imager->new(xsize=>16, ysize=>16, channels=>4);
223   $im->box(filled => 1, xmin => 8, color => '#FFE0C0');
224   $im->box(filled => 1, color => NC(0, 192, 192, 128),
225            ymin => 8, xmax => 7);
226   ok($im->write(file=>"testout/t104_alpha.ppm", type=>'pnm'),
227      "should succeed writing 4 channel image");
228   my $imread = Imager->new;
229   ok($imread->read(file => 'testout/t104_alpha.ppm'), "read it back");
230   is_color3($imread->getpixel('x' => 0, 'y' => 0), 0, 0, 0, 
231             "check transparent became black");
232   is_color3($imread->getpixel('x' => 8, 'y' => 0), 255, 224, 192,
233             "check color came through");
234   is_color3($imread->getpixel('x' => 0, 'y' => 15), 0, 96, 96,
235             "check translucent came through");
236   my $data;
237   ok($im->write(data => \$data, type => 'pnm', i_background => '#FF0000'),
238      "write with red background");
239   ok($imread->read(data => $data, type => 'pnm'),
240      "read it back");
241   is_color3($imread->getpixel('x' => 0, 'y' => 0), 255, 0, 0, 
242             "check transparent became red");
243   is_color3($imread->getpixel('x' => 8, 'y' => 0), 255, 224, 192,
244             "check color came through");
245   is_color3($imread->getpixel('x' => 0, 'y' => 15), 127, 96, 96,
246             "check translucent came through");
247 }
248
249 {
250   # more RT #30074 - 16 bit images
251   my $im = Imager->new(xsize=>16, ysize=>16, channels=>4, bits => 16);
252   $im->box(filled => 1, xmin => 8, color => '#FFE0C0');
253   $im->box(filled => 1, color => NC(0, 192, 192, 128),
254            ymin => 8, xmax => 7);
255   ok($im->write(file=>"testout/t104_alp16.ppm", type=>'pnm', 
256                 pnm_write_wide_data => 1),
257      "should succeed writing 4 channel image");
258   my $imread = Imager->new;
259   ok($imread->read(file => 'testout/t104_alp16.ppm'), "read it back");
260   is($imread->bits, 16, "check we did produce a 16 bit image");
261   is_color3($imread->getpixel('x' => 0, 'y' => 0), 0, 0, 0, 
262             "check transparent became black");
263   is_color3($imread->getpixel('x' => 8, 'y' => 0), 255, 224, 192,
264             "check color came through");
265   is_color3($imread->getpixel('x' => 0, 'y' => 15), 0, 96, 96,
266             "check translucent came through");
267   my $data;
268   ok($im->write(data => \$data, type => 'pnm', i_background => '#FF0000',
269                 pnm_write_wide_data => 1),
270      "write with red background");
271   ok($imread->read(data => $data, type => 'pnm'),
272      "read it back");
273   is($imread->bits, 16, "check it's 16-bit");
274   is_color3($imread->getpixel('x' => 0, 'y' => 0), 255, 0, 0, 
275             "check transparent became red");
276   is_color3($imread->getpixel('x' => 8, 'y' => 0), 255, 224, 192,
277             "check color came through");
278   is_color3($imread->getpixel('x' => 0, 'y' => 15), 127, 96, 96,
279             "check translucent came through");
280 }
281
282 # various bad input files
283 print "# check error handling\n";
284 {
285   my $im = Imager->new;
286   ok(!$im->read(file => 'testimg/short_bin.ppm', type=>'pnm'),
287      "fail to read short bin ppm");
288   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
289          "check error message");
290 }
291
292 {
293   my $im = Imager->new;
294   ok(!$im->read(file => 'testimg/short_bin16.ppm', type=>'pnm'),
295      "fail to read short bin ppm (maxval 65535)");
296   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
297          "check error message");
298 }
299
300 {
301   my $im = Imager->new;
302   ok(!$im->read(file => 'testimg/short_bin.pgm', type=>'pnm'),
303      "fail to read short bin pgm");
304   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
305          "check error message");
306 }
307
308 {
309   my $im = Imager->new;
310   ok(!$im->read(file => 'testimg/short_bin16.pgm', type=>'pnm'),
311      "fail to read short bin pgm (maxval 65535)");
312   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
313          "check error message");
314 }
315
316 {
317   my $im = Imager->new;
318   ok(!$im->read(file => 'testimg/short_bin.pbm', type => 'pnm'),
319      "fail to read a short bin pbm");
320   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
321          "check error message");
322 }
323
324 {
325   my $im = Imager->new;
326   ok(!$im->read(file => 'testimg/short_asc.ppm', type => 'pnm'),
327      "fail to read a short asc ppm");
328   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
329          "check error message");
330 }
331
332 {
333   my $im = Imager->new;
334   ok(!$im->read(file => 'testimg/short_asc.pgm', type => 'pnm'),
335      "fail to read a short asc pgm");
336   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
337          "check error message");
338 }
339
340 {
341   my $im = Imager->new;
342   ok(!$im->read(file => 'testimg/short_asc.pbm', type => 'pnm'),
343      "fail to read a short asc pbm");
344   cmp_ok($im->errstr, '=~', 'short read - file truncated', 
345          "check error message");
346 }
347
348 {
349   my $im = Imager->new;
350   ok(!$im->read(file => 'testimg/bad_asc.ppm', type => 'pnm'),
351      "fail to read a bad asc ppm");
352   cmp_ok($im->errstr, '=~', 'invalid data for ascii pnm', 
353          "check error message");
354 }
355
356 {
357   my $im = Imager->new;
358   ok(!$im->read(file => 'testimg/bad_asc.pgm', type => 'pnm'),
359      "fail to read a bad asc pgm");
360   cmp_ok($im->errstr, '=~', 'invalid data for ascii pnm', 
361          "check error message");
362 }
363
364 {
365   my $im = Imager->new;
366   ok(!$im->read(file => 'testimg/bad_asc.pbm', type => 'pnm'),
367      "fail to read a bad asc pbm");
368   cmp_ok($im->errstr, '=~', 'invalid data for ascii pnm', 
369          "check error message");
370 }
371
372 {
373   my $im = Imager->new;
374   ok($im->read(file => 'testimg/short_bin.ppm', type => 'pnm',
375                 allow_incomplete => 1),
376      "partial read bin ppm");
377   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
378   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
379 }
380
381 {
382   my $im = Imager->new;
383   ok($im->read(file => 'testimg/short_bin16.ppm', type => 'pnm',
384                 allow_incomplete => 1),
385      "partial read bin16 ppm");
386   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
387   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
388   is($im->bits, 16, "check correct bits");
389 }
390
391 {
392   my $im = Imager->new;
393   ok($im->read(file => 'testimg/short_bin.pgm', type => 'pnm',
394                 allow_incomplete => 1),
395      "partial read bin pgm");
396   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
397   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
398 }
399
400 {
401   my $im = Imager->new;
402   ok($im->read(file => 'testimg/short_bin16.pgm', type => 'pnm',
403                 allow_incomplete => 1),
404      "partial read bin16 pgm");
405   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
406   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
407 }
408
409 {
410   my $im = Imager->new;
411   ok($im->read(file => 'testimg/short_bin.pbm', type => 'pnm',
412                 allow_incomplete => 1),
413      "partial read bin pbm");
414   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
415   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
416 }
417
418 {
419   my $im = Imager->new;
420   ok($im->read(file => 'testimg/short_asc.ppm', type => 'pnm',
421                 allow_incomplete => 1),
422      "partial read asc ppm");
423   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
424   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
425 }
426
427 {
428   my $im = Imager->new;
429   ok($im->read(file => 'testimg/short_asc.pgm', type => 'pnm',
430                 allow_incomplete => 1),
431      "partial read asc pgm");
432   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
433   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
434 }
435
436 {
437   my $im = Imager->new;
438   ok($im->read(file => 'testimg/short_asc.pbm', type => 'pnm',
439                 allow_incomplete => 1),
440      "partial read asc pbm");
441   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
442   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
443 }
444
445 {
446   my @imgs = Imager->read_multi(file => 'testimg/multiple.ppm');
447   is( 0+@imgs, 3, "Read 3 images");
448   is( $imgs[0]->tags( name => 'pnm_type' ), 1, "Image 1 is type 1" );
449   is( $imgs[0]->getwidth, 2, " ... width=2" );
450   is( $imgs[0]->getheight, 2, " ... width=2" );
451   is( $imgs[1]->tags( name => 'pnm_type' ), 6, "Image 2 is type 6" );
452   is( $imgs[1]->getwidth, 164, " ... width=164" );
453   is( $imgs[1]->getheight, 180, " ... width=180" );
454   is( $imgs[2]->tags( name => 'pnm_type' ), 5, "Image 3 is type 5" );
455   is( $imgs[2]->getwidth, 2, " ... width=2" );
456   is( $imgs[2]->getheight, 2, " ... width=2" );
457 }
458
459 {
460   my $im = Imager->new;
461   ok($im->read(file => 'testimg/bad_asc.ppm', type => 'pnm',
462                 allow_incomplete => 1),
463      "partial read bad asc ppm");
464   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
465   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
466 }
467
468 {
469   my $im = Imager->new;
470   ok($im->read(file => 'testimg/bad_asc.pgm', type => 'pnm',
471                 allow_incomplete => 1),
472      "partial read bad asc pgm");
473   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
474   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
475 }
476
477 {
478   my $im = Imager->new;
479   ok($im->read(file => 'testimg/bad_asc.pbm', type => 'pnm',
480                 allow_incomplete => 1),
481      "partial read bad asc pbm");
482   is($im->tags(name => 'i_incomplete'), 1, "partial flag set");
483   is($im->tags(name => 'i_lines_read'), 1, "lines_read set");
484 }
485
486 {
487   print "# monochrome output\n";
488   my $im = Imager->new(xsize => 10, ysize => 10, channels => 1, type => 'paletted');
489   ok($im->addcolors(colors => [ '#000000', '#FFFFFF' ]),
490      "add black and white");
491   $im->box(filled => 1, xmax => 4, color => '#000000');
492   $im->box(filled => 1, xmin => 5, color => '#FFFFFF');
493   is($im->type, 'paletted', 'mono still paletted');
494   ok($im->write(file => 'testout/t104_mono.pbm', type => 'pnm'),
495      "save as pbm");
496
497   # check it
498   my $imread = Imager->new;
499   ok($imread->read(file => 'testout/t104_mono.pbm', type=>'pnm'),
500      "read it back in")
501     or print "# ", $imread->errstr, "\n";
502   is($imread->type, 'paletted', "check result is paletted");
503   is($imread->tags(name => 'pnm_type'), 4, "check type");
504   is_image($im, $imread, "check image matches");
505 }
506
507 {
508   print "# monochrome output - reversed palette\n";
509   my $im = Imager->new(xsize => 10, ysize => 10, channels => 1, type => 'paletted');
510   ok($im->addcolors(colors => [ '#FFFFFF', '#000000' ]),
511      "add white and black");
512   $im->box(filled => 1, xmax => 4, color => '#000000');
513   $im->box(filled => 1, xmin => 5, color => '#FFFFFF');
514   is($im->type, 'paletted', 'mono still paletted');
515   ok($im->write(file => 'testout/t104_mono2.pbm', type => 'pnm'),
516      "save as pbm");
517
518   # check it
519   my $imread = Imager->new;
520   ok($imread->read(file => 'testout/t104_mono2.pbm', type=>'pnm'),
521      "read it back in")
522     or print "# ", $imread->errstr, "\n";
523   is($imread->type, 'paletted', "check result is paletted");
524   is($imread->tags(name => 'pnm_type'), 4, "check type");
525   is_image($im, $imread, "check image matches");
526 }
527
528 {
529   print "# 16-bit output\n";
530   my $data;
531   my $im = test_image_16();
532   
533   # without tag, it should do 8-bit output
534   ok($im->write(data => \$data, type => 'pnm'),
535      "write 16-bit image as 8-bit/sample ppm");
536   my $im8 = Imager->new;
537   ok($im8->read(data => $data), "read it back");
538   is($im8->tags(name => 'pnm_maxval'), 255, "check maxval");
539   is_image($im, $im8, "check image matches");
540
541   # try 16-bit output
542   $im->settag(name => 'pnm_write_wide_data', value => 1);
543   $data = '';
544   ok($im->write(data => \$data, type => 'pnm'),
545      "write 16-bit image as 16-bit/sample ppm");
546   $im->write(file=>'testout/t104_16.ppm');
547   my $im16 = Imager->new;
548   ok($im16->read(data => $data), "read it back");
549   is($im16->tags(name => 'pnm_maxval'), 65535, "check maxval");
550   $im16->write(file=>'testout/t104_16b.ppm');
551   is_image($im, $im16, "check image matches");
552 }
553
554 {
555   ok(grep($_ eq 'pnm', Imager->read_types), "check pnm in read types");
556   ok(grep($_ eq 'pnm', Imager->write_types), "check pnm in write types");
557 }
558
559 { # test new() loading an image
560   my $im = Imager->new(file => "testimg/penguin-base.ppm");
561   ok($im, "received an image");
562   is($im->getwidth, 164, "check width matches image");
563
564   # fail to load an image
565   my $im2 = Imager->new(file => "Imager.pm", filetype => "pnm");
566   ok(!$im2, "no image when file failed to load");
567   cmp_ok(Imager->errstr, '=~', "bad header magic, not a PNM file",
568          "check error message transferred");
569
570   # load from data
571  SKIP:
572   {
573     ok(open(FH, "< testimg/penguin-base.ppm"), "open test file")
574       or skip("couldn't open data source", 4);
575     binmode FH;
576     my $imdata = do { local $/; <FH> };
577     close FH;
578     ok(length $imdata, "we got the data");
579     my $im3 = Imager->new(data => $imdata);
580     ok($im3, "read the file data");
581     is($im3->getwidth, 164, "check width matches image");
582   }
583 }
584
585 sub openimage {
586   my $fname = shift;
587   local(*FH);
588   open(FH, $fname) or die "Cannot open $fname: $!\n";
589   binmode(FH);
590   return *FH;
591 }
592
593 sub slurp {
594   my $fh = openimage(shift);
595   local $/;
596   my $data = <$fh>;
597   close($fh);
598   return $data;
599 }
600
601 sub check_gray {
602   my ($c, $gray) = @_;
603
604   my ($g) = $c->rgba;
605   is($g, $gray, "compare gray");
606 }
607