]> git.imager.perl.org - imager.git/blob - t/t01introvert.t
- added t/t91pod.t
[imager.git] / t / t01introvert.t
1 #!perl -w
2 # t/t01introvert.t - tests internals of image formats
3 # to make sure we get expected values
4
5 use strict;
6 use lib 't';
7 use Test::More tests=>196;
8
9 BEGIN { use_ok(Imager => qw(:handy :all)) }
10
11 require "t/testtools.pl";
12
13 init_log("testout/t01introvert.log",1);
14
15 my $im_g = Imager::ImgRaw::new(100, 101, 1);
16
17 my $red = NC(255, 0, 0);
18 my $green = NC(0, 255, 0);
19 my $blue = NC(0, 0, 255);
20
21 use Imager::Color::Float;
22 my $f_black = Imager::Color::Float->new(0, 0, 0);
23 my $f_red = Imager::Color::Float->new(1.0, 0, 0);
24 my $f_green = Imager::Color::Float->new(0, 1.0, 0);
25 my $f_blue = Imager::Color::Float->new(0, 0, 1.0);
26
27 is(Imager::i_img_getchannels($im_g), 1, "1 channel image channel count");
28 ok(Imager::i_img_getmask($im_g) & 1, "1 channel image mask");
29 ok(!Imager::i_img_virtual($im_g), "1 channel image not virtual");
30 is(Imager::i_img_bits($im_g), 8, "1 channel image has 8 bits/sample");
31 is(Imager::i_img_type($im_g), 0, "1 channel image is direct");
32
33 my @ginfo = Imager::i_img_info($im_g);
34 is($ginfo[0], 100, "1 channel image width");
35 is($ginfo[1], 101, "1 channel image height");
36
37 undef $im_g; # can we check for release after this somehow?
38
39 my $im_rgb = Imager::ImgRaw::new(100, 101, 3);
40
41 is(Imager::i_img_getchannels($im_rgb), 3, "3 channel image channel count");
42 is((Imager::i_img_getmask($im_rgb) & 7), 7, "3 channel image mask");
43 is(Imager::i_img_bits($im_rgb), 8, "3 channel image has 8 bits/sample");
44 is(Imager::i_img_type($im_rgb), 0, "3 channel image is direct");
45
46 undef $im_rgb;
47
48 my $im_pal = Imager::i_img_pal_new(100, 101, 3, 256);
49
50 ok($im_pal, "make paletted image");
51 is(Imager::i_img_getchannels($im_pal), 3, "pal img channel count");
52 is(Imager::i_img_bits($im_pal), 8, "pal img bits");
53 is(Imager::i_img_type($im_pal), 1, "pal img is paletted");
54
55 my $red_idx = check_add($im_pal, $red, 0);
56 my $green_idx = check_add($im_pal, $green, 1);
57 my $blue_idx = check_add($im_pal, $blue, 2);
58
59 # basic writing of palette indicies
60 # fill with red
61 is(Imager::i_ppal($im_pal, 0, 0, ($red_idx) x 100), 100, 
62    "write red 100 times");
63 # and blue
64 is(Imager::i_ppal($im_pal, 50, 0, ($blue_idx) x 50), 50,
65    "write blue 50 times");
66
67 # make sure we get it back
68 my @pals = Imager::i_gpal($im_pal, 0, 100, 0);
69 ok(!grep($_ != $red_idx, @pals[0..49]), "check for red");
70 ok(!grep($_ != $blue_idx, @pals[50..99]), "check for blue");
71 is(Imager::i_gpal($im_pal, 0, 100, 0), "\0" x 50 . "\2" x 50, 
72    "gpal in scalar context");
73 my @samp = Imager::i_gsamp($im_pal, 0, 100, 0, 0, 1, 2);
74 is(@samp, 300, "gsamp count in list context");
75 my @samp_exp = ((255, 0, 0) x 50, (0, 0, 255) x 50);
76 is_deeply(\@samp, \@samp_exp, "gsamp list deep compare");
77 my $samp = Imager::i_gsamp($im_pal, 0, 100, 0, 0, 1, 2);
78 is(length($samp), 300, "gsamp scalar length");
79 is($samp, "\xFF\0\0" x 50 . "\0\0\xFF" x 50, "gsamp scalar bytes");
80
81 # reading indicies as colors
82 my $c_red = Imager::i_get_pixel($im_pal, 0, 0);
83 ok($c_red, "got the red pixel");
84 ok(color_cmp($red, $c_red) == 0, "and it's red");
85 my $c_blue = Imager::i_get_pixel($im_pal, 50, 0);
86 ok($c_blue, "got the blue pixel");
87 ok(color_cmp($blue, $c_blue) == 0, "and it's blue");
88
89 # drawing with colors
90 ok(Imager::i_ppix($im_pal, 0, 0, $green) == 0, "draw with color in palette");
91 # that was in the palette, should still be paletted
92 is(Imager::i_img_type($im_pal), 1, "image still paletted");
93
94 my $c_green = Imager::i_get_pixel($im_pal, 0, 0);
95 ok($c_green, "got green pixel");
96 ok(color_cmp($green, $c_green) == 0, "and it's green");
97
98 is(Imager::i_colorcount($im_pal), 3, "still 3 colors in palette");
99 is(Imager::i_findcolor($im_pal, $green), 1, "and green is the second");
100
101 my $black = NC(0, 0, 0);
102 # this should convert the image to RGB
103 ok(Imager::i_ppix($im_pal, 1, 0, $black) == 0, "draw with black (not in palette)");
104 is(Imager::i_img_type($im_pal), 0, "pal img shouldn't be paletted now");
105
106 my %quant =
107   (
108    colors => [$red, $green, $blue, $black],
109    makemap => 'none',
110   );
111 my $im_pal2 = Imager::i_img_to_pal($im_pal, \%quant);
112 ok($im_pal2, "got an image from quantizing");
113 is(@{$quant{colors}}, 4, "has the right number of colours");
114 is(Imager::i_gsamp($im_pal2, 0, 100, 0, 0, 1, 2),
115   "\0\xFF\0\0\0\0"."\xFF\0\0" x 48 . "\0\0\xFF" x 50,
116    "colors are still correct");
117
118 # test the OO interfaces
119 my $impal2 = Imager->new(type=>'pseudo', xsize=>200, ysize=>201);
120 ok($impal2, "make paletted via OO");
121 is($impal2->getchannels, 3, "check channels");
122 is($impal2->bits, 8, "check bits");
123 is($impal2->type, 'paletted', "check type");
124
125 {
126   my $red_idx = $impal2->addcolors(colors=>[$red]);
127   ok($red_idx, "add red to OO");
128   is(0+$red_idx, 0, "and it's expected index for red");
129   my $blue_idx = $impal2->addcolors(colors=>[$blue, $green]);
130   ok($blue_idx, "add blue/green via OO");
131   is($blue_idx, 1, "and it's expected index for blue");
132   my $green_idx = $blue_idx + 1;
133   my $c = $impal2->getcolors(start=>$green_idx);
134   ok(color_cmp($green, $c) == 0, "found green where expected");
135   my @cols = $impal2->getcolors;
136   is(@cols, 3, "got 3 colors");
137   my @exp = ( $red, $blue, $green );
138   my $good = 1;
139   for my $i (0..2) {
140     if (color_cmp($cols[$i], $exp[$i])) {
141       $good = 0;
142       last;
143     }
144   }
145   ok($good, "all colors in palette as expected");
146   is($impal2->colorcount, 3, "and colorcount returns 3");
147   is($impal2->maxcolors, 256, "maxcolors as expected");
148   is($impal2->findcolor(color=>$blue), 1, "findcolors found blue");
149   ok($impal2->setcolors(start=>0, colors=>[ $blue, $red ]),
150      "we can setcolors");
151
152   # make an rgb version
153   my $imrgb2 = $impal2->to_rgb8();
154   is($imrgb2->type, 'direct', "converted is direct");
155
156   # and back again, specifying the palette
157   my @colors = ( $red, $blue, $green );
158   my $impal3 = $imrgb2->to_paletted(colors=>\@colors,
159                                     make_colors=>'none',
160                                     translate=>'closest');
161   ok($impal3, "got a paletted image from conversion");
162   dump_colors(@colors);
163   print "# in image\n";
164   dump_colors($impal3->getcolors);
165   is($impal3->colorcount, 3, "new image has expected color table size");
166   is($impal3->type, 'paletted', "and is paletted");
167 }
168
169 ok(!Imager->new(xsize=>0, ysize=>1), "fail to create 0 height image");
170 cmp_ok(Imager->errstr, '=~', qr/Image sizes must be positive/,
171        "0 height error message check");
172 ok(!Imager->new(xsize=>1, ysize=>0), "fail to create 0 width image");
173 cmp_ok(Imager->errstr, '=~', qr/Image sizes must be positive/,
174        "0 width error message check");
175 ok(!Imager->new(xsize=>-1, ysize=>1), "fail to create -ve height image");
176 cmp_ok(Imager->errstr, '=~', qr/Image sizes must be positive/,
177        "-ve width error message check");
178 ok(!Imager->new(xsize=>1, ysize=>-1), "fail to create -ve width image");
179 cmp_ok(Imager->errstr, '=~', qr/Image sizes must be positive/,
180        "-ve height error message check");
181 ok(!Imager->new(xsize=>-1, ysize=>-1), "fail to create -ve width/height image");
182 cmp_ok(Imager->errstr, '=~', qr/Image sizes must be positive/,
183        "-ve width/height error message check");
184
185 ok(!Imager->new(xsize=>1, ysize=>1, channels=>0),
186    "fail to create a zero channel image");
187 cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
188        "out of range channel message check");
189 ok(!Imager->new(xsize=>1, ysize=>1, channels=>5),
190    "fail to create a five channel image");
191 cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
192        "out of range channel message check");
193
194 {
195   # https://rt.cpan.org/Ticket/Display.html?id=8213
196   # check for handling of memory allocation of very large images
197   # only test this on 32-bit machines - on a 64-bit machine it may
198   # result in trying to allocate 4Gb of memory, which is unfriendly at
199   # least and may result in running out of memory, causing a different
200   # type of exit
201  SKIP:
202   {
203     use Config;
204     skip("don't want to allocate 4Gb", 8) unless $Config{intsize} == 4;
205
206     my $uint_range = 256 ** $Config{intsize};
207     print "# range $uint_range\n";
208     my $dim1 = int(sqrt($uint_range))+1;
209     
210     my $im_b = Imager->new(xsize=>$dim1, ysize=>$dim1, channels=>1);
211     is($im_b, undef, "integer overflow check - 1 channel");
212     
213     $im_b = Imager->new(xisze=>$dim1, ysize=>1, channels=>1);
214     ok($im_b, "but same width ok");
215     $im_b = Imager->new(xisze=>1, ysize=>$dim1, channels=>1);
216     ok($im_b, "but same height ok");
217     cmp_ok(Imager->errstr, '=~', qr/integer overflow/,
218            "check the error message");
219
220     # do a similar test with a 3 channel image, so we're sure we catch
221     # the same case where the third dimension causes the overflow
222     my $dim3 = int(sqrt($uint_range / 3))+1;
223     
224     $im_b = Imager->new(xsize=>$dim3, ysize=>$dim3, channels=>3);
225     is($im_b, undef, "integer overflow check - 3 channel");
226     
227     $im_b = Imager->new(xisze=>$dim3, ysize=>1, channels=>3);
228     ok($im_b, "but same width ok");
229     $im_b = Imager->new(xisze=>1, ysize=>$dim3, channels=>3);
230     ok($im_b, "but same height ok");
231
232     cmp_ok(Imager->errstr, '=~', qr/integer overflow/,
233            "check the error message");
234   }
235 }
236
237 { # http://rt.cpan.org/NoAuth/Bug.html?id=9672
238   my $warning;
239   local $SIG{__WARN__} = 
240     sub { 
241       $warning = "@_";
242       my $printed = $warning;
243       $printed =~ s/\n$//;
244       $printed =~ s/\n/\n\#/g; 
245       print "# ",$printed, "\n";
246     };
247   my $img = Imager->new(xsize=>10, ysize=>10);
248   $img->to_rgb8(); # doesn't really matter what the source is
249   cmp_ok($warning, '=~', 'void', "correct warning");
250   cmp_ok($warning, '=~', 't01introvert\\.t', "correct file");
251 }
252
253 { # http://rt.cpan.org/NoAuth/Bug.html?id=11860
254   my $im = Imager->new(xsize=>2, ysize=>2);
255   $im->setpixel(x=>0, 'y'=>0, color=>$red);
256   $im->setpixel(x=>1, 'y'=>0, color=>$blue);
257
258   my @row = Imager::i_glin($im->{IMG}, 0, 2, 0);
259   is(@row, 2, "got 2 pixels from i_glin");
260   ok(color_cmp($row[0], $red) == 0, "red first");
261   ok(color_cmp($row[1], $blue) == 0, "then blue");
262 }
263
264 { # general tag tests
265   
266   # we don't care much about the image itself
267   my $im = Imager::ImgRaw::new(10, 10, 1);
268
269   ok(Imager::i_tags_addn($im, 'alpha', 0, 101), "i_tags_addn(...alpha, 0, 101)");
270   ok(Imager::i_tags_addn($im, undef, 99, 102), "i_tags_addn(...undef, 99, 102)");
271   is(Imager::i_tags_count($im), 2, "should have 2 tags");
272   ok(Imager::i_tags_addn($im, undef, 99, 103), "i_tags_addn(...undef, 99, 103)");
273   is(Imager::i_tags_count($im), 3, "should have 3 tags, despite the dupe");
274   is(Imager::i_tags_find($im, 'alpha', 0), '0 but true', "find alpha");
275   is(Imager::i_tags_findn($im, 99, 0), 1, "find 99");
276   is(Imager::i_tags_findn($im, 99, 2), 2, "find 99 again");
277   is(Imager::i_tags_get($im, 0), 101, "check first");
278   is(Imager::i_tags_get($im, 1), 102, "check second");
279   is(Imager::i_tags_get($im, 2), 103, "check third");
280
281   ok(Imager::i_tags_add($im, 'beta', 0, "hello", 0), 
282      "add string with string key");
283   ok(Imager::i_tags_add($im, 'gamma', 0, "goodbye", 0),
284      "add another one");
285   ok(Imager::i_tags_add($im, undef, 199, "aloha", 0),
286      "add one keyed by number");
287   is(Imager::i_tags_find($im, 'beta', 0), 3, "find beta");
288   is(Imager::i_tags_find($im, 'gamma', 0), 4, "find gamma");
289   is(Imager::i_tags_findn($im, 199, 0), 5, "find 199");
290   ok(Imager::i_tags_delete($im, 2), "delete");
291   is(Imager::i_tags_find($im, 'beta', 0), 2, 'find beta after deletion');
292   ok(Imager::i_tags_delbyname($im, 'beta'), 'delete beta by name');
293   is(Imager::i_tags_find($im, 'beta', 0), undef, 'beta not there now');
294   is(Imager::i_tags_get_string($im, "gamma"), "goodbye", 
295      'i_tags_get_string() on a string');
296   is(Imager::i_tags_get_string($im, 99), 102, 
297      'i_tags_get_string() on a number entry');
298   ok(Imager::i_tags_delbycode($im, 99), 'delete by code');
299   is(Imager::i_tags_findn($im, 99, 0), undef, '99 not there now');
300   is(Imager::i_tags_count($im), 3, 'final count of 3');
301 }
302
303
304   print "# low-level scan line function tests\n";
305   my $im = Imager::ImgRaw::new(10, 10, 4);
306   Imager::i_ppix($im, 5, 0, $red);
307
308   # i_glin/i_glinf
309   my @colors = Imager::i_glin($im, 0, 10, 0);
310   is_deeply([ (0) x 20, (255, 0, 0, 255), (0) x 16 ], 
311             [ map $_->rgba, @colors ],
312             "i_glin - list context");
313   my $colors = Imager::i_glin($im, 0, 10, 0);
314   is("00" x 20 . "FF0000FF" . "00" x 16, 
315      uc unpack("H*", $colors), "i_glin - scalar context");
316   my @fcolors = Imager::i_glinf($im, 0, 10, 0);
317   is_deeply([ (0.0) x 20, (1.0, 0, 0, 1.0) , (0) x 16 ],
318             [ map $_->rgba, @fcolors ],
319             "i_glinf - list context");
320   my $fcolors = Imager::i_glinf($im, 0, 10, 0);
321   is_deeply([ (0.0) x 20, (1.0, 0, 0, 1.0) , (0) x 16 ],
322             [ unpack "d*", $fcolors ],
323             "i_glinf - scalar context");
324
325   # i_plin/i_plinf
326   my @plin_colors = (($black) x 4, $red, $blue, ($black) x 4);
327   is(Imager::i_plin($im, 0, 1, @plin_colors),
328      10, "i_plin - pass in a list");
329   # make sure we get it back
330   is_deeply([ map [ $_->rgba ], @plin_colors ],
331             [ map [ $_->rgba ], Imager::i_glin($im, 0, 10, 1) ],
332             "check i_plin wrote to the image");
333   my @scalar_plin = 
334     (
335      (0,0,0,0) x 4, 
336      (0, 255, 0, 255),
337      (0, 0, 255, 255), 
338      (0, 0, 0, 0) x 4,
339     );
340   is(Imager::i_plin($im, 0, 2, pack("C*", @scalar_plin)),
341      10, "i_plin - pass in a scalar");
342   is_deeply(\@scalar_plin,
343             [ map $_->rgba , Imager::i_glin($im, 0, 10, 2) ],
344             "check i_plin scalar wrote to the image");
345
346   my @plinf_colors = # Note: only 9 pixels
347     ( 
348      ($f_blue) x 4, 
349      $f_red, 
350      ($f_black) x 3, 
351      $f_black
352     );
353   is(Imager::i_plinf($im, 0, 3, @plinf_colors), 9,
354      "i_plinf - list");
355   is_deeply([ map $_->rgba, Imager::i_glinf($im, 0, 9, 3) ],
356             [ map $_->rgba, @plinf_colors ],
357             "check colors were written");
358   my @scalar_plinf =
359     (
360      ( 1.0, 1.0,   0, 1.0 ) x 3,
361      (   0, 1.0, 1.0, 1.0 ) x 2,
362      (   0,   0,   0,   0 ),
363      ( 1.0,   0, 1.0, 1.0 ),
364     );
365   is(Imager::i_plinf($im, 2, 4, pack("d*", @scalar_plinf)),
366      7, "i_plinf - scalar");
367   is_deeply(\@scalar_plinf,
368             [ map $_->rgba, Imager::i_glinf($im, 2, 9, 4) ],
369             "check colors were written");
370
371   is_deeply([ Imager::i_gsamp($im, 0, 10, 0, (0, 3)) ],
372             [ (0, 0) x 5, (255, 255), (0, 0) x 4 ],
373             "i_gsamp list context");
374   is("0000" x 5 . "FFFF" . "0000" x 4,
375      uc unpack("H*", Imager::i_gsamp($im, 0, 10, 0, (0, 3))),
376      "i_gsamp scalar context");
377   is_deeply([ Imager::i_gsampf($im, 2, 9, 4, 0, 2, 3) ],
378             [ (1.0, 0, 1.0) x 3, (0, 1.0, 1.0) x 2, (0, 0, 0),
379               (1.0, 1.0, 1.0) ], "i_gsampf - list context");
380   is_deeply([ unpack("d*", Imager::i_gsampf($im, 2, 9, 4, 0, 2, 3)) ],
381             [ (1.0, 0, 1.0) x 3, (0, 1.0, 1.0) x 2, (0, 0, 0),
382               (1.0, 1.0, 1.0) ], "i_gsampf - scalar context");
383   print "# end low-level scan-line function tests\n";
384 }
385
386 {
387   print "# OO level scanline function tests\n";
388   my $im = Imager->new(xsize=>10, ysize=>10, channels=>4);
389   $im->setpixel(color=>$red, 'x'=>5, 'y'=>0);
390   ok(!$im->getscanline(), "getscanline() - supply nothing, get nothing");
391   is($im->errstr, "missing y parameter", "check message");
392   is_deeply([ map [ $_->rgba ], $im->getscanline('y'=>0) ],
393             [ ([ 0,0,0,0]) x 5, [ 255, 0, 0, 255 ], ([ 0,0,0,0]) x 4 ],
394             "getscanline, list context, default x, width");
395   is_deeply([ map [ $_->rgba ], $im->getscanline('y'=>0, 'x'=>3) ],
396             [ ([0,0,0,0]) x 2, [ 255, 0, 0, 255 ], ([0,0,0,0]) x 4 ],
397             "getscanline, list context, default width");
398   is_deeply([ map [ $_->rgba ], $im->getscanline('y'=>0, 'x'=>4, width=>4) ],
399             [ [0,0,0,0], [ 255, 0, 0, 255 ], ([0,0,0,0]) x 2 ],
400             "getscanline, list context, no defaults");
401   is(uc unpack("H*",  $im->getscanline('y'=>0)),
402      "00000000" x 5 .  "FF0000FF" . "00000000" x 4,
403      "getscanline, scalar context, default x, width");
404   is_deeply([ map [ $_->rgba ], 
405               $im->getscanline('y'=>0, 'x'=>4, width=>4, type=>'float') ],
406             [ [0,0,0,0], [ 1.0, 0, 0, 1.0 ], ([0,0,0,0]) x 2 ],
407             "getscanline float, list context, no defaults");
408   is_deeply([ unpack "d*",
409               $im->getscanline('y'=>0, 'x'=>4, width=>4, type=>'float') ],
410             [ (0,0,0,0), ( 1.0, 0, 0, 1.0 ), (0,0,0,0) x 2 ],
411             "getscanline float, scalar context, no defaults");
412
413   ok(!$im->getscanline('y'=>0, type=>'invalid'),
414      "check invalid type checking");
415   like($im->errstr, qr/invalid type parameter/, 
416        "check message for invalid type");
417
418   my @plin_colors = (($black) x 4, $red, $blue, ($green) x 4);
419   is($im->setscanline('y'=>1, pixels=>\@plin_colors), 10,
420      "setscanline - arrayref, default x");
421   is_deeply([ map [ $_->rgba ], @plin_colors ],
422             [ map [ $_->rgba ], $im->getscanline('y'=>1) ],
423             "check colors were written");
424
425   my @plin_colors2 = ( $green, $red, $blue, $red );
426   is($im->setscanline('y'=>2, 'x'=>3, pixels=>\@plin_colors2), 4,
427      "setscanline - arrayref");
428   is_deeply([ ([ 0,0,0,0 ]) x 3, (map [ $_->rgba ], @plin_colors2),
429               ([ 0,0,0,0 ]) x 3 ],
430             [ map [ $_->rgba ], $im->getscanline('y'=>2) ],
431             "check write to middle of line");
432   
433   my $raw_colors = pack "H*", "FF00FFFF"."FF0000FF"."FFFFFFFF";
434   is($im->setscanline('y'=>3, 'x'=>2, pixels=>$raw_colors), 3,
435      "setscanline - scalar, default raw type")
436     or print "# ",$im->errstr,"\n";
437   is(uc unpack("H*", $im->getscanline('y'=>3, 'x'=>1, 'width'=>5)),
438      "00000000".uc(unpack "H*", $raw_colors)."00000000",
439      "check write");
440
441   # float colors
442   my @fcolors = ( $f_red, $f_blue, $f_black, $f_green );
443   is($im->setscanline('y'=>4, 'x'=>3, pixels=>\@fcolors), 4,
444      "setscanline - float arrayref");
445   is_deeply([ map [ $_->rgba ], @fcolors ],
446             [ map [ $_->rgba ], $im->getscanline('y'=>4, 'x'=>3, width=>4, type=>'float') ],
447             "check write");
448   # packed
449   my $packed_fcolors = pack "d*", map $_->rgba, @fcolors;
450   is($im->setscanline('y'=>5, 'x'=>4, pixels=>$packed_fcolors, type=>'float'), 4,
451      "setscanline - float scalar");
452   is_deeply([ map [ $_->rgba ], @fcolors ],
453             [ map [ $_->rgba ], $im->getscanline('y'=>5, 'x'=>4, width=>4, type=>'float') ],
454             "check write");
455
456   # get samples
457   is_deeply([ $im->getsamples('y'=>1, channels=>[ 0 ]) ],
458             [ map +($_->rgba)[0], @plin_colors ],
459             "get channel 0, list context, default x, width");
460   is_deeply([ unpack "C*", $im->getsamples('y'=>1, channels=>[0, 2]) ],
461             [ map { ($_->rgba)[0, 2] } @plin_colors ],
462             "get channel 0, 1, scalar context");
463   is_deeply([ $im->getsamples('y'=>4, 'x'=>3, width=>4, type=>'float',
464                               channels=>[1,3]) ],
465             [ map { ($_->rgba)[1,3] } @fcolors ],
466             "get channels 1,3, list context, float samples");
467   is_deeply([ unpack "d*", 
468               $im->getsamples('y'=>4, 'x'=>3, width=>4,
469                               type=>'float', channels=>[3,2,1,0]) ],
470             [ map { ($_->rgba)[3,2,1,0] } @fcolors ],
471             "get channels 3..0 as scalar, float samples");
472   
473   print "# end OO level scanline function tests\n";
474 }
475
476 { # check the channel mask function
477   
478   my $im = Imager->new(xsize => 10, ysize=>10, bits=>8);
479
480   mask_tests($im, 0.005);
481 }
482
483 sub check_add {
484   my ($im, $color, $expected) = @_;
485   my $index = Imager::i_addcolors($im, $color);
486   ok($index, "got index");
487   print "# $index\n";
488   is(0+$index, $expected, "index matched expected");
489   my ($new) = Imager::i_getcolors($im, $index);
490   ok($new, "got the color");
491   ok(color_cmp($new, $color) == 0, "color matched what was added");
492
493   $index;
494 }
495
496 # sub array_ncmp {
497 #   my ($a1, $a2) = @_;
498 #   my $len = @$a1 < @$a2 ? @$a1 : @$a2;
499 #   for my $i (0..$len-1) {
500 #     my $diff = $a1->[$i] <=> $a2->[$i] 
501 #       and return $diff;
502 #   }
503 #   return @$a1 <=> @$a2;
504 # }
505
506 sub dump_colors {
507   for my $col (@_) {
508     print "# ", map(sprintf("%02X", $_), ($col->rgba)[0..2]),"\n";
509   }
510 }