5 use vars qw(@ISA @EXPORT_OK);
28 sub diff_text_with_nul {
29 my ($desc, $text1, $text2, @params) = @_;
31 my $builder = Test::Builder->new;
34 my $imbase = Imager->new(xsize => 100, ysize => 100);
35 my $imcopy = Imager->new(xsize => 100, ysize => 100);
37 $builder->ok($imbase->string(x => 5, 'y' => 50, size => 20,
39 @params), "$desc - draw text1");
40 $builder->ok($imcopy->string(x => 5, 'y' => 50, size => 20,
42 @params), "$desc - draw text2");
43 $builder->isnt_num(Imager::i_img_diff($imbase->{IMG}, $imcopy->{IMG}), 0,
44 "$desc - check result different");
47 sub is_color3($$$$$) {
48 my ($color, $red, $green, $blue, $comment) = @_;
50 my $builder = Test::Builder->new;
52 unless (defined $color) {
53 $builder->ok(0, $comment);
54 $builder->diag("color is undef");
57 unless ($color->can('rgba')) {
58 $builder->ok(0, $comment);
59 $builder->diag("color is not a color object");
63 my ($cr, $cg, $cb) = $color->rgba;
64 unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue, $comment)) {
65 $builder->diag(<<END_DIAG);
77 sub is_color_close3($$$$$$) {
78 my ($color, $red, $green, $blue, $tolerance, $comment) = @_;
80 my $builder = Test::Builder->new;
82 unless (defined $color) {
83 $builder->ok(0, $comment);
84 $builder->diag("color is undef");
87 unless ($color->can('rgba')) {
88 $builder->ok(0, $comment);
89 $builder->diag("color is not a color object");
93 my ($cr, $cg, $cb) = $color->rgba;
94 unless ($builder->ok(abs($cr - $red) <= $tolerance
95 && abs($cg - $green) <= $tolerance
96 && abs($cb - $blue) <= $tolerance, $comment)) {
97 $builder->diag(<<END_DIAG);
98 Color out of tolerance ($tolerance):
99 Red: expected $red vs received $cr
100 Green: expected $green vs received $cg
101 Blue: expected $blue vs received $cb
109 sub is_color4($$$$$$) {
110 my ($color, $red, $green, $blue, $alpha, $comment) = @_;
112 my $builder = Test::Builder->new;
114 unless (defined $color) {
115 $builder->ok(0, $comment);
116 $builder->diag("color is undef");
119 unless ($color->can('rgba')) {
120 $builder->ok(0, $comment);
121 $builder->diag("color is not a color object");
125 my ($cr, $cg, $cb, $ca) = $color->rgba;
126 unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue
127 && $ca == $alpha, $comment)) {
128 $builder->diag(<<END_DIAG);
141 sub is_fcolor4($$$$$$;$) {
142 my ($color, $red, $green, $blue, $alpha, $comment_or_diff, $comment_or_undef) = @_;
143 my ($comment, $mindiff);
144 if (defined $comment_or_undef) {
145 ( $mindiff, $comment ) = ( $comment_or_diff, $comment_or_undef )
148 ( $mindiff, $comment ) = ( 0.001, $comment_or_diff )
151 my $builder = Test::Builder->new;
153 unless (defined $color) {
154 $builder->ok(0, $comment);
155 $builder->diag("color is undef");
158 unless ($color->can('rgba')) {
159 $builder->ok(0, $comment);
160 $builder->diag("color is not a color object");
164 my ($cr, $cg, $cb, $ca) = $color->rgba;
165 unless ($builder->ok(abs($cr - $red) <= $mindiff
166 && abs($cg - $green) <= $mindiff
167 && abs($cb - $blue) <= $mindiff
168 && abs($ca - $alpha) <= $mindiff, $comment)) {
169 $builder->diag(<<END_DIAG);
183 my ($color, $grey, $comment) = @_;
185 my $builder = Test::Builder->new;
187 unless (defined $color) {
188 $builder->ok(0, $comment);
189 $builder->diag("color is undef");
192 unless ($color->can('rgba')) {
193 $builder->ok(0, $comment);
194 $builder->diag("color is not a color object");
198 my ($cgrey) = $color->rgba;
199 unless ($builder->ok($cgrey == $grey, $comment)) {
200 $builder->diag(<<END_DIAG);
202 Grey: $grey vs $cgrey
211 my $green=Imager::i_color_new(0,255,0,255);
212 my $blue=Imager::i_color_new(0,0,255,255);
213 my $red=Imager::i_color_new(255,0,0,255);
215 my $img=Imager::ImgRaw::new(150,150,3);
217 Imager::i_box_filled($img,70,25,130,125,$green);
218 Imager::i_box_filled($img,20,25,80,125,$blue);
219 Imager::i_arc($img,75,75,30,0,361,$red);
220 Imager::i_conv($img,[0.1, 0.2, 0.4, 0.2, 0.1]);
226 my $green = Imager::Color->new(0, 255, 0, 255);
227 my $blue = Imager::Color->new(0, 0, 255, 255);
228 my $red = Imager::Color->new(255, 0, 0, 255);
229 my $img = Imager->new(xsize => 150, ysize => 150);
230 $img->box(filled => 1, color => $green, box => [ 70, 24, 130, 124 ]);
231 $img->box(filled => 1, color => $blue, box => [ 20, 26, 80, 126 ]);
232 $img->arc(x => 75, y => 75, r => 30, color => $red);
233 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
239 my $green = Imager::Color->new(0, 255, 0, 255);
240 my $blue = Imager::Color->new(0, 0, 255, 255);
241 my $red = Imager::Color->new(255, 0, 0, 255);
242 my $img = Imager->new(xsize => 150, ysize => 150, bits => 16);
243 $img->box(filled => 1, color => $green, box => [ 70, 25, 130, 125 ]);
244 $img->box(filled => 1, color => $blue, box => [ 20, 25, 80, 125 ]);
245 $img->arc(x => 75, y => 75, r => 30, color => $red);
246 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
251 sub test_image_double {
252 my $green = Imager::Color->new(0, 255, 0, 255);
253 my $blue = Imager::Color->new(0, 0, 255, 255);
254 my $red = Imager::Color->new(255, 0, 0, 255);
255 my $img = Imager->new(xsize => 150, ysize => 150, bits => 'double');
256 $img->box(filled => 1, color => $green, box => [ 70, 25, 130, 125 ]);
257 $img->box(filled => 1, color => $blue, box => [ 20, 25, 80, 125 ]);
258 $img->arc(x => 75, y => 75, r => 30, color => $red);
259 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
264 sub is_image_similar($$$$) {
265 my ($left, $right, $limit, $comment) = @_;
267 my $builder = Test::Builder->new;
269 unless (defined $left) {
270 $builder->ok(0, $comment);
271 $builder->diag("left is undef");
274 unless (defined $right) {
275 $builder->ok(0, $comment);
276 $builder->diag("right is undef");
279 unless ($left->{IMG}) {
280 $builder->ok(0, $comment);
281 $builder->diag("left image has no low level object");
284 unless ($right->{IMG}) {
285 $builder->ok(0, $comment);
286 $builder->diag("right image has no low level object");
289 unless ($left->getwidth == $right->getwidth) {
290 $builder->ok(0, $comment);
291 $builder->diag("left width " . $left->getwidth . " vs right width "
295 unless ($left->getheight == $right->getheight) {
296 $builder->ok(0, $comment);
297 $builder->diag("left height " . $left->getheight . " vs right height "
298 . $right->getheight);
301 unless ($left->getchannels == $right->getchannels) {
302 $builder->ok(0, $comment);
303 $builder->diag("left channels " . $left->getchannels . " vs right channels "
304 . $right->getchannels);
307 my $diff = Imager::i_img_diff($left->{IMG}, $right->{IMG});
308 if ($diff > $limit) {
309 $builder->ok(0, $comment);
310 $builder->diag("image data difference > $limit - $diff");
313 # find the first mismatch
315 for my $y (0 .. $left->getheight()-1) {
316 for my $x (0.. $left->getwidth()-1) {
317 my @lsamples = $left->getsamples(x => $x, y => $y, width => 1);
318 my @rsamples = $right->getsamples(x => $x, y => $y, width => 1);
319 if ("@lsamples" ne "@rsamples") {
320 $builder->diag("first mismatch at ($x, $y) - @lsamples vs @rsamples");
330 return $builder->ok(1, $comment);
334 my ($left, $right, $comment) = @_;
336 local $Test::Builder::Level = $Test::Builder::Level + 1;
338 return is_image_similar($left, $right, 0, $comment);
341 sub image_bounds_checks {
344 my $builder = Test::Builder->new;
346 $builder->ok(!$im->getpixel(x => -1, y => 0), 'bounds check get (-1, 0)');
347 $builder->ok(!$im->getpixel(x => 10, y => 0), 'bounds check get (10, 0)');
348 $builder->ok(!$im->getpixel(x => 0, y => -1), 'bounds check get (0, -1)');
349 $builder->ok(!$im->getpixel(x => 0, y => 10), 'bounds check get (0, 10)');
350 $builder->ok(!$im->getpixel(x => -1, y => 0), 'bounds check get (-1, 0) float');
351 $builder->ok(!$im->getpixel(x => 10, y => 0), 'bounds check get (10, 0) float');
352 $builder->ok(!$im->getpixel(x => 0, y => -1), 'bounds check get (0, -1) float');
353 $builder->ok(!$im->getpixel(x => 0, y => 10), 'bounds check get (0, 10) float');
354 my $black = Imager::Color->new(0, 0, 0);
355 require Imager::Color::Float;
356 my $blackf = Imager::Color::Float->new(0, 0, 0);
357 $builder->ok(!$im->setpixel(x => -1, y => 0, color => $black), 'bounds check set (-1, 0)');
358 $builder->ok(!$im->setpixel(x => 10, y => 0, color => $black), 'bounds check set (10, 0)');
359 $builder->ok(!$im->setpixel(x => 0, y => -1, color => $black), 'bounds check set (0, -1)');
360 $builder->ok(!$im->setpixel(x => 0, y => 10, color => $black), 'bounds check set (0, 10)');
361 $builder->ok(!$im->setpixel(x => -1, y => 0, color => $blackf), 'bounds check set (-1, 0) float');
362 $builder->ok(!$im->setpixel(x => 10, y => 0, color => $blackf), 'bounds check set (10, 0) float');
363 $builder->ok(!$im->setpixel(x => 0, y => -1, color => $blackf), 'bounds check set (0, -1) float');
364 $builder->ok(!$im->setpixel(x => 0, y => 10, color => $blackf), 'bounds check set (0, 10) float');
367 sub test_colorf_gpix {
368 my ($im, $x, $y, $expected, $epsilon, $comment) = @_;
370 my $builder = Test::Builder->new;
372 defined $comment or $comment = '';
374 my $c = Imager::i_gpixf($im, $x, $y);
376 $builder->ok(0, "$comment - retrieve color at ($x,$y)");
379 unless ($builder->ok(colorf_cmp($c, $expected, $epsilon) == 0,
380 "$comment - got right color ($x, $y)")) {
382 my @exp = $expected->rgba;
383 $builder->diag(<<EOS);
384 # got: ($c[0], $c[1], $c[2])
385 # expected: ($exp[0], $exp[1], $exp[2])
391 sub test_color_gpix {
392 my ($im, $x, $y, $expected, $comment) = @_;
394 my $builder = Test::Builder->new;
396 defined $comment or $comment = '';
397 my $c = Imager::i_get_pixel($im, $x, $y);
399 $builder->ok(0, "$comment - retrieve color at ($x,$y)");
402 unless ($builder->ok(color_cmp($c, $expected) == 0,
403 "got right color ($x, $y)")) {
405 my @exp = $expected->rgba;
406 $builder->diag(<<EOS);
407 # got: ($c[0], $c[1], $c[2])
408 # expected: ($exp[0], $exp[1], $exp[2])
416 sub test_colorf_glin {
417 my ($im, $x, $y, $pels, $comment) = @_;
419 my $builder = Test::Builder->new;
421 my @got = Imager::i_glinf($im, $x, $x+@$pels, $y);
423 or return $builder->is_num(scalar(@got), scalar(@$pels), "$comment - pixels retrieved");
425 return $builder->ok(!grep(colorf_cmp($pels->[$_], $got[$_], 0.005), 0..$#got),
426 "$comment - check colors ($x, $y)");
430 my ($c1, $c2, $epsilon) = @_;
432 defined $epsilon or $epsilon = 0;
437 # print "# (",join(",", @s1[0..2]),") <=> (",join(",", @s2[0..2]),")\n";
438 return abs($s1[0]-$s2[0]) >= $epsilon && $s1[0] <=> $s2[0]
439 || abs($s1[1]-$s2[1]) >= $epsilon && $s1[1] <=> $s2[1]
440 || abs($s1[2]-$s2[2]) >= $epsilon && $s1[2] <=> $s2[2];
449 return $s1[0] <=> $s2[0]
451 || $s1[2] <=> $s2[2];
454 # these test the action of the channel mask on the image supplied
455 # which should be an OO image.
457 my ($im, $epsilon) = @_;
459 my $builder = Test::Builder->new;
461 defined $epsilon or $epsilon = 0;
463 # we want to check all four of ppix() and plin(), ppix() and plinf()
464 # basic test procedure:
465 # first using default/all 1s mask, set to white
466 # make sure we got white
467 # set mask to skip a channel, set to grey
468 # make sure only the right channels set
470 print "# channel mask tests\n";
472 my $white = Imager::NC(255, 255, 255);
473 my $grey = Imager::NC(128, 128, 128);
474 my $white_grey = Imager::NC(128, 255, 128);
476 print "# with ppix\n";
477 $builder->ok($im->setmask(mask=>~0), "set to default mask");
478 $builder->ok($im->setpixel(x=>0, 'y'=>0, color=>$white), "set to white all channels");
479 test_color_gpix($im->{IMG}, 0, 0, $white, "ppix");
480 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
481 $builder->ok($im->setpixel(x=>0, 'y'=>0, color=>$grey), "set to grey, no channel 2");
482 test_color_gpix($im->{IMG}, 0, 0, $white_grey, "ppix masked");
484 print "# with plin\n";
485 $builder->ok($im->setmask(mask=>~0), "set to default mask");
486 $builder->ok($im->setscanline(x=>0, 'y'=>1, pixels => [$white]),
487 "set to white all channels");
488 test_color_gpix($im->{IMG}, 0, 1, $white, "plin");
489 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
490 $builder->ok($im->setscanline(x=>0, 'y'=>1, pixels=>[$grey]),
491 "set to grey, no channel 2");
492 test_color_gpix($im->{IMG}, 0, 1, $white_grey, "plin masked");
495 my $whitef = Imager::NCF(1.0, 1.0, 1.0);
496 my $greyf = Imager::NCF(0.5, 0.5, 0.5);
497 my $white_greyf = Imager::NCF(0.5, 1.0, 0.5);
499 print "# with ppixf\n";
500 $builder->ok($im->setmask(mask=>~0), "set to default mask");
501 $builder->ok($im->setpixel(x=>0, 'y'=>2, color=>$whitef), "set to white all channels");
502 test_colorf_gpix($im->{IMG}, 0, 2, $whitef, $epsilon, "ppixf");
503 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
504 $builder->ok($im->setpixel(x=>0, 'y'=>2, color=>$greyf), "set to grey, no channel 2");
505 test_colorf_gpix($im->{IMG}, 0, 2, $white_greyf, $epsilon, "ppixf masked");
507 print "# with plinf\n";
508 $builder->ok($im->setmask(mask=>~0), "set to default mask");
509 $builder->ok($im->setscanline(x=>0, 'y'=>3, pixels => [$whitef]),
510 "set to white all channels");
511 test_colorf_gpix($im->{IMG}, 0, 3, $whitef, $epsilon, "plinf");
512 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
513 $builder->ok($im->setscanline(x=>0, 'y'=>3, pixels=>[$greyf]),
514 "set to grey, no channel 2");
515 test_colorf_gpix($im->{IMG}, 0, 3, $white_greyf, $epsilon, "plinf masked");
525 Imager::Test - common functions used in testing Imager
529 use Imager::Test 'diff_text_with_nul';
530 diff_text_with_nul($test_name, $text1, $text2, @string_options);
534 This is a repository of functions used in testing Imager.
536 Some functions will only be useful in testing Imager itself, while
537 others should be useful in testing modules that use Imager.
539 No functions are exported by default.
545 =item is_color3($color, $red, $blue, $green, $comment)
547 Tests is $color matches the given ($red, $blue, $green)
549 =item is_image($im1, $im2, $comment)
551 Tests if the 2 images have the same content. Both images must be
552 defined, have the same width, height, channels and the same color in
553 each pixel. The color comparison is done at 8-bits per pixel. The
554 color representation such as direct vs paletted, bits per sample are
555 not checked. Equivalent to is_image_similar($im1, $im2, 0, $comment).
557 =item is_image_similar($im1, $im2, $maxdiff, $comment)
559 Tests if the 2 images have similar content. Both images must be
560 defined, have the same width, height and channels. The cum of the
561 squares of the differences of each sample are calculated and must be
562 less than or equal to I<$maxdiff> for the test to pass. The color
563 comparison is done at 8-bits per pixel. The color representation such
564 as direct vs paletted, bits per sample are not checked.
566 =item test_image_raw()
568 Returns a 150x150x3 Imager::ImgRaw test image.
572 Returns a 150x150x3 8-bit/sample OO test image.
574 =item test_image_16()
576 Returns a 150x150x3 16-bit/sample OO test image.
578 =item test_image_double()
580 Returns a 150x150x3 double/sample OO test image.
582 =item diff_text_with_nul($test_name, $text1, $text2, @options)
584 Creates 2 test images and writes $text1 to the first image and $text2
585 to the second image with the string() method. Each call adds 3 ok/not
586 ok to the output of the test script.
588 Extra options that should be supplied include the font and either a
589 color or channel parameter.
591 This was explicitly created for regression tests on #21770.
593 =item image_bounds_checks($im)
595 Attempts to write to various pixel positions outside the edge of the
596 image to ensure that it fails in those locations.
598 Any new image type should pass these tests. Does 16 separate tests.
600 =item test_colorf_gpix($im, $x, $y, $expected, $epsilon, $comment)
602 Retrieves the pixel ($x,$y) from the low-level image $im and compares
603 it to the floating point color $expected, with a tolerance of epsilon.
605 =item test_color_gpix($im, $x, $y, $expected, $comment)
607 Retrieves the pixel ($x,$y) from the low-level image $im and compares
608 it to the floating point color $expected.
610 =item test_colorf_glin($im, $x, $y, $pels, $comment)
612 Retrieves the floating point pixels ($x, $y)-[$x+@$pels, $y] from the
613 low level image $im and compares them against @$pels.
615 =item mask_tests($im, $epsilon)
617 Perform a standard set of mask tests on the OO image $im.
623 Tony Cook <tony@develop-help.com>