Commit | Line | Data |
---|---|---|
f1ac5027 TC |
1 | #!perl -w |
2 | use strict; | |
3 | ||
2de568dc | 4 | print "1..40\n"; |
efdc2568 | 5 | |
f1ac5027 TC |
6 | use Imager ':handy'; |
7 | use Imager::Fill; | |
8 | use Imager::Color::Float; | |
9 | ||
efdc2568 | 10 | sub ok ($$$); |
f1ac5027 | 11 | |
efdc2568 | 12 | Imager::init_log("testout/t20fill.log", 1); |
f1ac5027 TC |
13 | |
14 | my $blue = NC(0,0,255); | |
15 | my $red = NC(255, 0, 0); | |
16 | my $redf = Imager::Color::Float->new(1, 0, 0); | |
17 | my $rsolid = Imager::i_new_fill_solid($blue, 0); | |
18 | ok(1, $rsolid, "building solid fill"); | |
19 | my $raw1 = Imager::ImgRaw::new(100, 100, 3); | |
20 | # use the normal filled box | |
21 | Imager::i_box_filled($raw1, 0, 0, 99, 99, $blue); | |
22 | my $raw2 = Imager::ImgRaw::new(100, 100, 3); | |
23 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rsolid); | |
24 | ok(2, 1, "drawing with solid fill"); | |
25 | my $diff = Imager::i_img_diff($raw1, $raw2); | |
26 | ok(3, $diff == 0, "solid fill doesn't match"); | |
27 | Imager::i_box_filled($raw1, 0, 0, 99, 99, $red); | |
28 | my $rsolid2 = Imager::i_new_fill_solidf($redf, 0); | |
29 | ok(4, $rsolid2, "creating float solid fill"); | |
30 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rsolid2); | |
31 | $diff = Imager::i_img_diff($raw1, $raw2); | |
32 | ok(5, $diff == 0, "float solid fill doesn't match"); | |
33 | ||
34 | # ok solid still works, let's try a hatch | |
35 | # hash1 is a 2x2 checkerboard | |
36 | my $rhatcha = Imager::i_new_fill_hatch($red, $blue, 0, 1, undef, 0, 0); | |
37 | my $rhatchb = Imager::i_new_fill_hatch($blue, $red, 0, 1, undef, 2, 0); | |
38 | ok(6, $rhatcha && $rhatchb, "can't build hatched fill"); | |
39 | ||
40 | # the offset should make these match | |
41 | Imager::i_box_cfill($raw1, 0, 0, 99, 99, $rhatcha); | |
42 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rhatchb); | |
43 | ok(7, 1, "filling with hatch"); | |
44 | $diff = Imager::i_img_diff($raw1, $raw2); | |
45 | ok(8, $diff == 0, "hatch images different"); | |
46 | $rhatchb = Imager::i_new_fill_hatch($blue, $red, 0, 1, undef, 4, 6); | |
47 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rhatchb); | |
48 | $diff = Imager::i_img_diff($raw1, $raw2); | |
49 | ok(9, $diff == 0, "hatch images different"); | |
50 | ||
51 | # I guess I was tired when I originally did this - make sure it keeps | |
52 | # acting the way it's meant to | |
53 | # I had originally expected these to match with the red and blue swapped | |
54 | $rhatchb = Imager::i_new_fill_hatch($red, $blue, 0, 1, undef, 2, 2); | |
55 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rhatchb); | |
56 | $diff = Imager::i_img_diff($raw1, $raw2); | |
57 | ok(10, $diff == 0, "hatch images different"); | |
58 | ||
59 | # this shouldn't match | |
60 | $rhatchb = Imager::i_new_fill_hatch($red, $blue, 0, 1, undef, 1, 1); | |
61 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rhatchb); | |
62 | $diff = Imager::i_img_diff($raw1, $raw2); | |
63 | ok(11, $diff, "hatch images the same!"); | |
64 | ||
65 | # custom hatch | |
66 | # the inverse of the 2x2 checkerboard | |
67 | my $hatch = pack("C8", 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC); | |
68 | my $rcustom = Imager::i_new_fill_hatch($blue, $red, 0, 0, $hatch, 0, 0); | |
69 | Imager::i_box_cfill($raw2, 0, 0, 99, 99, $rcustom); | |
70 | $diff = Imager::i_img_diff($raw1, $raw2); | |
71 | ok(12, !$diff, "custom hatch mismatch"); | |
72 | ||
73 | # test the oo interface | |
74 | my $im1 = Imager->new(xsize=>100, ysize=>100); | |
75 | my $im2 = Imager->new(xsize=>100, ysize=>100); | |
76 | ||
efdc2568 | 77 | my $solid = Imager::Fill->new(solid=>'#FF0000'); |
f1ac5027 TC |
78 | ok(13, $solid, "creating oo solid fill"); |
79 | ok(14, $solid->{fill}, "bad oo solid fill"); | |
80 | $im1->box(fill=>$solid); | |
81 | $im2->box(filled=>1, color=>$red); | |
82 | $diff = Imager::i_img_diff($im1->{IMG}, $im2->{IMG}); | |
83 | ok(15, !$diff, "oo solid fill"); | |
84 | ||
85 | my $hatcha = Imager::Fill->new(hatch=>'check2x2'); | |
86 | my $hatchb = Imager::Fill->new(hatch=>'check2x2', dx=>2); | |
87 | $im1->box(fill=>$hatcha); | |
88 | $im2->box(fill=>$hatchb); | |
89 | # should be different | |
90 | $diff = Imager::i_img_diff($im1->{IMG}, $im2->{IMG}); | |
91 | ok(16, $diff, "offset checks the same!"); | |
92 | $hatchb = Imager::Fill->new(hatch=>'check2x2', dx=>2, dy=>2); | |
93 | $im2->box(fill=>$hatchb); | |
94 | $diff = Imager::i_img_diff($im1->{IMG}, $im2->{IMG}); | |
95 | ok(17, !$diff, "offset into similar check should be the same"); | |
96 | ||
97 | # test dymanic build of fill | |
98 | $im2->box(fill=>{hatch=>'check2x2', dx=>2, fg=>NC(255,255,255), | |
99 | bg=>NC(0,0,0)}); | |
100 | $diff = Imager::i_img_diff($im1->{IMG}, $im2->{IMG}); | |
101 | ok(18, !$diff, "offset and flipped should be the same"); | |
102 | ||
103 | # a simple demo | |
104 | my $im = Imager->new(xsize=>200, ysize=>200); | |
105 | ||
106 | $im->box(xmin=>10, ymin=>10, xmax=>190, ymax=>190, | |
107 | fill=>{ hatch=>'check4x4', | |
108 | fg=>NC(128, 0, 0), | |
569795e8 TC |
109 | bg=>NC(128, 64, 0) }) |
110 | or print "# ",$im->errstr,"\n"; | |
f1ac5027 TC |
111 | $im->arc(r=>80, d1=>45, d2=>75, |
112 | fill=>{ hatch=>'stipple2', | |
113 | combine=>1, | |
efdc2568 | 114 | fg=>[ 0, 0, 0, 255 ], |
569795e8 TC |
115 | bg=>{ rgba=>[255,255,255,160] } }) |
116 | or print "# ",$im->errstr,"\n"; | |
f1ac5027 | 117 | $im->arc(r=>80, d1=>75, d2=>135, |
569795e8 TC |
118 | fill=>{ fountain=>'radial', xa=>100, ya=>100, xb=>20, yb=>100 }) |
119 | or print "# ",$im->errstr,"\n"; | |
f1ac5027 TC |
120 | $im->write(file=>'testout/t20_sample.ppm'); |
121 | ||
cc6483e0 TC |
122 | # flood fill tests |
123 | my $rffimg = Imager::ImgRaw::new(100, 100, 3); | |
124 | # build a H | |
125 | Imager::i_box_filled($rffimg, 10, 10, 20, 90, $blue); | |
126 | Imager::i_box_filled($rffimg, 80, 10, 90, 90, $blue); | |
127 | Imager::i_box_filled($rffimg, 20, 45, 80, 55, $blue); | |
128 | my $black = Imager::Color->new(0, 0, 0); | |
129 | Imager::i_flood_fill($rffimg, 15, 15, $red); | |
130 | my $rffcmp = Imager::ImgRaw::new(100, 100, 3); | |
131 | # build a H | |
132 | Imager::i_box_filled($rffcmp, 10, 10, 20, 90, $red); | |
133 | Imager::i_box_filled($rffcmp, 80, 10, 90, 90, $red); | |
134 | Imager::i_box_filled($rffcmp, 20, 45, 80, 55, $red); | |
135 | $diff = Imager::i_img_diff($rffimg, $rffcmp); | |
136 | ok(19, !$diff, "flood fill difference"); | |
137 | ||
138 | my $ffim = Imager->new(xsize=>100, ysize=>100); | |
139 | my $yellow = Imager::Color->new(255, 255, 0); | |
140 | $ffim->box(xmin=>10, ymin=>10, xmax=>20, ymax=>90, color=>$blue, filled=>1); | |
141 | $ffim->box(xmin=>20, ymin=>45, xmax=>80, ymax=>55, color=>$blue, filled=>1); | |
142 | $ffim->box(xmin=>80, ymin=>10, xmax=>90, ymax=>90, color=>$blue, filled=>1); | |
9d540150 | 143 | ok(20, $ffim->flood_fill('x'=>50, 'y'=>50, color=>$red), "flood fill"); |
cc6483e0 TC |
144 | $diff = Imager::i_img_diff($rffcmp, $ffim->{IMG}); |
145 | ok(21, !$diff, "oo flood fill difference"); | |
9d540150 | 146 | $ffim->flood_fill('x'=>50, 'y'=>50, |
cc6483e0 TC |
147 | fill=> { |
148 | hatch => 'check2x2' | |
149 | }); | |
150 | # fill=>{ | |
151 | # fountain=>'radial', | |
152 | # xa=>50, ya=>50, | |
153 | # xb=>10, yb=>10, | |
154 | # }); | |
155 | $ffim->write(file=>'testout/t20_ooflood.ppm'); | |
156 | ||
efdc2568 TC |
157 | # test combining modes |
158 | my $fill = NC(192, 128, 128, 128); | |
159 | my $target = NC(64, 32, 64); | |
160 | my %comb_tests = | |
161 | ( | |
162 | none=>{ result=>$fill }, | |
163 | normal=>{ result=>NC(128, 80, 96) }, | |
164 | multiply => { result=>NC(56, 24, 48) }, | |
165 | dissolve => { result=>[ $target, NC(128, 80, 96) ] }, | |
166 | add => { result=>NC(159, 96, 128) }, | |
167 | subtract => { result=>NC(31, 15, 31) }, # 31.87, 15.9, 31.87 | |
168 | diff => { result=>NC(96, 64, 64) }, | |
169 | lighten => { result=>NC(128, 80, 96) }, | |
170 | darken => { result=>$target }, | |
171 | # the following results are based on the results of the tests and | |
172 | # are suspect for that reason (and were broken at one point <sigh>) | |
173 | # but trying to work them out manually just makes my head hurt - TC | |
44193b81 | 174 | hue => { result=>NC(64, 32, 47) }, |
efdc2568 TC |
175 | saturation => { result=>NC(63, 37, 64) }, |
176 | value => { result=>NC(127, 64, 128) }, | |
177 | color => { result=>NC(64, 37, 52) }, | |
178 | ); | |
179 | ||
180 | my $testnum = 22; # from 22 to 34 | |
181 | for my $comb (Imager::Fill->combines) { | |
182 | my $test = $comb_tests{$comb}; | |
183 | my $targim = Imager->new(xsize=>1, ysize=>1); | |
184 | $targim->box(filled=>1, color=>$target); | |
185 | my $fillobj = Imager::Fill->new(solid=>$fill, combine=>$comb); | |
186 | $targim->box(fill=>$fillobj); | |
187 | my $c = Imager::i_get_pixel($targim->{IMG}, 0, 0); | |
188 | if ($test->{result} =~ /ARRAY/) { | |
189 | ok($testnum++, scalar grep(color_close($_, $c), @{$test->{result}}), | |
190 | "combine '$comb'") | |
191 | or print "# got:",join(",", $c->rgba)," allowed: ", | |
192 | join("|", map { join(",", $_->rgba) } @{$test->{result}}),"\n"; | |
193 | } | |
194 | else { | |
195 | ok($testnum++, color_close($c, $test->{result}), "combine '$comb'") | |
196 | or print "# got: ",join(",", $c->rgba), | |
197 | " allowed: ",join(",", $test->{result}->rgba),"\n"; | |
198 | } | |
199 | } | |
200 | ||
0d321238 TC |
201 | ok($testnum++, $ffim->arc(r=>45, color=>$blue, aa=>1), "aa circle"); |
202 | $ffim->write(file=>"testout/t20_aacircle.ppm"); | |
203 | ||
f576ce7e TC |
204 | # image based fills |
205 | my $green = NC(0, 255, 0); | |
206 | my $fillim = Imager->new(xsize=>40, ysize=>40, channels=>4); | |
207 | $fillim->box(filled=>1, xmin=>5, ymin=>5, xmax=>35, ymax=>35, | |
208 | color=>NC(0, 0, 255, 128)); | |
209 | $fillim->arc(filled=>1, r=>10, color=>$green, aa=>1); | |
210 | my $ooim = Imager->new(xsize=>150, ysize=>150); | |
211 | $ooim->box(filled=>1, color=>$green, xmin=>70, ymin=>25, xmax=>130, ymax=>125); | |
212 | $ooim->box(filled=>1, color=>$blue, xmin=>20, ymin=>25, xmax=>80, ymax=>125); | |
213 | $ooim->arc(r=>30, color=>$red, aa=>1); | |
214 | ||
215 | my $oocopy = $ooim->copy(); | |
216 | ok($testnum++, | |
217 | $oocopy->arc(fill=>{image=>$fillim, | |
218 | combine=>'normal', | |
219 | xoff=>5}, r=>40), | |
220 | "image based fill"); | |
221 | $oocopy->write(file=>'testout/t20_image.ppm'); | |
222 | ||
223 | # a more complex version | |
224 | use Imager::Matrix2d ':handy'; | |
225 | $oocopy = $ooim->copy; | |
226 | ok($testnum++, | |
227 | $oocopy->arc(fill=>{ | |
228 | image=>$fillim, | |
229 | combine=>'normal', | |
230 | matrix=>m2d_rotate(degrees=>30), | |
231 | xoff=>5 | |
232 | }, r=>40), | |
233 | "transformed image based fill"); | |
234 | $oocopy->write(file=>'testout/t20_image_xform.ppm'); | |
235 | ||
569795e8 TC |
236 | ok($testnum++, |
237 | !$oocopy->arc(fill=>{ hatch=>"not really a hatch" }, r=>20), | |
238 | "error handling of automatic fill conversion"); | |
239 | ok($testnum++, | |
240 | $oocopy->errstr =~ /Unknown hatch type/, | |
241 | "error message for automatic fill conversion"); | |
242 | ||
2de568dc TC |
243 | # previous box fills to float images, or using the fountain fill |
244 | # got into a loop here | |
245 | { | |
246 | local $SIG{ALRM} = sub { die; }; | |
247 | ||
248 | eval { | |
249 | alarm(2); | |
250 | ok($testnum, | |
251 | $ooim->box(xmin=>20, ymin=>20, xmax=>80, ymax=>40, | |
252 | fill=>{ fountain=>'linear', xa=>20, ya=>20, xb=>80, | |
253 | yb=>20 }), "linear box fill"); | |
254 | ++$testnum; | |
255 | }; | |
256 | $@ and ok($testnum++, 0, "linear box fill alarmed"); | |
257 | } | |
258 | ||
efdc2568 | 259 | sub ok ($$$) { |
f1ac5027 TC |
260 | my ($num, $test, $desc) = @_; |
261 | ||
262 | if ($test) { | |
263 | print "ok $num\n"; | |
264 | } | |
265 | else { | |
266 | print "not ok $num # $desc\n"; | |
267 | } | |
efdc2568 TC |
268 | $test; |
269 | } | |
270 | ||
271 | sub color_close { | |
272 | my ($c1, $c2) = @_; | |
273 | ||
274 | my @c1 = $c1->rgba; | |
275 | my @c2 = $c2->rgba; | |
276 | ||
277 | for my $i (0..2) { | |
278 | if (abs($c1[$i]-$c2[$i]) > 2) { | |
279 | return 0; | |
280 | } | |
281 | } | |
282 | return 1; | |
f1ac5027 TC |
283 | } |
284 | ||
285 | # for use during testing | |
286 | sub save { | |
287 | my ($im, $name) = @_; | |
288 | ||
289 | open FH, "> $name" or die "Cannot create $name: $!"; | |
290 | binmode FH; | |
291 | my $io = Imager::io_new_fd(fileno(FH)); | |
292 | Imager::i_writeppm_wiol($im, $io) or die "Cannot save to $name"; | |
293 | undef $io; | |
294 | close FH; | |
295 | } |