]> git.imager.perl.org - imager.git/commitdiff
Added Engines pod, moved masked images to ImageTypes, and moved convert()
authorArnar Mar Hrafnkelsson <addi@cpan.org>
Wed, 16 Jan 2002 04:39:02 +0000 (04:39 +0000)
committerArnar Mar Hrafnkelsson <addi@cpan.org>
Wed, 16 Jan 2002 04:39:02 +0000 (04:39 +0000)
and map() to Transformations.

Changes
Imager.pm
MANIFEST
lib/Imager/Engines.pod [new file with mode: 0644]
lib/Imager/ImageTypes.pod
lib/Imager/Transformations.pod

diff --git a/Changes b/Changes
index e125cf2186e9cc9a0d5d5499050bd5348fff2553..59668511d2c0904fe41898fcb071a448633bba47 100644 (file)
--- a/Changes
+++ b/Changes
@@ -596,6 +596,7 @@ Revision history for Perl extension Imager.
        - Added lib/Imager/Transformations.pod, some docs of simple transforms.
        - Added lib/Imager/ImageTypes.pod, draft of ImageType pod.
        - Added lib/Imager/Filters.pod, draft of Filters pod.
        - Added lib/Imager/Transformations.pod, some docs of simple transforms.
        - Added lib/Imager/ImageTypes.pod, draft of ImageType pod.
        - Added lib/Imager/Filters.pod, draft of Filters pod.
+       - Added lib/Imager/Engines.pod, draft of Engines pod.
 
 
 =================================================================
 
 
 =================================================================
