- use scanline oriented operations to flip images instead of pixel
[imager.git] / t / t64copyflip.t
1 #!perl -w
2 use strict;
3 use Test::More tests => 69;
4 use Imager;
5 use Imager::Test qw(is_color3 is_image is_imaged test_image_double);
6
7 #$Imager::DEBUG=1;
8
9 Imager::init('log'=>'testout/t64copyflip.log');
10
11 my $img=Imager->new() or die "unable to create image object\n";
12
13 $img->open(file=>'testimg/scale.ppm',type=>'pnm');
14 my $nimg = $img->copy();
15 ok($nimg, "copy returned something");
16
17 # test if ->copy() works
18
19 my $diff = Imager::i_img_diff($img->{IMG}, $nimg->{IMG});
20 is_image($img, $nimg, "copy matches source");
21
22 # test if ->flip(dir=>'h')->flip(dir=>'h') doesn't alter the image
23 $nimg->flip(dir=>"h")->flip(dir=>"h");
24 is_image($nimg, $img, "double horiz flipped matches original");
25
26 # test if ->flip(dir=>'v')->flip(dir=>'v') doesn't alter the image
27 $nimg->flip(dir=>"v")->flip(dir=>"v");
28 is_image($nimg, $img, "double vertically flipped image matches original");
29
30
31 # test if ->flip(dir=>'h')->flip(dir=>'v') is same as ->flip(dir=>'hv')
32 $nimg->flip(dir=>"v")->flip(dir=>"h")->flip(dir=>"hv");;
33 is_image($img, $nimg, "check flip with hv matches flip v then flip h");
34
35 {
36   my $imsrc = test_image_double;
37   my $imcp = $imsrc->copy;
38   is_imaged($imsrc, $imcp, "copy double image");
39   $imcp->flip(dir=>"v")->flip(dir=>"v");
40   is_imaged($imsrc, $imcp, "flip v twice");
41   $imcp->flip(dir=>"h")->flip(dir=>"h");
42   is_imaged($imsrc, $imcp, "flip h twice");
43   $imcp->flip(dir=>"h")->flip(dir=>"v")->flip(dir=>"hv");
44   is_imaged($imsrc, $imcp, "flip h,v,hv twice");
45 }
46
47 rot_test($img, 90, 4);
48 rot_test($img, 180, 2);
49 rot_test($img, 270, 4);
50 rot_test($img, 0, 1);
51
52 my $pimg = $img->to_paletted();
53 rot_test($pimg, 90, 4);
54 rot_test($pimg, 180, 2);
55 rot_test($pimg, 270, 4);
56 rot_test($pimg, 0, 1);
57
58 my $timg = $img->rotate(right=>90)->rotate(right=>270);
59 is(Imager::i_img_diff($img->{IMG}, $timg->{IMG}), 0,
60    "check rotate 90 then 270 matches original");
61 $timg = $img->rotate(right=>90)->rotate(right=>180)->rotate(right=>90);
62 is(Imager::i_img_diff($img->{IMG}, $timg->{IMG}), 0,
63      "check rotate 90 then 180 then 90 matches original");
64
65 # this could use more tests
66 my $rimg = $img->rotate(degrees=>10);
67 ok($rimg, "rotation by 10 degrees gave us an image");
68 if (!$rimg->write(file=>"testout/t64_rot10.ppm")) {
69   print "# Cannot save: ",$rimg->errstr,"\n";
70 }
71
72 # rotate with background
73 $rimg = $img->rotate(degrees=>10, back=>Imager::Color->new(builtin=>'red'));
74 ok($rimg, "rotate with background gave us an image");
75 if (!$rimg->write(file=>"testout/t64_rot10_back.ppm")) {
76   print "# Cannot save: ",$rimg->errstr,"\n";
77 }
78
79 {
80   # rotate with text background
81   my $rimg = $img->rotate(degrees => 45, back => '#FF00FF');
82   ok($rimg, "rotate with background as text gave us an image");
83   
84   # check the color set correctly
85   my $c = $rimg->getpixel(x => 0, 'y' => 0);
86   is_deeply([ 255, 0, 255 ], [ ($c->rgba)[0, 1, 2] ],
87             "check background set correctly");
88
89   # check error handling for background color
90   $rimg = $img->rotate(degrees => 45, back => "some really unknown color");
91   ok(!$rimg, "should fail due to bad back color");
92   cmp_ok($img->errstr, '=~', "^No color named ", "check error message");
93 }
94
95 my $trimg = $img->matrix_transform(matrix=>[ 1.2, 0, 0,
96                                              0,   1, 0,
97                                              0,   0, 1]);
98 ok($trimg, "matrix_transform() returned an image");
99 $trimg->write(file=>"testout/t64_trans.ppm")
100   or print "# Cannot save: ",$trimg->errstr,"\n";
101
102 $trimg = $img->matrix_transform(matrix=>[ 1.2, 0, 0,
103                                              0,   1, 0,
104                                              0,   0, 1],
105                                    back=>Imager::Color->new(builtin=>'blue'));
106 ok($trimg, "matrix_transform() with back returned an image");
107
108 $trimg->write(file=>"testout/t64_trans_back.ppm")
109   or print "# Cannot save: ",$trimg->errstr,"\n";
110
111 sub rot_test {
112   my ($src, $degrees, $count) = @_;
113
114   my $cimg = $src->copy();
115   my $in;
116   for (1..$count) {
117     $in = $cimg;
118     $cimg = $cimg->rotate(right=>$degrees)
119       or last;
120   }
121  SKIP:
122   {
123     ok($cimg, "got a rotated image")
124       or skip("no image to check", 4);
125     my $diff = Imager::i_img_diff($src->{IMG}, $cimg->{IMG});
126     is($diff, 0, "check it matches source")
127       or skip("didn't match", 3);
128
129     # check that other parameters match
130     is($src->type, $cimg->type, "type check");
131     is($src->bits, $cimg->bits, "bits check");
132     is($src->getchannels, $cimg->getchannels, "channels check");
133   }
134 }
135
136 { # http://rt.cpan.org/NoAuth/Bug.html?id=9672
137   my $warning;
138   local $SIG{__WARN__} = 
139     sub { 
140       $warning = "@_";
141       my $printed = $warning;
142       $printed =~ s/\n$//;
143       $printed =~ s/\n/\n\#/g; 
144       print "# ",$printed, "\n";
145     };
146   my $img = Imager->new(xsize=>10, ysize=>10);
147   $img->copy();
148   cmp_ok($warning, '=~', 'void', "correct warning");
149   cmp_ok($warning, '=~', 't64copyflip\\.t', "correct file");
150   $warning = '';
151   $img->rotate(degrees=>5);
152   cmp_ok($warning, '=~', 'void', "correct warning");
153   cmp_ok($warning, '=~', 't64copyflip\\.t', "correct file");
154   $warning = '';
155   $img->matrix_transform(matrix=>[1, 1, 1]);
156   cmp_ok($warning, '=~', 'void', "correct warning");
157   cmp_ok($warning, '=~', 't64copyflip\\.t', "correct file");
158 }
159
160 {
161   # 29936 - matrix_transform() should use fabs() instead of abs()
162   # range checking sz 
163
164   # this meant that when sz was < 1 (which it often is for these
165   # transformations), it treated the values out of range, producing a
166   # blank output image
167
168   my $src = Imager->new(xsize => 20, ysize => 20);
169   $src->box(filled => 1, color => 'FF0000');
170   my $out = $src->matrix_transform(matrix => [ 1, 0, 0,
171                                                0, 1, 0,
172                                                0, 0, 0.9999 ])
173     or print "# ", $src->errstr, "\n";
174   my $blank = Imager->new(xsize => 20, ysize => 20);
175   # they have to be different, surely that would be easy
176   my $diff = Imager::i_img_diff($out->{IMG}, $blank->{IMG});
177   ok($diff, "RT#29936 - check non-blank output");
178 }
179
180 {
181   my $im = Imager->new(xsize => 10, ysize => 10, channels => 4);
182   $im->box(filled => 1, color => 'FF0000');
183   my $back = Imager::Color->new(0, 0, 0, 0);
184   my $rot = $im->rotate(degrees => 10, back => $back);
185   # drop the alpha and make sure there's only 2 colors used
186   my $work = $rot->convert(preset => 'noalpha');
187   my $im_pal = $work->to_paletted(make_colors => 'mediancut');
188   my @colors = $im_pal->getcolors;
189   is(@colors, 2, "should be only 2 colors");
190   @colors = sort { ($a->rgba)[0] <=> ($b->rgba)[0] } @colors;
191   is_color3($colors[0], 0, 0, 0, "check we got black");
192   is_color3($colors[1], 255, 0, 0, "and red");
193 }