=head1 NAME
|
|
|
|
Imager::Filters - Entire Image Filtering Operations
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use Imager;
|
|
|
|
$img = ...;
|
|
|
|
$img->filter(type=>'autolevels');
|
|
$img->filter(type=>'autolevels', lsat=>0.2);
|
|
$img->filter(type=>'turbnoise')
|
|
|
|
# and lots of others
|
|
|
|
load_plugin("dynfilt/dyntest.so")
|
|
or die "unable to load plugin\n";
|
|
|
|
$img->filter(type=>'lin_stretch', a=>35, b=>200);
|
|
|
|
unload_plugin("dynfilt/dyntest.so")
|
|
or die "unable to load plugin\n";
|
|
|
|
$out = $img->difference(other=>$other_img);
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Filters are operations that have similar calling interface.
|
|
|
|
=over
|
|
|
|
=item filter
|
|
|
|
Parameters:
|
|
|
|
=over
|
|
|
|
=item *
|
|
|
|
type - the type of filter, see L</Types of Filters>.
|
|
|
|
=item *
|
|
|
|
many other possible parameters, see L</Types of Filters> below.
|
|
|
|
=back
|
|
|
|
=back
|
|
|
|
=head2 Types of Filters
|
|
|
|
Here is a list of the filters that are always avaliable in Imager.
|
|
This list can be obtained by running the C<filterlist.perl> script
|
|
that comes with the module source.
|
|
|
|
Filter Arguments Default value
|
|
autolevels lsat 0.1
|
|
usat 0.1
|
|
skew 0
|
|
|
|
bumpmap bump lightx lighty
|
|
elevation 0
|
|
st 2
|
|
|
|
bumpmap_complex bump
|
|
channel 0
|
|
tx 0
|
|
ty 0
|
|
Lx 0.2
|
|
Ly 0.4
|
|
Lz -1
|
|
cd 1.0
|
|
cs 40.0
|
|
n 1.3
|
|
Ia (0 0 0)
|
|
Il (255 255 255)
|
|
Is (255 255 255)
|
|
|
|
contrast intensity
|
|
|
|
conv coef
|
|
|
|
fountain xa ya xb yb
|
|
ftype linear
|
|
repeat none
|
|
combine none
|
|
super_sample none
|
|
ssample_param 4
|
|
segments(see below)
|
|
|
|
gaussian stddev
|
|
|
|
gradgen xo yo colors
|
|
dist 0
|
|
|
|
hardinvert
|
|
|
|
mosaic size 20
|
|
|
|
noise amount 3
|
|
subtype 0
|
|
|
|
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
|
|
|
|
All parameters must have some value but if a parameter has a default
|
|
value it may be omitted when calling the filter function.
|
|
|
|
Every one of these filters modifies the image in place.
|
|
|
|
A reference of the filters follows:
|
|
|
|
=over
|
|
|
|
=item autolevels
|
|
|
|
scales the value of each channel so that the values in the image will
|
|
cover the whole possible range for the channel. I<lsat> and I<usat>
|
|
truncate the range by the specified fraction at the top and bottom of
|
|
the range respectivly.
|
|
|
|
# increase contrast per channel, losing little detail
|
|
$img->filter(type=>"autolevels")
|
|
or die $img->errstr;
|
|
|
|
# increase contrast, losing 20% of highlight at top and bottom range
|
|
$img->filter(type=>"autolevels", lsat=>0.2, usat=>0.2)
|
|
or die $img->errstr;
|
|
|
|
=item bumpmap
|
|
|
|
uses the channel I<elevation> image I<bump> as a bumpmap on your
|
|
image, with the light at (I<lightx>, I<lightty>), with a shadow length
|
|
of I<st>.
|
|
|
|
$img->filter(type=>"bumpmap", bump=>$bumpmap_img,
|
|
lightx=>10, lighty=>10, st=>5)
|
|
or die $img->errstr;
|
|
|
|
=item bumpmap_complex
|
|
|
|
uses the channel I<channel> image I<bump> as a bumpmap on your image.
|
|
If Lz<0 the three L parameters are considered to be the direction of
|
|
the light. If Lz>0 the L parameters are considered to be the light
|
|
position. I<Ia> is the ambient colour, I<Il> is the light colour,
|
|
I<Is> is the color of specular highlights. I<cd> is the diffuse
|
|
coefficient and I<cs> is the specular coefficient. I<n> is the
|
|
shininess of the surface.
|
|
|
|
$img->filter(type=>"bumpmap_complex", bump=>$bumpmap_img)
|
|
or die $img->errstr;
|
|
|
|
=item contrast
|
|
|
|
scales each channel by I<intensity>. Values of I<intensity> < 1.0
|
|
will reduce the contrast.
|
|
|
|
# higher contrast
|
|
$img->filter(type=>"contrast", intensity=>1.3)
|
|
or die $img->errstr;
|
|
|
|
# lower contrast
|
|
$img->filter(type=>"contrast", intensity=>0.8)
|
|
or die $img->errstr;
|
|
|
|
=item conv
|
|
|
|
performs 2 1-dimensional convolutions on the image using the values
|
|
from I<coef>. I<coef> should be have an odd length and the sum of the
|
|
coefficients must be non-zero.
|
|
|
|
# sharper
|
|
$img->filter(type=>"conv", coef=>[-0.5, 2, -0.5 ])
|
|
or die $img->errstr;
|
|
|
|
# blur
|
|
$img->filter(type=>"conv", coef=>[ 1, 2, 1 ])
|
|
or die $img->errstr;
|
|
|
|
=item fountain
|
|
|
|
renders a fountain fill, similar to the gradient tool in most paint
|
|
software. The default fill is a linear fill from opaque black to
|
|
opaque white. The points A(xa, ya) and B(xb, yb) control the way the
|
|
fill is performed, depending on the ftype parameter:
|
|
|
|
=over
|
|
|
|
=item linear
|
|
|
|
the fill ramps from A through to B.
|
|
|
|
=item bilinear
|
|
|
|
the fill ramps in both directions from A, where AB defines the length
|
|
of the gradient.
|
|
|
|
=item radial
|
|
|
|
A is the center of a circle, and B is a point on it's circumference.
|
|
The fill ramps from the center out to the circumference.
|
|
|
|
=item radial_square
|
|
|
|
A is the center of a square and B is the center of one of it's sides.
|
|
This can be used to rotate the square. The fill ramps out to the
|
|
edges of the square.
|
|
|
|
=item revolution
|
|
|
|
A is the centre of a circle and B is a point on it's circumference. B
|
|
marks the 0 and 360 point on the circle, with the fill ramping
|
|
clockwise.
|
|
|
|
=item conical
|
|
|
|
A is the center of a circle and B is a point on it's circumference. B
|
|
marks the 0 and point on the circle, with the fill ramping in both
|
|
directions to meet opposite.
|
|
|
|
=back
|
|
|
|
The I<repeat> option controls how the fill is repeated for some
|
|
I<ftype>s after it leaves the AB range:
|
|
|
|
=over
|
|
|
|
=item none
|
|
|
|
no repeats, points outside of each range are treated as if they were
|
|
on the extreme end of that range.
|
|
|
|
=item sawtooth
|
|
|
|
the fill simply repeats in the positive direction
|
|
|
|
=item triangle
|
|
|
|
the fill repeats in reverse and then forward and so on, in the
|
|
positive direction
|
|
|
|
=item saw_both
|
|
|
|
the fill repeats in both the positive and negative directions (only
|
|
meaningful for a linear fill).
|
|
|
|
=item tri_both
|
|
|
|
as for triangle, but in the negative direction too (only meaningful
|
|
for a linear fill).
|
|
|
|
=back
|
|
|
|
By default the fill simply overwrites the whole image (unless you have
|
|
parts of the range 0 through 1 that aren't covered by a segment), if
|
|
any segments of your fill have any transparency, you can set the
|
|
I<combine> option to 'normal' to have the fill combined with the
|
|
existing pixels. See the description of I<combine> in L<Imager::Fill>.
|
|
|
|
If your fill has sharp edges, for example between steps if you use
|
|
repeat set to 'triangle', you may see some aliased or ragged edges.
|
|
You can enable super-sampling which will take extra samples within the
|
|
pixel in an attempt anti-alias the fill.
|
|
|
|
The possible values for the super_sample option are:
|
|
|
|
=over
|
|
|
|
=item none
|
|
|
|
no super-sampling is done
|
|
|
|
=item grid
|
|
|
|
a square grid of points are sampled. The number of points sampled is
|
|
the square of ceil(0.5 + sqrt(ssample_param)).
|
|
|
|
=item random
|
|
|
|
a random set of points within the pixel are sampled. This looks
|
|
pretty bad for low ssample_param values.
|
|
|
|
=item circle
|
|
|
|
the points on the radius of a circle within the pixel are sampled.
|
|
This seems to produce the best results, but is fairly slow (for now).
|
|
|
|
=back
|
|
|
|
You can control the level of sampling by setting the ssample_param
|
|
option. This is roughly the number of points sampled, but depends on
|
|
the type of sampling.
|
|
|
|
The segments option is an arrayref of segments. You really should use
|
|
the L<Imager::Fountain> class to build your fountain fill. Each
|
|
segment is an array ref containing:
|
|
|
|
=over
|
|
|
|
=item start
|
|
|
|
a floating point number between 0 and 1, the start of the range of
|
|
fill parameters covered by this segment.
|
|
|
|
=item middle
|
|
|
|
a floating point number between start and end which can be used to
|
|
push the color range towards one end of the segment.
|
|
|
|
=item end
|
|
|
|
a floating point number between 0 and 1, the end of the range of fill
|
|
parameters covered by this segment. This should be greater than
|
|
start.
|
|
|
|
=item c0
|
|
|
|
=item c1
|
|
|
|
The colors at each end of the segment. These can be either
|
|
Imager::Color or Imager::Color::Float objects.
|
|
|
|
=item segment type
|
|
|
|
The type of segment, this controls the way the fill parameter varies
|
|
over the segment. 0 for linear, 1 for curved (unimplemented), 2 for
|
|
sine, 3 for sphere increasing, 4 for sphere decreasing.
|
|
|
|
=item color type
|
|
|
|
The way the color varies within the segment, 0 for simple RGB, 1 for
|
|
hue increasing and 2 for hue decreasing.
|
|
|
|
=back
|
|
|
|
Don't forget to use Imager::Fountain instead of building your own.
|
|
Really. It even loads GIMP gradient files.
|
|
|
|
# build the gradient the hard way - linear from black to white,
|
|
# then back again
|
|
my @simple =
|
|
(
|
|
[ 0, 0.25, 0.5, 'black', 'white', 0, 0 ],
|
|
[ 0.5. 0.75, 1.0, 'white', 'black', 0, 0 ],
|
|
);
|
|
# across
|
|
my $linear = $img->copy;
|
|
$linear->filter(type => "fountain",
|
|
ftype => 'linear',
|
|
repeat => 'sawtooth',
|
|
segments => \@simple,
|
|
xa => 0,
|
|
ya => $linear->getheight / 2,
|
|
xb => $linear->getwidth - 1,
|
|
yb => $linear->getheight / 2)
|
|
or die $linear->errstr;
|
|
# around
|
|
my $revolution = $img->copy;
|
|
$revolution->filter(type => "fountain",
|
|
ftype => 'revolution',
|
|
segments => \@simple,
|
|
xa => $revolution->getwidth / 2,
|
|
ya => $revolution->getheight / 2,
|
|
xb => $revolution->getwidth / 2,
|
|
yb => 0)
|
|
or die $revolution->errstr;
|
|
# out from the middle
|
|
my $radial = $img->copy;
|
|
$radial->filter(type => "fountain",
|
|
ftype => 'radial',
|
|
segments => \@simple,
|
|
xa => $im->getwidth / 2,
|
|
ya => $im->getheight / 2,
|
|
xb => $im->getwidth / 2,
|
|
yb => 0)
|
|
or die $radial->errstr;
|
|
|
|
=item gaussian
|
|
|
|
performs a gaussian blur of the image, using I<stddev> as the standard
|
|
deviation of the curve used to combine pixels, larger values give
|
|
bigger blurs. For a definition of Gaussian Blur, see:
|
|
|
|
http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node99.html
|
|
|
|
Values of C<stddev> around 0.5 provide a barely noticable blur, values
|
|
around 5 provide a very strong blur.
|
|
|
|
# only slightly blurred
|
|
$img->filter(type=>"gaussian", stddev=>0.5)
|
|
or die $img->errstr;
|
|
|
|
# more strongly blurred
|
|
$img->filter(type=>"gaussian", stddev=>5)
|
|
or die $img->errstr;
|
|
|
|
=item gradgen
|
|
|
|
renders a gradient, with the given I<colors> at the corresponding
|
|
points (x,y) in I<xo> and I<yo>. You can specify the way distance is
|
|
measured for color blending by setting I<dist> to 0 for Euclidean, 1
|
|
for Euclidean squared, and 2 for Manhattan distance.
|
|
|
|
$img->filter(type="gradgen",
|
|
xo=>[ 10, 50, 10 ],
|
|
yo=>[ 10, 50, 50 ],
|
|
colors=>[ qw(red blue green) ]);
|
|
|
|
=item hardinvert
|
|
|
|
inverts the image, black to white, white to black. All channels are
|
|
inverted, including the alpha channel if any.
|
|
|
|
$img->filter(type=>"hardinvert")
|
|
or die $img->errstr;
|
|
|
|
=item mosaic
|
|
|
|
produces averaged tiles of the given I<size>.
|
|
|
|
$img->filter(type=>"mosaic", size=>5)
|
|
or die $img->errstr;
|
|
|
|
=item noise
|
|
|
|
adds noise of the given I<amount> to the image. If I<subtype> is
|
|
zero, the noise is even to each channel, otherwise noise is added to
|
|
each channel independently.
|
|
|
|
# monochrome noise
|
|
$img->filter(type=>"noise", amount=>20, subtype=>0)
|
|
or die $img->errstr;
|
|
|
|
# color noise
|
|
$img->filter(type=>"noise", amount=>20, subtype=>1)
|
|
or die $img->errstr;
|
|
|
|
=item radnoise
|
|
|
|
renders radiant Perlin turbulent noise. The centre of the noise is at
|
|
(I<xo>, I<yo>), I<ascale> controls the angular scale of the noise ,
|
|
and I<rscale> the radial scale, higher numbers give more detail.
|
|
|
|
$img->filter(type=>"radnoise", xo=>50, yo=>50,
|
|
ascale=>1, rscale=>0.02)
|
|
or die $img->errstr;
|
|
|
|
=item postlevels
|
|
|
|
alters the image to have only I<levels> distinct level in each
|
|
channel.
|
|
|
|
$img->filter(type=>"postlevels", levels=>10)
|
|
or die $img->errstr;
|
|
|
|
=item turbnoise
|
|
|
|
renders Perlin turbulent noise. (I<xo>, I<yo>) controls the origin of
|
|
the noise, and I<scale> the scale of the noise, with lower numbers
|
|
giving more detail.
|
|
|
|
$img->filter(type=>"turbnoise", xo=>10, yo=>10, scale=>10)
|
|
or die $img->errstr;
|
|
|
|
=item unsharpmask
|
|
|
|
performs an unsharp mask on the image. This increases the contrast of
|
|
edges in 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).
|
|
|
|
$img->filter(type=>"unsharpmask", stddev=>1, scale=>0.5)
|
|
or die $img->errstr;
|
|
|
|
unsharpmark has the following parameters:
|
|
|
|
=over
|
|
|
|
=item *
|
|
|
|
stddev - this is equivalent to the C<Radius> value in the GIMP's
|
|
unsharpmask filter. This controls the size of the contrast increase
|
|
around edges, larger values will remove fine detail. You should
|
|
probably experiement on the types of images you plan to work with.
|
|
Default: 2.0.
|
|
|
|
=item *
|
|
|
|
scale - controls the strength of the edge enhancement, equivalent to
|
|
I<Amount> in the GIMP's unsharp mask filter. Default: 1.0.
|
|
|
|
=back
|
|
|
|
=item watermark
|
|
|
|
applies I<wmark> as a watermark on the image with strength I<pixdiff>,
|
|
with an origin at (I<tx>, I<ty>)
|
|
|
|
$img->filter(type=>"watermark", tx=>10, ty=>50,
|
|
wmark=>$wmark_image, pixdiff=>50)
|
|
or die $img->errstr;
|
|
|
|
=back
|
|
|
|
A demonstration of most of the filters can be found at:
|
|
|
|
http://www.develop-help.com/imager/filters.html
|
|
|
|
=head2 External Filters
|
|
|
|
As of Imager 0.48 you can create perl or XS based filters and hook
|
|
them into Imager's filter() method:
|
|
|
|
=over
|
|
|
|
=item register_filter
|
|
|
|
Registers a filter so it is visible via Imager's filter() method.
|
|
|
|
Imager->register_filter(type => 'your_filter',
|
|
defaults => { parm1 => 'default1' },
|
|
callseq => [ qw/image parm1/ ],
|
|
callsub => \&your_filter);
|
|
$img->filter(type=>'your_filter', parm1 => 'something');
|
|
|
|
The following parameters are needed:
|
|
|
|
=over
|
|
|
|
=item *
|
|
|
|
type - the type value that will be supplied to filter() to use your
|
|
filter.
|
|
|
|
=item *
|
|
|
|
defaults - a hash of defaults for the filter's parameters
|
|
|
|
=item *
|
|
|
|
callseq - a reference to an array of required parameter names.
|
|
|
|
=item *
|
|
|
|
callsub - a code reference called to execute your filter. The
|
|
parameters passed to filter() are supplied as a list of parameter
|
|
name, value ... which can be assigned to a hash.
|
|
|
|
The special parameters C<image> and C<imager> are supplied as the low
|
|
level image object from $self and $self itself respectively.
|
|
|
|
The function you supply must modify the image in place.
|
|
|
|
=back
|
|
|
|
See Imager::Filter::Mandelbrot for an example.
|
|
|
|
=back
|
|
|
|
=head2 Plugins
|
|
|
|
The plugin interface is deprecated. Please use the Imager API, see
|
|
L</Imager::API> and L<External Filters> for details
|
|
|
|
It is possible to add filters to the module without recompiling the
|
|
module itself. This is done by using DSOs (Dynamic shared object)
|
|
avaliable on most systems. This way you can maintain our own filters
|
|
and not have to get me to add it, or worse patch every new version of
|
|
the Module. Modules can be loaded AND UNLOADED at runtime. This
|
|
means that you can have a server/daemon thingy that can do something
|
|
like:
|
|
|
|
load_plugin("dynfilt/dyntest.so")
|
|
or die "unable to load plugin\n";
|
|
|
|
$img->filter(type=>'lin_stretch', a=>35, b=>200);
|
|
|
|
unload_plugin("dynfilt/dyntest.so")
|
|
or die "unable to load plugin\n";
|
|
|
|
Someone decides that the filter is not working as it should -
|
|
dyntest.c modified and recompiled.
|
|
|
|
load_plugin("dynfilt/dyntest.so")
|
|
or die "unable to load plugin\n";
|
|
|
|
$img->filter(%hsh);
|
|
|
|
An example plugin comes with the module - Please send feedback to
|
|
addi@umich.edu if you test this.
|
|
|
|
Note: This seems to test ok on the following systems:
|
|
Linux, Solaris, HPUX, OpenBSD, FreeBSD, TRU64/OSF1, AIX.
|
|
If you test this on other systems please let me know.
|
|
|
|
=over
|
|
|
|
=item load_plugin
|
|
|
|
This is a function, not a method, exported by default. You should
|
|
import this function explicitly for future compatibility if you need
|
|
it.
|
|
|
|
Accepts a single parameter, the name of a shared library file to load.
|
|
|
|
Returns true on success. Check Imager->errstr on failure.
|
|
|
|
=item unload_plugin
|
|
|
|
This is a function, not a method, which is exported by default. You
|
|
should import this function explicitly for future compatibility if you
|
|
need it.
|
|
|
|
Accepts a single parameter, the name of a shared library to unload.
|
|
This library must have been previously loaded by load_plugin().
|
|
|
|
Returns true on success. Check Imager->errstr on failure.
|
|
|
|
=back
|
|
|
|
=head2 Image Difference
|
|
|
|
=over
|
|
|
|
=item difference
|
|
|
|
You can create a new image that is the difference between 2 other images.
|
|
|
|
my $diff = $img->difference(other=>$other_img);
|
|
|
|
For each pixel in $img that is different to the pixel in $other_img,
|
|
the pixel from $other_img is given, otherwise the pixel is transparent
|
|
black.
|
|
|
|
This can be used for debugging image differences ("Where are they
|
|
different?"), and for optimizing animated GIFs.
|
|
|
|
Note that $img and $other_img must have the same number of channels.
|
|
The width and height of $diff will be the minimum of each of the width
|
|
and height of $img and $other_img.
|
|
|
|
Parameters:
|
|
|
|
=over
|
|
|
|
=item *
|
|
|
|
other - the other image object to compare against
|
|
|
|
=item *
|
|
|
|
mindist - the difference between corresponding samples must be greater
|
|
than I<mindist> for the pixel to be considered different. So a value
|
|
of zero returns all different pixels, not all pixels. Range: 0 to 255
|
|
inclusive. Default: 0.
|
|
|
|
For large sample images this is scaled down to the range 0 .. 1.
|
|
|
|
=back
|
|
|
|
=back
|
|
|
|
=head1 AUTHOR
|
|
|
|
Arnar M. Hrafnkelsson, Tony Cook <tony@imager.perl.org>.
|
|
|
|
=head1 SEE ALSO
|
|
|
|
Imager, Imager::Filter::Flines, Imager::Filter::Mandelbrot
|
|
|
|
=head1 REVISION
|
|
|
|
$Revision: 1252 $
|
|
|
|
=cut
|