index 8baa2cb00a728441427ee1dd8dc2793786f6134e..fbc6945e6dc8c4afe0c9c87608d0a7d5b144b1ac 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -3156,748 +3156,8 @@ color table.
 
 
 
 
 
 
-=head2 Filters
-
-A special image method is the filter method. An example is:
-
-  $img->filter(type=>'autolevels');
-
-This will call the autolevels filter.  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
-  autolevels      lsat(0.1) usat(0.1) skew(0)
-  bumpmap         bump elevation(0) lightx lighty 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
-  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)
-
-The default values are in parenthesis.  All parameters must have some
-value but if a parameter has a default value it may be omitted when
-calling the filter function.
-
-The filters are:
 
 
-=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..
-
-=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>.
-
-=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.
-
-=item contrast
-
-scales each channel by I<intensity>.  Values of I<intensity> < 1.0
-will reduce the contrast.
-
-=item conv
-
-performs 2 1-dimensional convolutions on the image using the values
-from I<coef>.  I<coef> should be have an odd length.
-
-=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 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.
-
-=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
-
-=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 blendeing by setting I<dist> to 0 for Euclidean, 1
-for Euclidean squared, and 2 for Manhattan distance.
-
-=item hardinvert
-
-inverts the image, black to white, white to black.  All channels are
-inverted, including the alpha channel if any.
-
-=item mosaic
-
-produces averaged tiles of the given I<size>.
-
-=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.
-
-=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.
-
-=item postlevels
-
-alters the image to have only I<levels> distinct level in each
-channel.
-
-=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.
-
-=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>,
-with an origin at (I<tx>, I<ty>)
-
-=back
-
-A demonstration of most of the filters can be found at:
-
-  http://www.develop-help.com/imager/filters.html
-
-(This is a slow link.)
-
-=head2 Color transformations
-
-You can use the convert method to transform the color space of an
-image using a matrix.  For ease of use some presets are provided.
-
-The convert method can be used to:
-
-=over 4
-
-=item *
-
-convert an RGB or RGBA image to grayscale.
-
-=item *
-
-convert a grayscale image to RGB.
-
-=item *
-
-extract a single channel from an image.
-
-=item *
-
-set a given channel to a particular value (or from another channel)
-
-=back
-
-The currently defined presets are:
-
-=over
-
-=item gray
-
-=item grey
-
-converts an RGBA image into a grayscale image with alpha channel, or
-an RGB image into a grayscale image without an alpha channel.
-
-This weights the RGB channels at 22.2%, 70.7% and 7.1% respectively.
-
-=item noalpha
-
-removes the alpha channel from a 2 or 4 channel image.  An identity
-for other images.
-
-=item red
-
-=item channel0
-
-extracts the first channel of the image into a single channel image
-
-=item green
-
-=item channel1
-
-extracts the second channel of the image into a single channel image
-
-=item blue
-
-=item channel2
-
-extracts the third channel of the image into a single channel image
-
-=item alpha
-
-extracts the alpha channel of the image into a single channel image.
-
-If the image has 1 or 3 channels (assumed to be grayscale of RGB) then
-the resulting image will be all white.
-
-=item rgb
-
-converts a grayscale image to RGB, preserving the alpha channel if any
-
-=item addalpha
-
-adds an alpha channel to a grayscale or RGB image.  Preserves an
-existing alpha channel for a 2 or 4 channel image.
-
-=back
-
-For example, to convert an RGB image into a greyscale image:
-
-  $new = $img->convert(preset=>'grey'); # or gray
-
-or to convert a grayscale image to an RGB image:
-
-  $new = $img->convert(preset=>'rgb');
-
-The presets aren't necessary simple constants in the code, some are
-generated based on the number of channels in the input image.
-
-If you want to perform some other colour transformation, you can use
-the 'matrix' parameter.
-
-For each output pixel the following matrix multiplication is done:
-
-     channel[0]       [ [ $c00, $c01, ...  ]        inchannel[0]
-   [     ...      ] =          ...              x [     ...        ]
-     channel[n-1]       [ $cn0, ...,  $cnn ] ]      inchannel[max]
-                                                          1
-
-So if you want to swap the red and green channels on a 3 channel image:
-
-  $new = $img->convert(matrix=>[ [ 0, 1, 0 ],
-                                 [ 1, 0, 0 ],
-                                 [ 0, 0, 1 ] ]);
-
-or to convert a 3 channel image to greyscale using equal weightings:
-
-  $new = $img->convert(matrix=>[ [ 0.333, 0.333, 0.334 ] ])
-
-=head2 Color Mappings
-
-You can use the map method to map the values of each channel of an
-image independently using a list of lookup tables.  It's important to
-realize that the modification is made inplace.  The function simply
-returns the input image again or undef on failure.
-
-Each channel is mapped independently through a lookup table with 256
-entries.  The elements in the table should not be less than 0 and not
-greater than 255.  If they are out of the 0..255 range they are
-clamped to the range.  If a table does not contain 256 entries it is
-silently ignored.
-
-Single channels can mapped by specifying their name and the mapping
-table.  The channel names are C<red>, C<green>, C<blue>, C<alpha>.
-
-  @map = map { int( $_/2 } 0..255;
-  $img->map( red=>\@map );
-
-It is also possible to specify a single map that is applied to all
-channels, alpha channel included.  For example this applies a gamma
-correction with a gamma of 1.4 to the input image.
-
-  $gamma = 1.4;
-  @map = map { int( 0.5 + 255*($_/255)**$gamma ) } 0..255;
-  $img->map(all=> \@map);
-
-The C<all> map is used as a default channel, if no other map is
-specified for a channel then the C<all> map is used instead.  If we
-had not wanted to apply gamma to the alpha channel we would have used:
-
-  $img->map(all=> \@map, alpha=>[]);
-
-Since C<[]> contains fewer than 256 element the gamma channel is
-unaffected.
-
-It is also possible to simply specify an array of maps that are
-applied to the images in the rgba order.  For example to apply
-maps to the C<red> and C<blue> channels one would use:
-
-  $img->map(maps=>[\@redmap, [], \@bluemap]);
-
-
-
-=head2 Transformations
-
-Another special image method is transform.  It can be used to generate
-warps and rotations and such features.  It can be given the operations
-in postfix notation or the module Affix::Infix2Postfix can be used.
-Look in the test case t/t55trans.t for an example.
-
-transform() needs expressions (or opcodes) that determine the source
-pixel for each target pixel.  Source expressions are infix expressions
-using any of the +, -, *, / or ** binary operators, the - unary
-operator, ( and ) for grouping and the sin() and cos() functions.  The
-target pixel is input as the variables x and y.
-
-You specify the x and y expressions as xexpr and yexpr respectively.
-You can also specify opcodes directly, but that's magic deep enough
-that you can look at the source code.
-
-You can still use the transform() function, but the transform2()
-function is just as fast and is more likely to be enhanced and
-maintained.
-
-Later versions of Imager also support a transform2() class method
-which allows you perform a more general set of operations, rather than
-just specifying a spatial transformation as with the transform()
-method, you can also perform colour transformations, image synthesis
-and image combinations.
-
-transform2() takes an reference to an options hash, and a list of
-images to operate one (this list may be empty):
-
-  my %opts;
-  my @imgs;
-  ...
-  my $img = Imager::transform2(\%opts, @imgs)
-      or die "transform2 failed: $Imager::ERRSTR";
-
-The options hash may define a transformation function, and optionally:
-
-=over 4
-
-=item *
-
-width - the width of the image in pixels.  If this isn't supplied the
-width of the first input image is used.  If there are no input images
-an error occurs.
-
-=item *
-
-height - the height of the image in pixels.  If this isn't supplied
-the height of the first input image is used.  If there are no input
-images an error occurs.
-
-=item *
-
-constants - a reference to hash of constants to define for the
-expression engine.  Some extra constants are defined by Imager
-
-=back
-
-The tranformation function is specified using either the expr or
-rpnexpr member of the options.
-
-=over 4
-
-=item Infix expressions
-
-You can supply infix expressions to transform 2 with the expr keyword.
-
-$opts{expr} = 'return getp1(w-x, h-y)'
-
-The 'expression' supplied follows this general grammar:
-
-   ( identifier '=' expr ';' )* 'return' expr
-
-This allows you to simplify your expressions using variables.
-
-A more complex example might be:
-
-$opts{expr} = 'pix = getp1(x,y); return if(value(pix)>0.8,pix*0.8,pix)'
-
-Currently to use infix expressions you must have the Parse::RecDescent
-module installed (available from CPAN).  There is also what might be a
-significant delay the first time you run the infix expression parser
-due to the compilation of the expression grammar.
-
-=item Postfix expressions
-
-You can supply postfix or reverse-polish notation expressions to
-transform2() through the rpnexpr keyword.
-
-The parser for rpnexpr emulates a stack machine, so operators will
-expect to see their parameters on top of the stack.  A stack machine
-isn't actually used during the image transformation itself.
-
-You can store the value at the top of the stack in a variable called
-foo using !foo and retrieve that value again using @foo.  The !foo
-notation will pop the value from the stack.
-
-An example equivalent to the infix expression above:
-
- $opts{rpnexpr} = 'x y getp1 !pix @pix value 0.8 gt @pix 0.8 * @pix ifp'
-
-=back
-
-transform2() has a fairly rich range of operators.
-
-=over 4
-
-=item +, *, -, /, %, **
-
-multiplication, addition, subtraction, division, remainder and
-exponentiation.  Multiplication, addition and subtraction can be used
-on colour values too - though you need to be careful - adding 2 white
-values together and multiplying by 0.5 will give you grey, not white.
-
-Division by zero (or a small number) just results in a large number.
-Modulo zero (or a small number) results in zero.
-
-=item sin(N), cos(N), atan2(y,x)
-
-Some basic trig functions.  They work in radians, so you can't just
-use the hue values.
-
-=item distance(x1, y1, x2, y2)
-
-Find the distance between two points.  This is handy (along with
-atan2()) for producing circular effects.
-
-=item sqrt(n)
-
-Find the square root.  I haven't had much use for this since adding
-the distance() function.
-
-=item abs(n)
-
-Find the absolute value.
-
-=item getp1(x,y), getp2(x,y), getp3(x, y)
-
-Get the pixel at position (x,y) from the first, second or third image
-respectively.  I may add a getpn() function at some point, but this
-prevents static checking of the instructions against the number of
-images actually passed in.
-
-=item value(c), hue(c), sat(c), hsv(h,s,v)
-
-Separates a colour value into it's value (brightness), hue (colour)
-and saturation elements.  Use hsv() to put them back together (after
-suitable manipulation).
-
-=item red(c), green(c), blue(c), rgb(r,g,b)
-
-Separates a colour value into it's red, green and blue colours.  Use
-rgb(r,g,b) to put it back together.
-
-=item int(n)
-
-Convert a value to an integer.  Uses a C int cast, so it may break on
-large values.
-
-=item if(cond,ntrue,nfalse), if(cond,ctrue,cfalse)
-
-A simple (and inefficient) if function.
-
-=item <=,<,==,>=,>,!=
-
-Relational operators (typically used with if()).  Since we're working
-with floating point values the equalities are 'near equalities' - an
-epsilon value is used.
-
-=item &&, ||, not(n)
-
-Basic logical operators.
-
-=back
-
-A few examples:
-
-=over 4
-
-=item rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat x y getp1 !pix @pix sat 0.7 gt @pat @pix ifp'
-
-tiles a smaller version of the input image over itself where the
-colour has a saturation over 0.7.
-
-=item rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat y 360 / !rat x y getp1 1 @rat - pmult @pat @rat pmult padd'
-
-tiles the input image over itself so that at the top of the image the
-full-size image is at full strength and at the bottom the tiling is
-most visible.
-
-=item rpnexpr=>'x y getp1 !pix @pix value 0.96 gt @pix sat 0.1 lt and 128 128 255 rgb @pix ifp'
-
-replace pixels that are white or almost white with a palish blue
-
-=item rpnexpr=>'x 35 % 10 * y 45 % 8 * getp1 !pat x y getp1 !pix @pix sat 0.2 lt @pix value 0.9 gt and @pix @pat @pix value 2 / 0.5 + pmult ifp'
-
-Tiles the input image overitself where the image isn't white or almost
-white.
-
-=item rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
-
-Produces a spiral.
-
-=item rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
-
-A spiral built on top of a colour wheel.
-
-=back
-
-For details on expression parsing see L<Imager::Expr>.  For details on
-the virtual machine used to transform the images, see
-L<Imager::regmach.pod>.
-
-=head2 Matrix Transformations
-
-Rather than having to write code in a little language, you can use a
-matrix to perform transformations, using the matrix_transform()
-method:
-
-  my $im2 = $im->matrix_transform(matrix=>[ -1, 0, $im->getwidth-1,
-                                            0,  1, 0,
-                                            0,  0, 1 ]);
-
-By default the output image will be the same size as the input image,
-but you can supply the xsize and ysize parameters to change the size.
-
-Rather than building matrices by hand you can use the Imager::Matrix2d
-module to build the matrices.  This class has methods to allow you to
-scale, shear, rotate, translate and reflect, and you can combine these
-with an overloaded multiplication operator.
-
-WARNING: the matrix you provide in the matrix operator transforms the
-co-ordinates within the B<destination> image to the co-ordinates
-within the I<source> image.  This can be confusing.
-
-Since Imager has 3 different fairly general ways of transforming an
-image spatially, this method also has a yatf() alias.  Yet Another
-Transformation Function.
-
-=head2 Masked Images
-
-Masked images let you control which pixels are modified in an
-underlying image.  Where the first channel is completely black in the
-mask image, writes to the underlying image are ignored.
-
-For example, given a base image called $img:
-
-  my $mask = Imager->new(xsize=>$img->getwidth, ysize=>getheight,
-                         channels=>1);
-  # ... draw something on the mask
-  my $maskedimg = $img->masked(mask=>$mask);
-
-You can specifiy the region of the underlying image that is masked
-using the left, top, right and bottom options.
-
-If you just want a subset of the image, without masking, just specify
-the region without specifying a mask.
-
-=head2 Plugins
-
-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")  || die "unable to load plugin\n";
-  %hsh=(a=>35,b=>200,type=>lin_stretch);
-  $img->filter(%hsh);
-  unload_plugin("dynfilt/dyntest.so") || die "unable to load plugin\n";
-  $img->write(type=>'pnm',file=>'testout/t60.jpg')
-    || die "error in write()\n";
-
-Someone decides that the filter is not working as it should -
-dyntest.c modified and recompiled.
-
-  load_plugin("dynfilt/dyntest.so") || 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.
 
 
 =head1 BUGS
 
 
 =head1 BUGS
index 2c4e02c9d1ab244af2bd8630f815c9e65ed75b3d..575d139c054e1e389bb329adbe7b113885e26049 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -65,6 +65,7 @@ lib/Imager/Draw.pod
 lib/Imager/Transformations.pod
 lib/Imager/ImageTypes.pod
 lib/Imager/Filters.pod
 lib/Imager/Transformations.pod
 lib/Imager/ImageTypes.pod
 lib/Imager/Filters.pod
+lib/Imager/Engines.pod
 lib/Imager/Fill.pm
 lib/Imager/Font.pm
 lib/Imager/Font/Type1.pm
 lib/Imager/Fill.pm
 lib/Imager/Font.pm
 lib/Imager/Font/Type1.pm
diff --git a/lib/Imager/Engines.pod b/lib/Imager/Engines.pod
new file mode 100644 (file)
index 0000000..5a33036
--- /dev/null
@@ -0,0 +1,278 @@
+=head1 NAME
+
+Imager::Engines - Programmable transformation operations
+
+=head1 SYNOPSIS
+
+  use Imager;
+
+  my %opts;
+  my @imgs;
+  my $img;
+  ...
+
+  my $newimg = $img->transform(
+      xexpr=>'x',
+      yexpr=>'y+10*sin((x+y)/10)')
+    or die $img->errstr;
+
+  my $newimg = Imager::transform2(\%opts, @imgs)
+    or die "transform2 failed: $Imager::ERRSTR";
+
+  my $newimg = $img->matrix_transform(
+     matrix=>[ -1, 0, $img->getwidth-1,
+                0,  1, 0,
+                0,  0, 1 ]);
+
+
+=head1 DESCRIPTION
+
+=head2 transform
+
+The C<transform()> function can be used to generate spatial warps and
+rotations and such effects.  It only operates on a single image and
+its only function is to displace pixels.
+
+It can be given the operations in postfix notation or the module
+Affix::Infix2Postfix can be used to generate postfix code from infix
+code.  Look in the test case t/t55trans.t for an example.
+
+C<transform()> needs expressions (or opcodes) that determine the
+source pixel for each target pixel.  Source expressions are infix
+expressions using any of the +, -, *, / or ** binary operators, the -
+unary operator, ( and ) for grouping and the sin() and cos()
+functions.  The target pixel is input as the variables x and y.
+
+You specify the x and y expressions as xexpr and yexpr respectively.
+You can also specify opcodes directly, but that's magic deep enough
+that you can look at the source code.
+
+Note: You can still use the transform() function, but the transform2()
+function is just as fast and is more likely to be enhanced and
+maintained.
+
+
+
+=head2 transform2
+
+Imager also supports a C<transform2()> class method which allows you
+perform a more general set of operations, rather than just specifying
+a spatial transformation as with the transform() method, you can also
+perform colour transformations, image synthesis and image
+combinations from multiple source images.
+
+C<transform2()> takes an reference to an options hash, and a list of
+images to operate one (this list may be empty):
+
+  my %opts;
+  my @imgs;
+  ...
+  my $img = Imager::transform2(\%opts, @imgs)
+      or die "transform2 failed: $Imager::ERRSTR";
+
+The options hash may define a transformation function, and optionally:
+
+=over
+
+=item *
+
+width - the width of the image in pixels.  If this isn't supplied the
+width of the first input image is used.  If there are no input images
+an error occurs.
+
+=item *
+
+height - the height of the image in pixels.  If this isn't supplied
+the height of the first input image is used.  If there are no input
+images an error occurs.
+
+=item *
+
+constants - a reference to hash of constants to define for the
+expression engine.  Some extra constants are defined by Imager
+
+=back
+
+The tranformation function is specified using either the expr or
+rpnexpr member of the options.
+
+=over
+
+=item Infix expressions
+
+You can supply infix expressions to transform 2 with the expr keyword.
+
+$opts{expr} = 'return getp1(w-x, h-y)'
+
+The 'expression' supplied follows this general grammar:
+
+   ( identifier '=' expr ';' )* 'return' expr
+
+This allows you to simplify your expressions using variables.
+
+A more complex example might be:
+
+$opts{expr} = 'pix = getp1(x,y); return if(value(pix)>0.8,pix*0.8,pix)'
+
+Currently to use infix expressions you must have the Parse::RecDescent
+module installed (available from CPAN).  There is also what might be a
+significant delay the first time you run the infix expression parser
+due to the compilation of the expression grammar.
+
+=item Postfix expressions
+
+You can supply postfix or reverse-polish notation expressions to
+transform2() through the rpnexpr keyword.
+
+The parser for rpnexpr emulates a stack machine, so operators will
+expect to see their parameters on top of the stack.  A stack machine
+isn't actually used during the image transformation itself.
+
+You can store the value at the top of the stack in a variable called
+foo using !foo and retrieve that value again using @foo.  The !foo
+notation will pop the value from the stack.
+
+An example equivalent to the infix expression above:
+
+ $opts{rpnexpr} = 'x y getp1 !pix @pix value 0.8 gt @pix 0.8 * @pix ifp'
+
+=back
+
+transform2() has a fairly rich range of operators.
+
+=over
+
+=item +, *, -, /, %, **
+
+multiplication, addition, subtraction, division, remainder and
+exponentiation.  Multiplication, addition and subtraction can be used
+on colour values too - though you need to be careful - adding 2 white
+values together and multiplying by 0.5 will give you grey, not white.
+
+Division by zero (or a small number) just results in a large number.
+Modulo zero (or a small number) results in zero.
+
+=item sin(N), cos(N), atan2(y,x)
+
+Some basic trig functions.  They work in radians, so you can't just
+use the hue values.
+
+=item distance(x1, y1, x2, y2)
+
+Find the distance between two points.  This is handy (along with
+atan2()) for producing circular effects.
+
+=item sqrt(n)
+
+Find the square root.  I haven't had much use for this since adding
+the distance() function.
+
+=item abs(n)
+
+Find the absolute value.
+
+=item getp1(x,y), getp2(x,y), getp3(x, y)
+
+Get the pixel at position (x,y) from the first, second or third image
+respectively.  I may add a getpn() function at some point, but this
+prevents static checking of the instructions against the number of
+images actually passed in.
+
+=item value(c), hue(c), sat(c), hsv(h,s,v)
+
+Separates a colour value into it's value (brightness), hue (colour)
+and saturation elements.  Use hsv() to put them back together (after
+suitable manipulation).
+
+=item red(c), green(c), blue(c), rgb(r,g,b)
+
+Separates a colour value into it's red, green and blue colours.  Use
+rgb(r,g,b) to put it back together.
+
+=item int(n)
+
+Convert a value to an integer.  Uses a C int cast, so it may break on
+large values.
+
+=item if(cond,ntrue,nfalse), if(cond,ctrue,cfalse)
+
+A simple (and inefficient) if function.
+
+=item <=,<,==,>=,>,!=
+
+Relational operators (typically used with if()).  Since we're working
+with floating point values the equalities are 'near equalities' - an
+epsilon value is used.
+
+=item &&, ||, not(n)
+
+Basic logical operators.
+
+=back
+
+A few examples:
+
+=over
+
+=item rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat x y getp1 !pix @pix sat 0.7 gt @pat @pix ifp'
+
+tiles a smaller version of the input image over itself where the
+colour has a saturation over 0.7.
+
+=item rpnexpr=>'x 25 % 15 * y 35 % 10 * getp1 !pat y 360 / !rat x y getp1 1 @rat - pmult @pat @rat pmult padd'
+
+tiles the input image over itself so that at the top of the image the
+full-size image is at full strength and at the bottom the tiling is
+most visible.
+
+=item rpnexpr=>'x y getp1 !pix @pix value 0.96 gt @pix sat 0.1 lt and 128 128 255 rgb @pix ifp'
+
+replace pixels that are white or almost white with a palish blue
+
+=item rpnexpr=>'x 35 % 10 * y 45 % 8 * getp1 !pat x y getp1 !pix @pix sat 0.2 lt @pix value 0.9 gt and @pix @pat @pix value 2 / 0.5 + pmult ifp'
+
+Tiles the input image overitself where the image isn't white or almost
+white.
+
+=item rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
+
+Produces a spiral.
+
+=item rpnexpr=>'x y 160 180 distance !d y 180 - x 160 - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a 180 * 3.1416 / 1 @a2 sin 1 + 2 / hsv'
+
+A spiral built on top of a colour wheel.
+
+=back
+
+For details on expression parsing see L<Imager::Expr>.  For details on
+the virtual machine used to transform the images, see
+L<Imager::regmach.pod>.
+
+
+=head2 Matrix Transformations
+
+Rather than having to write code in a little language, you can use a
+matrix to perform affine transformations, using the matrix_transform()
+method:
+
+  my $newimg = $img->matrix_transform(matrix=>[ -1, 0, $img->getwidth-1,
+                                            0,  1, 0,
+                                            0,  0, 1 ]);
+
+By default the output image will be the same size as the input image,
+but you can supply the xsize and ysize parameters to change the size.
+
+Rather than building matrices by hand you can use the Imager::Matrix2d
+module to build the matrices.  This class has methods to allow you to
+scale, shear, rotate, translate and reflect, and you can combine these
+with an overloaded multiplication operator.
+
+WARNING: the matrix you provide in the matrix operator transforms the
+co-ordinates within the B<destination> image to the co-ordinates
+within the I<source> image.  This can be confusing.
+
+Since Imager has 3 different fairly general ways of transforming an
+image spatially, this method also has a yatf() alias.  Yet Another
+Transformation Function.
+
+=cut
index 261dd82f7624a9c5627f15f39ce9bc8c6024a50d..09a6825174d73a91a419d315d733ffff63999503 100644 (file)
@@ -320,6 +320,32 @@ RGB image with:
   $rgbimg = $img->to_rgb8;
 
 
   $rgbimg = $img->to_rgb8;
 
 
+
+=head2 Masked Images
+
+Masked images let you control which pixels are modified in an
+underlying image.  Where the first channel is completely black in the
+mask image, writes to the underlying image are ignored.
+
+For example, given a base image called $img:
+
+  my $mask = Imager->new(xsize=>$img->getwidth, ysize=>getheight,
+                         channels=>1);
+  # ... draw something on the mask
+  my $maskedimg = $img->masked(mask=>$mask);
+
+You can specifiy the region of the underlying image that is masked
+using the left, top, right and bottom options.
+
+If you just want a subset of the image, without masking, just specify
+the region without specifying a mask.
+
+
+
+
+
+
+
 =head2 Tags
 
 Image tags contain meta-data about the image, ie. information not
 =head2 Tags
 
 Image tags contain meta-data about the image, ie. information not
@@ -399,3 +425,7 @@ If this tag is present then the whole image could not be read.  This
 isn't implemented for all images yet.
 
 =back
 isn't implemented for all images yet.
 
 =back
+
+
+
+
index ee4431b1eb4697bebedefba0adce35b6f55a6c01..b3f98f5fabbef1abeba9019d93259ecd0ceb3ce6 100644 (file)
@@ -23,11 +23,29 @@ Imager::Transformations - Simple transformations of one image into another.
 
   $img->flip(dir=>"h");       # horizontal flip
   $img->flip(dir=>"vh");      # vertical and horizontal flip
 
   $img->flip(dir=>"h");       # horizontal flip
   $img->flip(dir=>"vh");      # vertical and horizontal flip
-  $nimg = $img->copy->flip(dir=>"v"); # make a copy and flip it vertically
+  $newimg = $img->copy->flip(dir=>"v"); # make a copy and flip it vertically
 
   my $rot20 = $img->rotate(degrees=>20);
   my $rotpi4 = $img->rotate(radians=>3.14159265/4);
 
 
   my $rot20 = $img->rotate(degrees=>20);
   my $rotpi4 = $img->rotate(radians=>3.14159265/4);
 
+
+  # Convert image to gray
+  $new = $img->convert(preset=>'grey');          
+
+  # Swap red/green channel  
+  $new = $img->convert(matrix=>[ [ 0, 1, 0 ],
+                                 [ 1, 0, 0 ],
+                                 [ 0, 0, 1 ] ]);
+
+  # limit the range of red channel from 0..255 to 0..127
+  @map = map { int( $_/2 } 0..255;
+  $img->map( red=>\@map );
+
+  # Apply a Gamma of 1.4
+  my $gamma = 1.4;
+  my @map = map { int( 0.5 + 255*($_/255)**$gamma ) } 0..255;
+  $img->map(all=>\@map);  # inplace conversion
+
 =head1 DESCRIPTION
 
 The methods described in Imager::Transformations fall into two categories.
 =head1 DESCRIPTION
 
 The methods described in Imager::Transformations fall into two categories.
@@ -172,7 +190,161 @@ parameter which can take the values C<h>, C<v>, C<vh> and C<hv>.
 
 
 
 
 
 
+=head2 Color transformations
+
+You can use the convert method to transform the color space of an
+image using a matrix.  For ease of use some presets are provided.
+
+The convert method can be used to:
+
+=over
+
+=item *
+
+convert an RGB or RGBA image to grayscale.
+
+=item *
+
+convert a grayscale image to RGB.
+
+=item *
+
+extract a single channel from an image.
+
+=item *
+
+set a given channel to a particular value (or from another channel)
+
+=back
+
+The currently defined presets are:
+
+=over
+
+=item gray
+
+=item grey
+
+converts an RGBA image into a grayscale image with alpha channel, or
+an RGB image into a grayscale image without an alpha channel.
+
+This weights the RGB channels at 22.2%, 70.7% and 7.1% respectively.
+
+=item noalpha
+
+removes the alpha channel from a 2 or 4 channel image.  An identity
+for other images.
+
+=item red
+
+=item channel0
+
+extracts the first channel of the image into a single channel image
+
+=item green
+
+=item channel1
+
+extracts the second channel of the image into a single channel image
+
+=item blue
+
+=item channel2
+
+extracts the third channel of the image into a single channel image
+
+=item alpha
+
+extracts the alpha channel of the image into a single channel image.
+
+If the image has 1 or 3 channels (assumed to be grayscale of RGB) then
+the resulting image will be all white.
+
+=item rgb
+
+converts a grayscale image to RGB, preserving the alpha channel if any
+
+=item addalpha
+
+adds an alpha channel to a grayscale or RGB image.  Preserves an
+existing alpha channel for a 2 or 4 channel image.
+
+=back
+
+For example, to convert an RGB image into a greyscale image:
+
+  $new = $img->convert(preset=>'grey'); # or gray
+
+or to convert a grayscale image to an RGB image:
+
+  $new = $img->convert(preset=>'rgb');
+
+The presets aren't necessary simple constants in the code, some are
+generated based on the number of channels in the input image.
+
+If you want to perform some other colour transformation, you can use
+the 'matrix' parameter.
+
+For each output pixel the following matrix multiplication is done:
+
+  | channel[0] |   | $c00, ...,  $c0k |   | inchannel[0] |
+  |    ...     | = |       ...        | x |     ...      |
+  | channel[k] |   | $ck0, ...,  $ckk |   | inchannel[k] |
+                                                          1
+Where C<k = $img-&gt;getchannels()-1>.
+
+So if you want to swap the red and green channels on a 3 channel image:
+
+  $new = $img->convert(matrix=>[ [ 0, 1, 0 ],
+                                 [ 1, 0, 0 ],
+                                 [ 0, 0, 1 ] ]);
+
+or to convert a 3 channel image to greyscale using equal weightings:
+
+  $new = $img->convert(matrix=>[ [ 0.333, 0.333, 0.334 ] ])
+
+
+=head2 Color Mappings
+
+You can use the map method to map the values of each channel of an
+image independently using a list of lookup tables.  It's important to
+realize that the modification is made inplace.  The function simply
+returns the input image again or undef on failure.
+
+Each channel is mapped independently through a lookup table with 256
+entries.  The elements in the table should not be less than 0 and not
+greater than 255.  If they are out of the 0..255 range they are
+clamped to the range.  If a table does not contain 256 entries it is
+silently ignored.
+
+Single channels can mapped by specifying their name and the mapping
+table.  The channel names are C<red>, C<green>, C<blue>, C<alpha>.
+
+  @map = map { int( $_/2 } 0..255;
+  $img->map( red=>\@map );
+
+It is also possible to specify a single map that is applied to all
+channels, alpha channel included.  For example this applies a gamma
+correction with a gamma of 1.4 to the input image.
+
+  $gamma = 1.4;
+  @map = map { int( 0.5 + 255*($_/255)**$gamma ) } 0..255;
+  $img->map(all=> \@map);
+
+The C<all> map is used as a default channel, if no other map is
+specified for a channel then the C<all> map is used instead.  If we
+had not wanted to apply gamma to the alpha channel we would have used:
+
+  $img->map(all=> \@map, alpha=>[]);
+
+Since C<[]> contains fewer than 256 element the gamma channel is
+unaffected.
+
+It is also possible to simply specify an array of maps that are
+applied to the images in the rgba order.  For example to apply
+maps to the C<red> and C<blue> channels one would use:
 
 
+  $img->map(maps=>[\@redmap, [], \@bluemap]);