use a convolution kernel size based on the stddev rather than a
[imager.git] / t / t61filters.t
CommitLineData
d08b8f85
TC
1#!perl -w
2use strict;
3use Imager qw(:handy);
73962964 4use Test::More tests => 69;
f1ac5027 5Imager::init_log("testout/t61filters.log", 1);
73962964 6use Imager::Test qw(is_image_similar);
d08b8f85
TC
7# meant for testing the filters themselves
8my $imbase = Imager->new;
9$imbase->open(file=>'testout/t104.ppm') or die;
10my $im_other = Imager->new(xsize=>150, ysize=>150);
11$im_other->box(xmin=>30, ymin=>60, xmax=>120, ymax=>90, filled=>1);
12
8c3ff7d9 13test($imbase, {type=>'autolevels'}, 'testout/t61_autolev.ppm');
d08b8f85 14
8c3ff7d9 15test($imbase, {type=>'contrast', intensity=>0.5},
d08b8f85
TC
16 'testout/t61_contrast.ppm');
17
18# this one's kind of cool
8c3ff7d9 19test($imbase, {type=>'conv', coef=>[ -0.5, 1, -0.5, ], },
d08b8f85
TC
20 'testout/t61_conv.ppm');
21
73962964
TC
22{
23 my $gauss = test($imbase, {type=>'gaussian', stddev=>5 },
24 'testout/t61_gaussian.ppm');
25
26 my $imbase16 = $imbase->to_rgb16;
27 my $gauss16 = test($imbase16, {type=>'gaussian', stddev=>5 },
28 'testout/t61_gaussian16.ppm');
29 is_image_similar($gauss, $gauss16, 200000, "8 and 16 gaussian match");
30}
31
d08b8f85 32
8c3ff7d9 33test($imbase, { type=>'gradgen', dist=>1,
d08b8f85
TC
34 xo=>[ 10, 10, 120 ],
35 yo=>[ 10, 140, 60 ],
36 colors=> [ NC('#FF0000'), NC('#FFFF00'), NC('#00FFFF') ]},
37 'testout/t61_gradgen.ppm');
38
8c3ff7d9 39test($imbase, {type=>'mosaic', size=>8}, 'testout/t61_mosaic.ppm');
d08b8f85 40
8c3ff7d9 41test($imbase, {type=>'hardinvert'}, 'testout/t61_hardinvert.ppm');
d08b8f85 42
8c3ff7d9 43test($imbase, {type=>'noise'}, 'testout/t61_noise.ppm');
d08b8f85 44
8c3ff7d9 45test($imbase, {type=>'radnoise'}, 'testout/t61_radnoise.ppm');
d08b8f85 46
8c3ff7d9 47test($imbase, {type=>'turbnoise'}, 'testout/t61_turbnoise.ppm');
d08b8f85 48
8c3ff7d9 49test($imbase, {type=>'bumpmap', bump=>$im_other, lightx=>30, lighty=>30},
d08b8f85
TC
50 'testout/t61_bumpmap.ppm');
51
8c3ff7d9 52test($imbase, {type=>'bumpmap_complex', bump=>$im_other}, 'testout/t61_bumpmap_complex.ppm');
d08b8f85 53
8c3ff7d9 54test($imbase, {type=>'postlevels', levels=>3}, 'testout/t61_postlevels.ppm');
b2778574 55
8c3ff7d9 56test($imbase, {type=>'watermark', wmark=>$im_other },
d08b8f85
TC
57 'testout/t61_watermark.ppm');
58
8c3ff7d9
TC
59test($imbase, {type=>'fountain', xa=>75, ya=>75, xb=>85, yb=>30,
60 repeat=>'triangle', #ftype=>'radial',
61 super_sample=>'circle', ssample_param => 16,
62 },
6607600c
TC
63 'testout/t61_fountain.ppm');
64use Imager::Fountain;
65
66my $f1 = Imager::Fountain->new;
67$f1->add(end=>0.2, c0=>NC(255, 0,0), c1=>NC(255, 255,0));
68$f1->add(start=>0.2, c0=>NC(255,255,0), c1=>NC(0,0,255,0));
8c3ff7d9
TC
69test($imbase, { type=>'fountain', xa=>20, ya=>130, xb=>130, yb=>20,
70 #repeat=>'triangle',
71 segments=>$f1
72 },
6607600c
TC
73 'testout/t61_fountain2.ppm');
74my $f2 = Imager::Fountain->new
75 ->add(end=>0.5, c0=>NC(255,0,0), c1=>NC(255,0,0), color=>'hueup')
76 ->add(start=>0.5, c0=>NC(255,0,0), c1=>NC(255,0,0), color=>'huedown');
77#use Data::Dumper;
78#print Dumper($f2);
8c3ff7d9 79test($imbase, { type=>'fountain', xa=>20, ya=>130, xb=>130, yb=>20,
6607600c
TC
80 segments=>$f2 },
81 'testout/t61_fount_hsv.ppm');
8c3ff7d9
TC
82my $f3 = Imager::Fountain->read(gimp=>'testimg/gimpgrad');
83ok($f3, "read gimpgrad");
84test($imbase, { type=>'fountain', xa=>75, ya=>75, xb=>90, yb=>15,
6607600c 85 segments=>$f3, super_sample=>'grid',
efdc2568 86 ftype=>'radial_square', combine=>'color' },
6607600c 87 'testout/t61_fount_gimp.ppm');
8c3ff7d9 88test($imbase, { type=>'unsharpmask', stddev=>2.0 },
b6381851 89 'testout/t61_unsharp.ppm');
8c3ff7d9 90test($imbase, {type=>'conv', coef=>[ -1, 3, -1, ], },
0958329a
TC
91 'testout/t61_conv_sharp.ppm');
92
9cef8440
TC
93test($imbase, { type=>'nearest_color', dist=>1,
94 xo=>[ 10, 10, 120 ],
95 yo=>[ 10, 140, 60 ],
96 colors=> [ NC('#FF0000'), NC('#FFFF00'), NC('#00FFFF') ]},
97 'testout/t61_nearest.ppm');
98
4c033fd4
TC
99# Regression test: the checking of the segment type was incorrect
100# (the comparison was checking the wrong variable against the wrong value)
101my $f4 = [ [ 0, 0.5, 1, NC(0,0,0), NC(255,255,255), 5, 0 ] ];
8c3ff7d9
TC
102test($imbase, {type=>'fountain', xa=>75, ya=>75, xb=>90, yb=>15,
103 segments=>$f4, super_sample=>'grid',
104 ftype=>'linear', combine=>'color' },
4c033fd4 105 'testout/t61_regress_fount.ppm');
dff75dee
TC
106my $im2 = $imbase->copy;
107$im2->box(xmin=>20, ymin=>20, xmax=>40, ymax=>40, color=>'FF0000', filled=>1);
108$im2->write(file=>'testout/t61_diff_base.ppm');
109my $im3 = Imager->new(xsize=>150, ysize=>150, channels=>3);
110$im3->box(xmin=>20, ymin=>20, xmax=>40, ymax=>40, color=>'FF0000', filled=>1);
111my $diff = $imbase->difference(other=>$im2);
8c3ff7d9
TC
112ok($diff, "got difference image");
113SKIP:
114{
115 skip(1, "missing comp or diff image") unless $im3 && $diff;
116
117 is(Imager::i_img_diff($im3->{IMG}, $diff->{IMG}), 0,
118 "compare test image and diff image");
dff75dee 119}
6607600c 120
817ba871
TC
121# newer versions of gimp add a line to the gradient file
122my $name;
123my $f5 = Imager::Fountain->read(gimp=>'testimg/newgimpgrad.ggr',
124 name => \$name);
125ok($f5, "read newer gimp gradient")
126 or print "# ",Imager->errstr,"\n";
127is($name, "imager test gradient", "check name read correctly");
128$f5 = Imager::Fountain->read(gimp=>'testimg/newgimpgrad.ggr');
129ok($f5, "check we handle case of no name reference correctly")
130 or print "# ",Imager->errstr,"\n";
131
132# test writing of gradients
133ok($f2->write(gimp=>'testout/t61grad1.ggr'), "save a gradient")
134 or print "# ",Imager->errstr,"\n";
135undef $name;
136my $f6 = Imager::Fountain->read(gimp=>'testout/t61grad1.ggr',
137 name=>\$name);
138ok($f6, "read what we wrote")
139 or print "# ",Imager->errstr,"\n";
140ok(!defined $name, "we didn't set the name, so shouldn't get one");
141
142# try with a name
143ok($f2->write(gimp=>'testout/t61grad2.ggr', name=>'test gradient'),
144 "write gradient with a name")
145 or print "# ",Imager->errstr,"\n";
146undef $name;
147my $f7 = Imager::Fountain->read(gimp=>'testout/t61grad2.ggr', name=>\$name);
148ok($f7, "read what we wrote")
149 or print "# ",Imager->errstr,"\n";
150is($name, "test gradient", "check the name matches");
151
109bec2d
TC
152# we attempt to convert color names in segments to segments now
153{
154 my @segs =
155 (
156 [ 0.0, 0.5, 1.0, '000000', '#FFF', 0, 0 ],
157 );
158 my $im = Imager->new(xsize=>50, ysize=>50);
159 ok($im->filter(type=>'fountain', segments => \@segs,
160 xa=>0, ya=>30, xb=>49, yb=>30),
161 "fountain with color names instead of objects in segments");
162 my $left = $im->getpixel('x'=>0, 'y'=>20);
163 ok(color_close($left, Imager::Color->new(0,0,0)),
164 "check black converted correctly");
165 my $right = $im->getpixel('x'=>49, 'y'=>20);
166 ok(color_close($right, Imager::Color->new(255,255,255)),
167 "check white converted correctly");
168
169 # check that invalid color names are handled correctly
170 my @segs2 =
171 (
172 [ 0.0, 0.5, 1.0, '000000', 'FxFxFx', 0, 0 ],
173 );
174 ok(!$im->filter(type=>'fountain', segments => \@segs2,
175 xa=>0, ya=>30, xb=>49, yb=>30),
176 "fountain with invalid color name");
177 cmp_ok($im->errstr, '=~', 'No color named', "check error message");
178}
179
b692658a
TC
180{
181 my $im = Imager->new(xsize=>100, ysize=>100);
182 # build the gradient the hard way - linear from black to white,
183 # then back again
184 my @simple =
185 (
186 [ 0, 0.25, 0.5, 'black', 'white', 0, 0 ],
187 [ 0.5. 0.75, 1.0, 'white', 'black', 0, 0 ],
188 );
189 # across
190 my $linear = $im->filter(type => "fountain",
191 ftype => 'linear',
192 repeat => 'sawtooth',
193 xa => 0,
194 ya => $im->getheight / 2,
195 xb => $im->getwidth - 1,
196 yb => $im->getheight / 2);
197 ok($linear, "linear fountain sample");
198 # around
199 my $revolution = $im->filter(type => "fountain",
200 ftype => 'revolution',
201 xa => $im->getwidth / 2,
202 ya => $im->getheight / 2,
203 xb => $im->getwidth / 2,
204 yb => 0);
205 ok($revolution, "revolution fountain sample");
206 # out from the middle
207 my $radial = $im->filter(type => "fountain",
208 ftype => 'radial',
209 xa => $im->getwidth / 2,
210 ya => $im->getheight / 2,
211 xb => $im->getwidth / 2,
212 yb => 0);
213 ok($radial, "radial fountain sample");
214}
215
7327d4b0
TC
216{
217 # try a simple custom filter that uses the Perl image interface
218 sub perl_filt {
219 my %args = @_;
220
221 my $im = $args{imager};
222
223 my $channels = $args{channels};
224 unless (@$channels) {
225 $channels = [ reverse(0 .. $im->getchannels-1) ];
226 }
227 my @chans = @$channels;
228 push @chans, 0 while @chans < 4;
229
230 for my $y (0 .. $im->getheight-1) {
231 my $row = $im->getsamples(y => $y, channels => \@chans);
232 $im->setscanline(y => $y, pixels => $row);
233 }
234 }
235 Imager->register_filter(type => 'perl_test',
236 callsub => \&perl_filt,
237 defaults => { channels => [] },
238 callseq => [ qw/imager channels/ ]);
239 test($imbase, { type => 'perl_test' }, 'testout/t61perl.ppm');
240}
241
d08b8f85 242sub test {
8c3ff7d9 243 my ($in, $params, $out) = @_;
b2778574 244
d08b8f85 245 my $copy = $in->copy;
8c3ff7d9
TC
246 if (ok($copy->filter(%$params), $params->{type})) {
247 ok($copy->write(file=>$out), "write $params->{type}")
248 or print "# ",$copy->errstr,"\n";
d08b8f85
TC
249 }
250 else {
8c3ff7d9
TC
251 SKIP:
252 {
253 skip("couldn't filter", 1);
254 }
d08b8f85 255 }
73962964 256 $copy;
d08b8f85 257}
109bec2d
TC
258
259sub color_close {
260 my ($c1, $c2) = @_;
261
262 my @c1 = $c1->rgba;
263 my @c2 = $c2->rgba;
264
265 for my $i (0..2) {
266 if (abs($c1[$i]-$c2[$i]) > 2) {
267 return 0;
268 }
269 }
270 return 1;
271}