The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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.

Why a new module? Compiling PerlMagick can be complicated, and it lacks drawing functions. GD.pm has those but only supports gif and png. I like studying graphics, so why not let others in a similar situation benefit? The basis for this module is code written to preprocess remote sensing data.

Note: Documentation is ordered in:

API Basic concepts Reading and writing images Obtaining/setting attributes of images Drawing Methods Text rendering Image resizing Filters Transformations Plugins Internals Functional interface

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');

There are a few exceptions to this.

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 start clean 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.

Reading and writing images

$img->read() has generally has 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.

*Note that load() is now an alias for read but will be removed later*

$img->write has the same interface as open(). 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.

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.

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.

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.

  $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

So far there are only the functional interface is implemented for text rendering.

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.

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.

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 - If you test this on other systems please let me know.

Internals

DOCUMENTATION OF THIS SECTION INCOMPLETE

An image object is a wrapper around the raw handle to an image. It is stored in the IMG value of the object hash. When Imager->new() is called the IMG member is set to undef by default but if you give it arguments like $img=Imager->new(xsize=>100,ysize=>100) then it will return a 3 channel image of size 100 x 100..

Functional interface

DOCUMENTATION OF THIS SECTION OUT OF SYNC WITH CODE

Use only if you cannot do what you need to do with the OO interface. This is mostly intended for people who want to develop the OO interface or the XS part of the module.

  $bool   = i_has_format($str);
  
  $colref = i_color_set($colref,$r,$g,$b,$a);
  
  $imref  = i_img_empty($imref,$x,$y);
  $imref  = i_img_empty_ch($imref,$x,$y,$channels);
  
  @iminfo = i_img_info($imref);
  
            i_img_setmask($imref,$channel_mask);
  $ch_msk = i_img_getmask($imref);

            i_draw($imref,$x1,$y1,$x2,$y2,$colref);
            i_box($imref,$x1,$y1,$x2,$y2,$colref);
            i_box_filled($imref,$x1,$y1,$x2,$y2,$colref);
            i_arc($imref,$x,$y,$rad,$deg1,$deg2,$colref);
  
            i_copyto($imref,$srcref,$x1,$y1,$x2,$y2,$tx,$ty,
                   $trans_cl_ref);
            i_rubthru($imref,$srcref,$tx,$ty);
   $imref = i_scaleaxis($imref,$scale_factor,$axis);
  
            i_gaussian($imref,$stdev);
            i_conv($imref,$arrayref,$array_len);
  
            i_img_diff($imref1,$imref2);
  
            i_init_fonts();
  
            i_t1_set_aa($level);
            i_t1_cp($imref,$xb,$yb,$channel,$fontnum,
                  $pts,$str,$strlen,$align);
            i_t1_text($imref,$xb,$yb,$colorref,
                      $fontnum,$pts,$str,$strlen,$align);

            i_tt_set_aa($level);
            i_tt_cp($imref,$xb,$yb,$channel,$fontname,
                  $pts,$str,$strlen,$align);
            i_tt_text($imref,$xb,$yb,$colorref,
                      $fontname,$pts,$str,$strlen,$align);


   @bbox  = i_t1_bbox($fontnum,$pts,$str,$strlen);
  
   $imref = i_readjpeg($imref,$fd);
            i_writejpeg($imref,$fd,$qfactor);
  
   $imref = i_readpng($imref,$fd);
            i_writepng($imref,$fd);
  
   $imref = i_readgif($imref,$fd);
            i_writegif($imref,$fd,$planes,$lmdither,$lmfixed);
            i_writegifmc($imref,$fd,$planes);

   $imref = i_readppm($imref,$fd);
            i_writeppm($imref,$fd);
  
            i_readraw($imref,$fd,$xsize,$ysize,$datachannels,
                    $storechannels,$interleave);
            i_writeraw($imref,$fd);
  

BUGS

This documentation is all messy!

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.

There are some undocumented functions lying around - you can look at the *sigh* ugly list of EXPORT symbols at the top of Imager.pm and try to find out what a call does if you feel adventureus

TODO

Fix the bugs ofcourse and look in the TODO file

AUTHOR

Arnar M. Hrafnkelsson, addi@umich.edu

SEE ALSO

perl(1), Affix::Infix2Postfix(3). http://www.eecs.umich.edu/~addi/perl/Imager/