5 use vars qw(@ISA @EXPORT_OK $VERSION);
33 sub diff_text_with_nul {
34 my ($desc, $text1, $text2, @params) = @_;
36 my $builder = Test::Builder->new;
39 my $imbase = Imager->new(xsize => 100, ysize => 100);
40 my $imcopy = Imager->new(xsize => 100, ysize => 100);
42 $builder->ok($imbase->string(x => 5, 'y' => 50, size => 20,
44 @params), "$desc - draw text1");
45 $builder->ok($imcopy->string(x => 5, 'y' => 50, size => 20,
47 @params), "$desc - draw text2");
48 $builder->isnt_num(Imager::i_img_diff($imbase->{IMG}, $imcopy->{IMG}), 0,
49 "$desc - check result different");
52 sub is_color3($$$$$) {
53 my ($color, $red, $green, $blue, $comment) = @_;
55 my $builder = Test::Builder->new;
57 unless (defined $color) {
58 $builder->ok(0, $comment);
59 $builder->diag("color is undef");
62 unless ($color->can('rgba')) {
63 $builder->ok(0, $comment);
64 $builder->diag("color is not a color object");
68 my ($cr, $cg, $cb) = $color->rgba;
69 unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue, $comment)) {
70 $builder->diag(<<END_DIAG);
82 sub is_color_close3($$$$$$) {
83 my ($color, $red, $green, $blue, $tolerance, $comment) = @_;
85 my $builder = Test::Builder->new;
87 unless (defined $color) {
88 $builder->ok(0, $comment);
89 $builder->diag("color is undef");
92 unless ($color->can('rgba')) {
93 $builder->ok(0, $comment);
94 $builder->diag("color is not a color object");
98 my ($cr, $cg, $cb) = $color->rgba;
99 unless ($builder->ok(abs($cr - $red) <= $tolerance
100 && abs($cg - $green) <= $tolerance
101 && abs($cb - $blue) <= $tolerance, $comment)) {
102 $builder->diag(<<END_DIAG);
103 Color out of tolerance ($tolerance):
104 Red: expected $red vs received $cr
105 Green: expected $green vs received $cg
106 Blue: expected $blue vs received $cb
114 sub is_color4($$$$$$) {
115 my ($color, $red, $green, $blue, $alpha, $comment) = @_;
117 my $builder = Test::Builder->new;
119 unless (defined $color) {
120 $builder->ok(0, $comment);
121 $builder->diag("color is undef");
124 unless ($color->can('rgba')) {
125 $builder->ok(0, $comment);
126 $builder->diag("color is not a color object");
130 my ($cr, $cg, $cb, $ca) = $color->rgba;
131 unless ($builder->ok($cr == $red && $cg == $green && $cb == $blue
132 && $ca == $alpha, $comment)) {
133 $builder->diag(<<END_DIAG);
146 sub is_fcolor4($$$$$$;$) {
147 my ($color, $red, $green, $blue, $alpha, $comment_or_diff, $comment_or_undef) = @_;
148 my ($comment, $mindiff);
149 if (defined $comment_or_undef) {
150 ( $mindiff, $comment ) = ( $comment_or_diff, $comment_or_undef )
153 ( $mindiff, $comment ) = ( 0.001, $comment_or_diff )
156 my $builder = Test::Builder->new;
158 unless (defined $color) {
159 $builder->ok(0, $comment);
160 $builder->diag("color is undef");
163 unless ($color->can('rgba')) {
164 $builder->ok(0, $comment);
165 $builder->diag("color is not a color object");
169 my ($cr, $cg, $cb, $ca) = $color->rgba;
170 unless ($builder->ok(abs($cr - $red) <= $mindiff
171 && abs($cg - $green) <= $mindiff
172 && abs($cb - $blue) <= $mindiff
173 && abs($ca - $alpha) <= $mindiff, $comment)) {
174 $builder->diag(<<END_DIAG);
188 my ($color, $grey, $comment) = @_;
190 my $builder = Test::Builder->new;
192 unless (defined $color) {
193 $builder->ok(0, $comment);
194 $builder->diag("color is undef");
197 unless ($color->can('rgba')) {
198 $builder->ok(0, $comment);
199 $builder->diag("color is not a color object");
203 my ($cgrey) = $color->rgba;
204 unless ($builder->ok($cgrey == $grey, $comment)) {
205 $builder->diag(<<END_DIAG);
207 Grey: $grey vs $cgrey
216 my $green=Imager::i_color_new(0,255,0,255);
217 my $blue=Imager::i_color_new(0,0,255,255);
218 my $red=Imager::i_color_new(255,0,0,255);
220 my $img=Imager::ImgRaw::new(150,150,3);
222 Imager::i_box_filled($img,70,25,130,125,$green);
223 Imager::i_box_filled($img,20,25,80,125,$blue);
224 Imager::i_arc($img,75,75,30,0,361,$red);
225 Imager::i_conv($img,[0.1, 0.2, 0.4, 0.2, 0.1]);
231 my $green = Imager::Color->new(0, 255, 0, 255);
232 my $blue = Imager::Color->new(0, 0, 255, 255);
233 my $red = Imager::Color->new(255, 0, 0, 255);
234 my $img = Imager->new(xsize => 150, ysize => 150);
235 $img->box(filled => 1, color => $green, box => [ 70, 24, 130, 124 ]);
236 $img->box(filled => 1, color => $blue, box => [ 20, 26, 80, 126 ]);
237 $img->arc(x => 75, y => 75, r => 30, color => $red);
238 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
244 my $green = Imager::Color->new(0, 255, 0, 255);
245 my $blue = Imager::Color->new(0, 0, 255, 255);
246 my $red = Imager::Color->new(255, 0, 0, 255);
247 my $img = Imager->new(xsize => 150, ysize => 150, bits => 16);
248 $img->box(filled => 1, color => $green, box => [ 70, 25, 130, 125 ]);
249 $img->box(filled => 1, color => $blue, box => [ 20, 25, 80, 125 ]);
250 $img->arc(x => 75, y => 75, r => 30, color => $red);
251 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
256 sub test_image_double {
257 my $green = Imager::Color->new(0, 255, 0, 255);
258 my $blue = Imager::Color->new(0, 0, 255, 255);
259 my $red = Imager::Color->new(255, 0, 0, 255);
260 my $img = Imager->new(xsize => 150, ysize => 150, bits => 'double');
261 $img->box(filled => 1, color => $green, box => [ 70, 25, 130, 125 ]);
262 $img->box(filled => 1, color => $blue, box => [ 20, 25, 80, 125 ]);
263 $img->arc(x => 75, y => 75, r => 30, color => $red);
264 $img->filter(type => 'conv', coef => [ 0.1, 0.2, 0.4, 0.2, 0.1 ]);
269 sub _low_image_diff_check {
270 my ($left, $right, $comment) = @_;
272 my $builder = Test::Builder->new;
274 unless (defined $left) {
275 $builder->ok(0, $comment);
276 $builder->diag("left is undef");
279 unless (defined $right) {
280 $builder->ok(0, $comment);
281 $builder->diag("right is undef");
284 unless ($left->{IMG}) {
285 $builder->ok(0, $comment);
286 $builder->diag("left image has no low level object");
289 unless ($right->{IMG}) {
290 $builder->ok(0, $comment);
291 $builder->diag("right image has no low level object");
294 unless ($left->getwidth == $right->getwidth) {
295 $builder->ok(0, $comment);
296 $builder->diag("left width " . $left->getwidth . " vs right width "
300 unless ($left->getheight == $right->getheight) {
301 $builder->ok(0, $comment);
302 $builder->diag("left height " . $left->getheight . " vs right height "
303 . $right->getheight);
306 unless ($left->getchannels == $right->getchannels) {
307 $builder->ok(0, $comment);
308 $builder->diag("left channels " . $left->getchannels . " vs right channels "
309 . $right->getchannels);
316 sub is_image_similar($$$$) {
317 my ($left, $right, $limit, $comment) = @_;
320 local $Test::Builder::Level = $Test::Builder::Level + 1;
322 _low_image_diff_check($left, $right, $comment)
326 my $builder = Test::Builder->new;
328 my $diff = Imager::i_img_diff($left->{IMG}, $right->{IMG});
329 if ($diff > $limit) {
330 $builder->ok(0, $comment);
331 $builder->diag("image data difference > $limit - $diff");
334 # find the first mismatch
336 for my $y (0 .. $left->getheight()-1) {
337 for my $x (0.. $left->getwidth()-1) {
338 my @lsamples = $left->getsamples(x => $x, y => $y, width => 1);
339 my @rsamples = $right->getsamples(x => $x, y => $y, width => 1);
340 if ("@lsamples" ne "@rsamples") {
341 $builder->diag("first mismatch at ($x, $y) - @lsamples vs @rsamples");
351 return $builder->ok(1, $comment);
355 my ($left, $right, $comment) = @_;
357 local $Test::Builder::Level = $Test::Builder::Level + 1;
359 return is_image_similar($left, $right, 0, $comment);
363 my ($left, $right, $comment) = @_;
366 local $Test::Builder::Level = $Test::Builder::Level + 1;
368 _low_image_diff_check($left, $right, $comment)
372 my $builder = Test::Builder->new;
374 my $diff = Imager::i_img_diffd($left->{IMG}, $right->{IMG});
376 $builder->ok(0, $comment);
377 $builder->diag("image data difference: $diff");
379 # find the first mismatch
381 for my $y (0 .. $left->getheight()-1) {
382 for my $x (0.. $left->getwidth()-1) {
383 my @lsamples = $left->getsamples(x => $x, y => $y, width => 1);
384 my @rsamples = $right->getsamples(x => $x, y => $y, width => 1);
385 if ("@lsamples" ne "@rsamples") {
386 $builder->diag("first mismatch at ($x, $y) - @lsamples vs @rsamples");
395 return $builder->ok(1, $comment);
399 my ($left, $right, $comment) = @_;
401 my $builder = Test::Builder->new;
403 my $diff = Imager::i_img_diff($left->{IMG}, $right->{IMG});
405 return $builder->ok($diff, "$comment");
408 sub image_bounds_checks {
411 my $builder = Test::Builder->new;
413 $builder->ok(!$im->getpixel(x => -1, y => 0), 'bounds check get (-1, 0)');
414 $builder->ok(!$im->getpixel(x => 10, y => 0), 'bounds check get (10, 0)');
415 $builder->ok(!$im->getpixel(x => 0, y => -1), 'bounds check get (0, -1)');
416 $builder->ok(!$im->getpixel(x => 0, y => 10), 'bounds check get (0, 10)');
417 $builder->ok(!$im->getpixel(x => -1, y => 0), 'bounds check get (-1, 0) float');
418 $builder->ok(!$im->getpixel(x => 10, y => 0), 'bounds check get (10, 0) float');
419 $builder->ok(!$im->getpixel(x => 0, y => -1), 'bounds check get (0, -1) float');
420 $builder->ok(!$im->getpixel(x => 0, y => 10), 'bounds check get (0, 10) float');
421 my $black = Imager::Color->new(0, 0, 0);
422 require Imager::Color::Float;
423 my $blackf = Imager::Color::Float->new(0, 0, 0);
424 $builder->ok(!$im->setpixel(x => -1, y => 0, color => $black), 'bounds check set (-1, 0)');
425 $builder->ok(!$im->setpixel(x => 10, y => 0, color => $black), 'bounds check set (10, 0)');
426 $builder->ok(!$im->setpixel(x => 0, y => -1, color => $black), 'bounds check set (0, -1)');
427 $builder->ok(!$im->setpixel(x => 0, y => 10, color => $black), 'bounds check set (0, 10)');
428 $builder->ok(!$im->setpixel(x => -1, y => 0, color => $blackf), 'bounds check set (-1, 0) float');
429 $builder->ok(!$im->setpixel(x => 10, y => 0, color => $blackf), 'bounds check set (10, 0) float');
430 $builder->ok(!$im->setpixel(x => 0, y => -1, color => $blackf), 'bounds check set (0, -1) float');
431 $builder->ok(!$im->setpixel(x => 0, y => 10, color => $blackf), 'bounds check set (0, 10) float');
434 sub test_colorf_gpix {
435 my ($im, $x, $y, $expected, $epsilon, $comment) = @_;
437 my $builder = Test::Builder->new;
439 defined $comment or $comment = '';
441 my $c = Imager::i_gpixf($im, $x, $y);
443 $builder->ok(0, "$comment - retrieve color at ($x,$y)");
446 unless ($builder->ok(colorf_cmp($c, $expected, $epsilon) == 0,
447 "$comment - got right color ($x, $y)")) {
449 my @exp = $expected->rgba;
450 $builder->diag(<<EOS);
451 # got: ($c[0], $c[1], $c[2])
452 # expected: ($exp[0], $exp[1], $exp[2])
458 sub test_color_gpix {
459 my ($im, $x, $y, $expected, $comment) = @_;
461 my $builder = Test::Builder->new;
463 defined $comment or $comment = '';
464 my $c = Imager::i_get_pixel($im, $x, $y);
466 $builder->ok(0, "$comment - retrieve color at ($x,$y)");
469 unless ($builder->ok(color_cmp($c, $expected) == 0,
470 "got right color ($x, $y)")) {
472 my @exp = $expected->rgba;
473 $builder->diag(<<EOS);
474 # got: ($c[0], $c[1], $c[2])
475 # expected: ($exp[0], $exp[1], $exp[2])
483 sub test_colorf_glin {
484 my ($im, $x, $y, $pels, $comment) = @_;
486 my $builder = Test::Builder->new;
488 my @got = Imager::i_glinf($im, $x, $x+@$pels, $y);
490 or return $builder->is_num(scalar(@got), scalar(@$pels), "$comment - pixels retrieved");
492 return $builder->ok(!grep(colorf_cmp($pels->[$_], $got[$_], 0.005), 0..$#got),
493 "$comment - check colors ($x, $y)");
497 my ($c1, $c2, $epsilon) = @_;
499 defined $epsilon or $epsilon = 0;
504 # print "# (",join(",", @s1[0..2]),") <=> (",join(",", @s2[0..2]),")\n";
505 return abs($s1[0]-$s2[0]) >= $epsilon && $s1[0] <=> $s2[0]
506 || abs($s1[1]-$s2[1]) >= $epsilon && $s1[1] <=> $s2[1]
507 || abs($s1[2]-$s2[2]) >= $epsilon && $s1[2] <=> $s2[2];
516 return $s1[0] <=> $s2[0]
518 || $s1[2] <=> $s2[2];
521 # these test the action of the channel mask on the image supplied
522 # which should be an OO image.
524 my ($im, $epsilon) = @_;
526 my $builder = Test::Builder->new;
528 defined $epsilon or $epsilon = 0;
530 # we want to check all four of ppix() and plin(), ppix() and plinf()
531 # basic test procedure:
532 # first using default/all 1s mask, set to white
533 # make sure we got white
534 # set mask to skip a channel, set to grey
535 # make sure only the right channels set
537 print "# channel mask tests\n";
539 my $white = Imager::NC(255, 255, 255);
540 my $grey = Imager::NC(128, 128, 128);
541 my $white_grey = Imager::NC(128, 255, 128);
543 print "# with ppix\n";
544 $builder->ok($im->setmask(mask=>~0), "set to default mask");
545 $builder->ok($im->setpixel(x=>0, 'y'=>0, color=>$white), "set to white all channels");
546 test_color_gpix($im->{IMG}, 0, 0, $white, "ppix");
547 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
548 $builder->ok($im->setpixel(x=>0, 'y'=>0, color=>$grey), "set to grey, no channel 2");
549 test_color_gpix($im->{IMG}, 0, 0, $white_grey, "ppix masked");
551 print "# with plin\n";
552 $builder->ok($im->setmask(mask=>~0), "set to default mask");
553 $builder->ok($im->setscanline(x=>0, 'y'=>1, pixels => [$white]),
554 "set to white all channels");
555 test_color_gpix($im->{IMG}, 0, 1, $white, "plin");
556 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
557 $builder->ok($im->setscanline(x=>0, 'y'=>1, pixels=>[$grey]),
558 "set to grey, no channel 2");
559 test_color_gpix($im->{IMG}, 0, 1, $white_grey, "plin masked");
562 my $whitef = Imager::NCF(1.0, 1.0, 1.0);
563 my $greyf = Imager::NCF(0.5, 0.5, 0.5);
564 my $white_greyf = Imager::NCF(0.5, 1.0, 0.5);
566 print "# with ppixf\n";
567 $builder->ok($im->setmask(mask=>~0), "set to default mask");
568 $builder->ok($im->setpixel(x=>0, 'y'=>2, color=>$whitef), "set to white all channels");
569 test_colorf_gpix($im->{IMG}, 0, 2, $whitef, $epsilon, "ppixf");
570 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
571 $builder->ok($im->setpixel(x=>0, 'y'=>2, color=>$greyf), "set to grey, no channel 2");
572 test_colorf_gpix($im->{IMG}, 0, 2, $white_greyf, $epsilon, "ppixf masked");
574 print "# with plinf\n";
575 $builder->ok($im->setmask(mask=>~0), "set to default mask");
576 $builder->ok($im->setscanline(x=>0, 'y'=>3, pixels => [$whitef]),
577 "set to white all channels");
578 test_colorf_gpix($im->{IMG}, 0, 3, $whitef, $epsilon, "plinf");
579 $builder->ok($im->setmask(mask=>0xF-0x2), "set channel to exclude channel1");
580 $builder->ok($im->setscanline(x=>0, 'y'=>3, pixels=>[$greyf]),
581 "set to grey, no channel 2");
582 test_colorf_gpix($im->{IMG}, 0, 3, $white_greyf, $epsilon, "plinf masked");
592 Imager::Test - common functions used in testing Imager
596 use Imager::Test 'diff_text_with_nul';
597 diff_text_with_nul($test_name, $text1, $text2, @string_options);
601 This is a repository of functions used in testing Imager.
603 Some functions will only be useful in testing Imager itself, while
604 others should be useful in testing modules that use Imager.
606 No functions are exported by default.
614 =item is_color3($color, $red, $blue, $green, $comment)
616 Tests is $color matches the given ($red, $blue, $green)
618 =item is_image($im1, $im2, $comment)
620 Tests if the 2 images have the same content. Both images must be
621 defined, have the same width, height, channels and the same color in
622 each pixel. The color comparison is done at 8-bits per pixel. The
623 color representation such as direct vs paletted, bits per sample are
624 not checked. Equivalent to is_image_similar($im1, $im2, 0, $comment).
626 =item is_imaged($im, $im2, $comment)
628 Tests if the two images have the same content at the double/sample
631 =item is_image_similar($im1, $im2, $maxdiff, $comment)
633 Tests if the 2 images have similar content. Both images must be
634 defined, have the same width, height and channels. The cum of the
635 squares of the differences of each sample are calculated and must be
636 less than or equal to I<$maxdiff> for the test to pass. The color
637 comparison is done at 8-bits per pixel. The color representation such
638 as direct vs paletted, bits per sample are not checked.
640 =item test_image_raw()
642 Returns a 150x150x3 Imager::ImgRaw test image.
646 Returns a 150x150x3 8-bit/sample OO test image.
648 =item test_image_16()
650 Returns a 150x150x3 16-bit/sample OO test image.
652 =item test_image_double()
654 Returns a 150x150x3 double/sample OO test image.
656 =item diff_text_with_nul($test_name, $text1, $text2, @options)
658 Creates 2 test images and writes $text1 to the first image and $text2
659 to the second image with the string() method. Each call adds 3
660 C<ok>/C<not ok> to the output of the test script.
662 Extra options that should be supplied include the font and either a
663 color or channel parameter.
665 This was explicitly created for regression tests on #21770.
667 =item image_bounds_checks($im)
669 Attempts to write to various pixel positions outside the edge of the
670 image to ensure that it fails in those locations.
672 Any new image type should pass these tests. Does 16 separate tests.
674 =item test_colorf_gpix($im, $x, $y, $expected, $epsilon, $comment)
676 Retrieves the pixel ($x,$y) from the low-level image $im and compares
677 it to the floating point color $expected, with a tolerance of epsilon.
679 =item test_color_gpix($im, $x, $y, $expected, $comment)
681 Retrieves the pixel ($x,$y) from the low-level image $im and compares
682 it to the floating point color $expected.
684 =item test_colorf_glin($im, $x, $y, $pels, $comment)
686 Retrieves the floating point pixels ($x, $y)-[$x+@$pels, $y] from the
687 low level image $im and compares them against @$pels.
689 =item mask_tests($im, $epsilon)
691 Perform a standard set of mask tests on the OO image $im.
697 Tony Cook <tony@develop-help.com>