$hsh{ssample_param}, $hsh{segments});
},
};
+ $filters{unsharpmask} =
+ {
+ callseq => [ qw(image stddev scale) ],
+ defaults => { stddev=>2.0, scale=>1.0 },
+ callsub =>
+ sub {
+ my %hsh = @_;
+ i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
+ },
+ };
$FORMATGUESS=\&def_guess_type;
}
postlevels levels(10)
radnoise xo(100) yo(100) ascale(17.0) rscale(0.02)
turbnoise xo(0.0) yo(0.0) scale(10.0)
+ unsharpmask stddev(2.0) scale(1.0)
watermark wmark pixdiff(10) tx(0) ty(0)
The default values are in parenthesis. All parameters must have some
the noise, and I<scale> the scale of the noise, with lower numbers
giving more detail.
+=item unsharpmask
+
+performs an unsharp mask on the image. This is the result of
+subtracting a gaussian blurred version of the image from the original.
+I<stddev> controls the stddev parameter of the gaussian blur. Each
+output pixel is: in + I<scale> * (in - blurred).
+
=item watermark
applies I<wmark> as a watermark on the image with strength I<pixdiff>,
i_contrast(im, 0.8);
i_hardinvert(im);
+ i_unsharp_mask(im, 2.0, 1.0);
// and more
=head1 DESCRIPTION
i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
}
+/*
+=item i_unsharp_mask(im, stddev, scale)
+
+Perform an usharp mask, which is defined as subtracting the blurred
+image from double the original.
+
+=cut
+*/
+void i_unsharp_mask(i_img *im, double stddev, double scale) {
+ i_img copy;
+ int x, y, ch;
+
+ if (scale < 0)
+ return;
+ /* it really shouldn't ever be more than 1.0, but maybe ... */
+ if (scale > 100)
+ scale = 100;
+
+ i_copy(©, im);
+ i_gaussian(©, stddev);
+ if (im->bits == i_8_bits) {
+ i_color *blur = mymalloc(im->xsize * sizeof(i_color) * 2);
+ i_color *out = blur + im->xsize;
+
+ for (y = 0; y < im->ysize; ++y) {
+ i_glin(©, 0, copy.xsize, y, blur);
+ i_glin(im, 0, im->xsize, y, out);
+ for (x = 0; x < im->xsize; ++x) {
+ for (ch = 0; ch < im->channels; ++ch) {
+ /*int temp = out[x].channel[ch] +
+ scale * (out[x].channel[ch] - blur[x].channel[ch]);*/
+ int temp = out[x].channel[ch] * 2 - blur[x].channel[ch];
+ if (temp < 0)
+ temp = 0;
+ else if (temp > 255)
+ temp = 255;
+ out[x].channel[ch] = temp;
+ }
+ }
+ i_plin(im, 0, im->xsize, y, out);
+ }
+
+ myfree(blur);
+ }
+ else {
+ i_fcolor *blur = mymalloc(im->xsize * sizeof(i_fcolor) * 2);
+ i_fcolor *out = blur + im->xsize;
+
+ for (y = 0; y < im->ysize; ++y) {
+ i_glinf(©, 0, copy.xsize, y, blur);
+ i_glinf(im, 0, im->xsize, y, out);
+ for (x = 0; x < im->xsize; ++x) {
+ for (ch = 0; ch < im->channels; ++ch) {
+ double temp = out[x].channel[ch] +
+ scale * (out[x].channel[ch] - blur[x].channel[ch]);
+ if (temp < 0)
+ temp = 0;
+ else if (temp > 1.0)
+ temp = 1.0;
+ out[x].channel[ch] = temp;
+ }
+ }
+ i_plinf(im, 0, im->xsize, y, out);
+ }
+
+ myfree(blur);
+ }
+ i_img_exorcise(©);
+}
+
struct fount_state;
static double linear_fount_f(double x, double y, struct fount_state *state);
static double bilinear_fount_f(double x, double y, struct fount_state *state);
my $im_other = Imager->new(xsize=>150, ysize=>150);
$im_other->box(xmin=>30, ymin=>60, xmax=>120, ymax=>90, filled=>1);
-print "1..35\n";
+print "1..37\n";
test($imbase, 1, {type=>'autolevels'}, 'testout/t61_autolev.ppm');
segments=>$f3, super_sample=>'grid',
ftype=>'radial_square', combine=>'color' },
'testout/t61_fount_gimp.ppm');
+test($imbase, 36, { type=>'unsharpmask', stddev=>2.0 },
+ 'testout/t61_unsharp.ppm');
sub test {
my ($in, $num, $params, $out) = @_;