summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Imager/Engines.pod
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Imager/Engines.pod')
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Imager/Engines.pod558
1 files changed, 558 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/Imager/Engines.pod b/Master/tlpkg/tlperl/lib/Imager/Engines.pod
new file mode 100755
index 00000000000..42784712e67
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Imager/Engines.pod
@@ -0,0 +1,558 @@
+=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.
+
+ $new_img=$img->transform(xexpr=>'x',yexpr=>'y+10*sin((x+y)/10)')
+
+ $new_img=$img->transform(xexpr=>'x+0.1*y+5*sin(y/10.0+1.57)',
+ yexpr=>'y+10*sin((x+y-0.785)/10)')
+
+=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
+
+=item *
+
+channels - the number of channels in the output image. If this isn't
+supplied a 3 channel image will be created.
+
+=back
+
+The tranformation function is specified using either the expr or
+rpnexpr member of the options.
+
+=head3 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 L<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.
+
+=head3 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'
+
+At the end of the expression there should be a single pixel value left
+on the stack, which is used as the output pixel.
+
+=head3 Operators
+
+transform2() has a fairly rich range of operators.
+
+Each entry below includes the usage with rpnexpr, formatted as:
+
+=over
+
+I<operand> I<operand> ... B<I<operator>> -- I<result>
+
+=back
+
+If the operand or result begins with "N" it is a numeric value, if it
+begins with "C" it is a color or pixel value.
+
+=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. % is implemented
+using fmod() so you can use this to take a value mod a floating point
+value.
+
+rpnexpr usage:
+
+=over
+
+I<N1> I<N2> B<+> -- I<N>
+
+I<N1> I<N2> B<*> -- I<N>
+
+I<N1> I<N2> B<-> -- I<N>
+
+I<N1> I<N2> B</> -- I<N>
+
+I<N1> I<N2> B<**> -- I<N>
+
+I<N1> B<uminus> -- I<N>
+
+=back
+
+=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.
+
+rpnexpr usage:
+
+=over
+
+I<N> B<sin> -- I<N>
+
+I<N> B<cos> -- I<N>
+
+I<Ny> I<Nx> B<atan2> -- I<N>
+
+=back
+
+=item distance(x1, y1, x2, y2)
+
+Find the distance between two points. This is handy (along with
+atan2()) for producing circular effects.
+
+rpnexpr usage:
+
+=over
+
+I<Nx1> I<Ny1> I<Nx2> I<Ny2> B<distance> -- I<N>
+
+=back
+
+=item sqrt(n)
+
+Find the square root. I haven't had much use for this since adding
+the distance() function.
+
+rpnexpr usage:
+
+=over
+
+I<N> B<sqrt> -- I<N>
+
+=back
+
+=item abs(n)
+
+Find the absolute value.
+
+rpnexpr usage:
+
+=over
+
+I<N> B<abs> -- I<N>
+
+=back
+
+=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.
+
+rpnexpr usage:
+
+=over
+
+I<Nx> I<Ny> B<getp1> -- I<C>
+
+I<Nx> I<Ny> B<getp2> -- I<C>
+
+I<Nx> I<Ny> B<getp3> -- I<C>
+
+=back
+
+=item value(c), hue(c), sat(c), hsv(h,s,v), hsva(h,s,v,alpha)
+
+Separates a colour value into it's value (brightness), hue (colour)
+and saturation elements. Use hsv() to put them back together (after
+suitable manipulation), or hsva() to include a tranparency value.
+
+rpnexpr usage:
+
+=over
+
+I<C> B<value> -- I<N>
+
+I<C> B<hue> -- I<N>
+
+I<C> B<sat> -- I<N>
+
+I<Nh> I<Ns> I<Nv> B<hsv> -- I<C>
+
+I<Nh> I<Ns> I<Nv> I<Na> B<hsva> -- I<C>
+
+=back
+
+=item red(c), green(c), blue(c), rgb(r,g,b), rgba(r,g,b,a)
+
+Separates a colour value into it's red, green and blue colours. Use
+rgb(r,g,b) to put it back together, or rgba() to include a
+transparency value.
+
+rpnexpr usage:
+
+=over
+
+I<C> B<red> -- I<N>
+
+I<C> B<green> -- I<N>
+
+I<C> B<blue> -- I<N>
+
+I<Nr> I<Ng> I<Nb> B<rgb> -- I<C>
+
+I<Nr> I<Ng> I<Nb> I<Na> B<rgba> -- I<C>
+
+=back
+
+=item alpha(c)
+
+Retrieve the alpha value from a colour.
+
+rpnexpr usage:
+
+=over
+
+I<C> B<alpha> -- I<N>
+
+=back
+
+=item int(n)
+
+Convert a value to an integer. Uses a C int cast, so it may break on
+large values.
+
+rpnexpr usage:
+
+=over
+
+I<N> B<int> -- I<N>
+
+=back
+
+=item if(cond,ntrue,nfalse), if(cond,ctrue,cfalse)
+
+A simple (and inefficient) if function.
+
+rpnexpr usage:
+
+=over
+
+I<Ncond> I<N-true-result> I<N-false-result> B<if> -- I<N>
+
+I<Ncond> I<C-true-result> I<C-false-result> B<if> -- I<C>
+
+I<Ncond> I<C-true-result> I<C-false-result> B<ifp> -- I<C>
+
+=back
+
+=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.
+
+=over
+
+I<N1> I<N2> B<< <= >> -- I<N>
+
+I<N1> I<N2> B<< < >> -- I<N>
+
+I<N1> I<N2> B<< >= >> -- I<N>
+
+I<N1> I<N2> B<< > >> -- I<N>
+
+I<N1> I<N2> B<< == >> -- I<N>
+
+I<N1> I<N2> B<< != >> -- I<N>
+
+=back
+
+=item &&, ||, not(n)
+
+Basic logical operators.
+
+rpnexpr usage:
+
+=over
+
+I<N1> I<N2> B<and> -- I<N>
+
+I<N1> I<N2> B<or> -- I<N>
+
+I<N> B<not> -- I<N>
+
+=back
+
+=item log(n), exp(n)
+
+Natural logarithm and exponential.
+
+rpnexpr usage:
+
+=over
+
+I<N> B<log> -- I<N>
+
+I<N> B<exp> -- I<N>
+
+=back
+
+=item det(a, b, c, d)
+
+Calculate the determinant of the 2 x 2 matrix;
+
+ a b
+ c d
+
+rpnexpr usage:
+
+=over
+
+I<Na> I<Nb> I<Nc> I<Nd> B<det> -- I<N>
+
+=back
+
+=back
+
+=head3 Constants
+
+transform2() defines the following constants:
+
+=over
+
+=item pi
+
+The classical constant.
+
+=item w
+
+=item h
+
+The width and height of the output image.
+
+=item cx
+
+=item cy
+
+The center of the output image.
+
+=item wI<image number>
+
+=item hI<image number>
+
+The width and height of each of the input images, C<w1> is the width
+of the first input image and so on.
+
+=item cxI<image number>
+
+=item cyI<image number>
+
+The center of each of the input images, (C<cx1>, C<cy1>) is the center
+of the first input image and so on.
+
+=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>.
+
+ # generate a colorful spiral
+ # requires that Parse::RecDescent be installed
+ my $newimg = Imager::transform2({
+ width => 160, height=>160,
+ expr => <<EOS
+ dist = distance(x, y, w/2, h/2);
+ angle = atan2(y-h/2, x-w/2);
+ angle2 = (dist / 10 + angle) % ( 2 * pi );
+ return hsv(angle*180/pi, 1, (sin(angle2)+1)/2);
+ EOS
+ });
+
+ # replace green portions of an image with another image
+ my $newimg = Imager::transform2({
+ rpnexpr => <<EOS
+ x y getp2 !pat # used to replace green portions
+ x y getp1 !pix # source with "green screen"
+ @pix red 10 lt @pix blue 10 lt && # low blue and red
+ @pix green 254 gt && # and high green
+ @pat @pix ifp
+ EOS
+ }, $source, $background);
+
+=head2 Matrix Transformations
+
+=over
+
+=item matrix_transform
+
+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.
+
+You can also supply a C<back> argument which acts as a background
+color for the areas of the image with no samples available (outside
+the rectangle of the source image.) This can be either an
+Imager::Color or Imager::Color::Float object. This is B<not> mixed
+transparent pixels in the middle of the source image, it is B<only>
+used for pixels where there is no corresponding pixel in the source
+image.
+
+=back
+
+=cut