NAME
Imager - Perl extension for Generating 24 bit Images
SYNOPSIS
use Imager;
init();
$img = Imager->new();
$img->open(file=>'image.ppm',type=>'ppm')
|| print "failed: ",$img->{ERRSTR},"\n";
$scaled=$img->scale(xpixels=>400,ypixels=>400);
$scaled->write(file=>'sc_image.ppm',type=>'ppm')
|| print "failed: ",$scaled->{ERRSTR},"\n";
DESCRIPTION
Imager is a module for creating and altering images - It is not meant as a replacement or a competitor to ImageMagick or GD. Both are excellent packages and well supported.
API
Almost all functions take the parameters in the hash fashion. Example:
$img->open(file=>'lena.png',type=>'png');
or just:
$img->open(file=>'lena.png');
Basic concept
An Image object is created with $img = Imager->new()
Should this fail for some reason an explanation can be found in $Imager::ERRSTR
usually error messages are stored in $img->{ERRSTR}
, but since no object is created this is the only way to give back errors. $Imager::ERRSTR
is also used to report all errors not directly associated with an image object. Examples:
$img=Imager->new(); # This is an empty image (size is 0 by 0)
$img->open(file=>'lena.png',type=>'png'); # initializes from file
or if you want to create an empty image:
$img=Imager->new(xsize=>400,ysize=>300,channels=>3);
The latter example creates a completely black image of width 400 and height 300 and 4 channels.
To create a color object call the function i_color_new, $color=i_color_new($r,$g,$b,$a)
. The parameters are all from 0 to 255 and are all converted to integers. Each is the red, green, blue, and alpha component of the color respectively. This object can then be passed to functions that require a color parameter.
Coordinates in Imager have the origin in the upper left corner. The horizontal coordinate increases to the left and the vertical downwards.
Reading and writing images
$img->read()
generally takes two parameters, 'file' and 'type'. If the type of the file can be determined from the suffix of the file it can be omitted. Format dependant parameters are: For images of type 'raw' two extra parameters are needed 'xsize' and 'ysize', if the 'channel' parameter is omitted for type 'raw' it is assumed to be 3. gif and png images might have a palette are converted to truecolor bit when read. Alpha channel is preserved for png images irregardless of them being in RGB or gray colorspace. Similarly grayscale jpegs are one channel images after reading them. For jpeg images the iptc header information (stored in the APP13 header) is avaliable to some degree. You can get the raw header with $img->{IPTCRAW}
, but you can also retrieve the most basic information with %hsh=$img->parseiptc()
as always patches are welcome. Neither ppm nor tiff have extra options. Examples:
$img = Imager->new();
$img->read(file=>"cover.jpg") or die $img->errstr; # gets type from name
$img = Imager->new();
{ local(*FH,$/); open(FH,"file.gif") or die $!; $a=<FH>; }
$img->read(data=>$a,type=>'gif') or die $img->errstr;
The second example shows how to read an image from a scalar, this is usefull if your data originates from somewhere else than a filesystem such as a database over a DBI connection.
*Note that load() is now an alias for read but will be removed later*
$img->write
has the same interface as read()
. The earlier comments on read()
for autodetecting filetypes apply. For jpegs quality can be adjusted via the 'jpegquality' parameter (0-100). The number of colorplanes in gifs are set with 'gifplanes' and should be between 1 (2 color) and 8 (256 colors). It is also possible to choose between two quantizing methods with the parameter 'gifquant'. If set to mc it uses the mediancut algorithm from either giflibrary. If set to lm it uses a local means algorithm. It is then possible to give some extra settings. lmdither is the dither deviation amount in pixels (manhattan distance). lmfixed can be an array ref who holds an array of i_color objects. Note that the local means algorithm needs much more cpu time but also gives considerable better results than the median cut algorithm.
Currently just for gif files, you can specify various options for the conversion from Imager's internal RGB format to the target's indexed file format. If you set the gifquant option to 'gen', you can use the options specified under "Quantization options".
To see what Imager is compiled to support the following code snippet is sufficient:
use Imager;
print "@{[keys %Imager::formats]}";
Multi-image files
Currently just for gif files, you can create files that contain more than one image.
To do this:
Imager->write_multi(\%opts, @images)
Where %opts describes 3 possible types of outputs:
- callback
-
A code reference which is called with a single parameter, the data to be written. You can also specify $opts{maxbuffer} which is the maximum amount of data buffered. Note that there can be larger writes than this if the file library writes larger blocks. A smaller value maybe useful for writing to a socket for incremental display.
- fd
-
The file descriptor to save the images to.
- file
-
The name of the file to write to.
%opts may also include the keys from "Gif options" and "Quantization options".
The current aim is to support other multiple image formats in the future, such as TIFF, and to support reading multiple images from a single file.
Gif options
These options can be specified when calling write_multi() for gif files, when writing a single image with the gifquant option set to 'gen', or for direct calls to i_writegif_gen and i_writegif_callback.
Note that some viewers will ignore some of these options (gif_user_input in particular).
- gif_each_palette
-
Each image in the gif file has it's own palette if this is non-zero. All but the first image has a local colour table (the first uses the global colour table.
- interlace
-
The images are written interlaced if this is non-zero.
- gif_delays
-
A reference to an array containing the delays between images, in 1/100 seconds.
- gif_user_input
-
A reference to an array contains user input flags. If the given flag is non-zero the image viewer should wait for input before displaying the next image.
- gif_disposal
-
A reference to an array of image disposal methods. These define what should be done to the image before displaying the next one. These are integers, where 0 means unspecified, 1 means the image should be left in place, 2 means restore to background colour and 3 means restore to the previous value.
- gif_tran_color
-
A reference to an Imager::Color object, which is the colour to use for the palette entry used to represent transparency in the palette.
- gif_positions
-
A reference to an array of references to arrays which represent screen positions for each image.
- gif_loop_count
-
If this is non-zero the Netscape loop extension block is generated, which makes the animation of the images repeat.
This is currently unimplemented due to some limitations in giflib.
Quantization options
These options can be specified when calling write_multi() for gif files, when writing a single image with the gifquant option set to 'gen', or for direct calls to i_writegif_gen and i_writegif_callback.
- colors
-
A arrayref of colors that are fixed. Note that some color generators will ignore this.
- transp
-
The type of transparency processing to perform for images with an alpha channel where the output format does not have a proper alpha channel (eg. gif). This can be any of:
- none
-
No transparency processing is done. (default)
- threshold
-
Pixels more transparent that tr_threshold are rendered as transparent.
- errdiff
-
An error diffusion dither is done on the alpha channel. Note that this is independent of the translation performed on the colour channels, so some combinations may cause undesired artifacts.
- ordered
-
The ordered dither specified by tr_orddith is performed on the alpha channel.
- tr_threshold
-
The highest alpha value at which a pixel will be made transparent when transp is 'threshold'. (0-255, default 127)
- tr_errdiff
-
The type of error diffusion to perform on the alpha channel when transp is 'errdiff'. This can be any defined error diffusion type except for custom (see errdiff below).
- tr_ordered
-
The type of ordered dither to perform on the alpha channel when transp is 'orddith'. Possible values are:
- random
-
A semi-random map is used. The map is the same each time. Currently the default (which may change.)
- dot8
-
8x8 dot dither.
- dot4
-
4x4 dot dither
- hline
-
horizontal line dither.
- vline
-
vertical line dither.
- "/line"
- slashline
-
diagonal line dither
- '\line'
- backline
-
diagonal line dither
- custom
-
A custom dither matrix is used - see tr_map
- tr_map
-
When tr_orddith is custom this defines an 8 x 8 matrix of integers representing the transparency threshold for pixels corresponding to each position. This should be a 64 element array where the first 8 entries correspond to the first row of the matrix. Values should be betweern 0 and 255.
- make_colors
-
Defines how the quantization engine will build the palette(s). Currently this is ignored if 'translate' is 'giflib', but that may change. Possible values are:
- none
-
Only colors supplied in 'colors' are used.
- webmap
-
The web color map is used (need url here.)
- addi
-
The original code for generating the color map (Addi's code) is used.
Other methods may be added in the future.
- colors
-
A arrayref containing Imager::Color objects, which represents the starting set of colors to use in translating the images. webmap will ignore this. The final colors used are copied back into this array (which is expanded if necessary.)
- max_colors
-
The maximum number of colors to use in the image.
- translate
-
The method used to translate the RGB values in the source image into the colors selected by make_colors. Note that make_colors is ignored whene translate is 'giflib'.
Possible values are:
- giflib
-
The giflib native quantization function is used.
- closest
-
The closest color available is used.
- perturb
-
The pixel color is modified by perturb, and the closest color is chosen.
- errdiff
-
An error diffusion dither is performed.
It's possible other transate values will be added.
- errdiff
-
The type of error diffusion dither to perform. These values (except for custom) can also be used in tr_errdif.
- floyd
-
Floyd-Steinberg dither
- jarvis
-
Jarvis, Judice and Ninke dither
- stucki
-
Stucki dither
- custom
-
Custom. If you use this you must also set errdiff_width, errdiff_height and errdiff_map.
- errdiff_width
- errdiff_height
- errdiff_orig
- errdiff_map
-
When translate is 'errdiff' and errdiff is 'custom' these define a custom error diffusion map. errdiff_width and errdiff_height define the size of the map in the arrayref in errdiff_map. errdiff_orig is an integer which indicates the current pixel position in the top row of the map.
- perturb
-
When translate is 'perturb' this is the magnitude of the random bias applied to each channel of the pixel before it is looked up in the color table.
Obtaining/setting attributes of images
To get the size of an image in pixels the $img->getwidth()
and $img->getheight()
are used.
To get the number of channels in an image $img->getchannels()
is used. $img->getmask() and $img->setmask() are used to get/set the channel mask of the image.
$mask=$img->getmask();
$img->setmask(mask=>1+2); # modify red and green only
$img->setmask(mask=>8); # modify alpha only
$img->setmask(mask=>$mask); # restore previous mask
The mask of an image describes which channels are updated when some operation is performed on an image. Naturally it is not possible to apply masks to operations like scaling that alter the dimensions of images.
It is possible to have Imager find the number of colors in an image by using $img->getcolorcount()
. It requires memory proportionally to the number of colors in the image so it is possible to have it stop sooner if you only need to know if there are more than a certain number of colors in the image. If there are more colors than asked for the function return undef. Examples:
if (!defined($img->getcolorcount(maxcolors=>512)) {
print "Less than 512 colors in image\n";
}
Drawing Methods
IMPLEMENTATION MORE OR LESS DONE CHECK THE TESTS
DOCUMENTATION OF THIS SECTION OUT OF SYNC
It is possible to draw with graphics primitives onto images. Such primitives include boxes, arcs, circles and lines. A reference oriented list follows.
Box: $img->box(color=>$blue,xmin=>10,ymin=>30,xmax=>200,ymax=>300,filled=>1);
The Above example calls the box
method for the image and the box covers the pixels with in the rectangle specified. If filled
is ommited it is drawn as an outline. If any of the edges of the box are ommited it will snap to the outer edge of the image in that direction. Also if a color is omitted a color with (255,255,255,255) is used instead.
Arc: $img->arc(color=>$red, r=20, x=>200, y=>100, d1=>10, d2=>20 );
This creates a red arc with a 'center' at (200, 100) and spans 10 degrees and the slice has a radius of 20. SEE section on BUGS.
Circle: $img->circle(color=>$green, r=50, x=>200, y=>100);
This creates a green circle with its center at (200, 100) and has a radius of 20.
Line: $img->line(color=>$green, x1=10, x2=>100, y1=>20, y2=>50, antialias=>1 );
That draws an antialiased line from (10,100) to (20,50).
Polyline: $img->polyline(points=>[[$x0,$y0],[$x1,$y1],[$x2,$y2]],color=>$red); $img->polyline(x=>[$x0,$x1,$x2], y=>[$y0,$y1,$y2], antialias=>1);
Polyline is used to draw multilple lines between a series of points. The point set can either be specified as an arrayref to an array of array references (where each such array represents a point). The other way is to specify two array references.
Text rendering
To create a font object you can use:
$t1font = Imager::Font->new(file=>'pathtofont.pfb');
$ttfont = Imager::Font->new(file=>'pathtofont.ttf');
As is two types of font types are supported t1 postscript fonts and truetype fonts. You can see if they are supported in your binary with the %Imager::formats
hash. It is possible to control other attributes the font such as default color, size and anti aliasing.
$blue = Imager::Color->new(10,10,255,0);
$t1font = Imager::Font->new(file=>'pathtofont.pfb',
color=>$blue,
size=30);
To draw text on images the string method of the images is used. A font must be passed to the method.
$img=Imager->new();
$img=read(file=>"test.jpg");
$img->string(font=>$t1font,
text=>"Model-XYZ",
x=>0,
y=>40,
size=>40,
color=>$red);
$img->write(file=>"testout.jpg");
This would put a 40 pixel high text in the top left corner of an image. If you measure the actuall pixels it varies since the fonts usually do not use their full height. It seems that the color and size can be specified twice. When a font is created only the actual font specified matters. It his however convenient to store default values in a font, such as color and size. If parameters are passed to the string function they are used instead of the defaults stored in the font.
If string() is called with the channel
parameter then the color isn't used and the font is drawn in only one channel. This can be quite handy to create overlays. See the examples for tips about this.
Sometimes it is necessary to know how much space a string takes before rendering it. The bounding_box() method of a font can be used for that. examples:
@bbox=$font->bounding_box(string=>"testing",size=>15);
@bbox=$font->bounding_box(string=>"testing",size=>15,canon=>1);
@bbox=$font->bounding_box(string=>"testing",size=>15,x=50,y=>20);
The first example gets the so called glyph metrics. First is the
Image resizing
To scale an image so porportions are maintained use the $img->scale()
method. if you give either a xpixels or ypixels parameter they will determine the width or height respectively. If both are given the one resulting in a larger image is used. example: $img
is 700 pixels wide and 500 pixels tall.
$img->scale(xpixels=>400); # 400x285
$img->scale(ypixels=>400); # 560x400
$img->scale(xpixels=>400,ypixels=>400); # 560x400
$img->scale(xpixels=>400,ypixels=>400,type=>min); # 400x285
$img->scale(scalefactor=>0.25); 175x125 $img->scale(); # 350x250
if you want to create low quality previews of images you can pass qtype=>'preview'
to scale and it will use nearest neighbor sampling instead of filtering. It is much faster but also generates worse looking images - especially if the original has a lot of sharp variations and the scaled image is by more than 3-5 times smaller than the original.
If you need to scale images per axis it is best to do it simply by calling scaleX and scaleY. You can pass either 'scalefactor' or 'pixels' to both functions.
Another way to resize an image size is to crop it. The parameters to crop are the edges of the area that you want in the returned image. If a parameter is omited a default is used instead.
$newimg = $img->crop(left=>50, right=>100, top=>10, bottom=>100);
$newimg = $img->crop(left=>50, top=>10, width=>50, height=>90);
$newimg = $img->crop(left=>50, right=>100); # top
Copying images
To create a copy of an image use the copy()
method. This is usefull if you want to keep an original after doing something that changes the image inplace like writing text.
$img=$orig->copy();
To copy an image to onto another image use the paste()
method.
$dest->paste(left=>40,top=>20,img=>$logo);
That copies the entire $logo
image onto the $dest
image so that the upper left corner of the $logo
image is at (40,20).
Blending Images
To put an image or a part of an image directly into another it is best to call the paste()
method on the image you want to add to.
$img->paste(img=>$srcimage,left=>30,top=>50);
That will take paste $srcimage
into $img
with the upper left corner at (30,50). If no values are given for left
or top
they will default to 0.
A more complicated way of blending images is where one image is put 'over' the other with a certain amount of opaqueness. The method that does this is rubthrough.
$img->rubthrough(src=>$srcimage,tx=>30,ty=>50);
That will take the image $srcimage
and overlay it with the upper left corner at (30,50). The $srcimage
must be a 4 channel image. The last channel is used as an alpha channel.
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 filterlist.perl
script that comes with the module source.
Filter Arguments
turbnoise
autolevels lsat(0.1) usat(0.1) skew(0)
radnoise
noise amount(3) subtype(0)
contrast intensity
hardinvert
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.
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.
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:
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.
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.
constants - a reference to hash of constants to define for the expression engine. Some extra constants are defined by Imager
The tranformation function is specified using either the expr or rpnexpr member of the options.
- 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.
- 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'
transform2() has a fairly rich range of operators.
- +, *, -, /, %, **
-
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.
- sin(N), cos(N), atan2(y,x)
-
Some basic trig functions. They work in radians, so you can't just use the hue values.
- distance(x1, y1, x2, y2)
-
Find the distance between two points. This is handy (along with atan2()) for producing circular effects.
- sqrt(n)
-
Find the square root. I haven't had much use for this since adding the distance() function.
- abs(n)
-
Find the absolute value.
- 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.
- 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).
- 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.
- int(n)
-
Convert a value to an integer. Uses a C int cast, so it may break on large values.
- if(cond,ntrue,nfalse), if(cond,ctrue,cfalse)
-
A simple (and inefficient) if function.
- <=,<,==,>=,>,!=
-
Relational operators (typically used with if()). Since we're working with floating point values the equalities are 'near equalities' - an epsilon value is used.
- &&, ||, not(n)
-
Basic logical operators.
A few examples:
- 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.
- 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.
- 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
- 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.
- 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.
- 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.
For details on expression parsing see Imager::Expr. For details on the virtual machine used to transform the images, see Imager::regmach.pod.
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=>'ppm',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.
BUGS
box, arc, circle do not support antialiasing yet. arc, is only filled as of yet. Some routines do not return $self where they should. This affects code like this, $img->box()->arc()
where an object is expected.
When saving Gif images the program does NOT try to shave of extra colors if it is possible. If you specify 128 colors and there are only 2 colors used - it will have a 128 colortable anyway.
AUTHOR
Arnar M. Hrafnkelsson, addi@umich.edu And a great deal of help from others - see the README for a complete list. =head1 SEE ALSO
perl(1), Affix::Infix2Postfix(3). http://www.eecs.umich.edu/~addi/perl/Imager/