# Raster drawing with Imager `Imager` is the raster workhorse: create an image, draw on it, filter it, save it. It is actively maintained, it links its own copies of the format libraries so PNG, JPEG, TIFF, GIF, and WEBP all work out of the box, and its drawing primitives are the ones from the [algorithms chapter](raster-algorithms.md) running at C speed. If you are starting a raster project on Perl today and have no reason to prefer something else, start here. Every drawing method returns false on failure and sets `errstr`, so the idiom is to check and report: ```perl use Imager; my $img = Imager->new(xsize => 400, ysize => 300, channels => 4) or die Imager->errstr; ``` `channels => 4` asks for RGBA (red, green, blue, alpha); use `3` for opaque RGB. The alpha channel is what lets the [compositing](foundations.md) from the foundations chapter work when you draw one image onto another. ## Colors Anywhere a method takes `color =>`, you can pass a name, a hex string, an `Imager::Color` object, or a plain array reference: ```perl my $red = Imager::Color->new('red'); my $red2 = Imager::Color->new('#FF0000'); my $red3 = Imager::Color->new(255, 0, 0); my $trans = Imager::Color->new(255, 0, 0, 128); # 50% alpha $img->box(color => [0, 128, 255], filled => 1); # array-ref, no object ``` The array-reference form is the least ceremony for a one-off color and is what most of the examples below use. ## The primitives Note the parameter names carefully, because they are not all the same shape. Boxes use corner coordinates `xmin/ymin/xmax/ymax`; circles and arcs use a center `x/y` with a radius `r`; arcs add start and end degrees `d1/d2`. ```perl # fill the whole canvas white first $img->box(color => 'white', filled => 1); # a line; aa => 1 requests anti-aliasing $img->line(x1 => 0, y1 => 0, x2 => 399, y2 => 299, color => [255, 0, 0], aa => 1); # an outlined box (no fill) and a filled one $img->box(xmin => 20, ymin => 20, xmax => 120, ymax => 90, color => 'black'); $img->box(xmin => 140, ymin => 20, xmax => 240, ymax => 90, color => [200, 220, 255], filled => 1); # a filled circle: center (200,150), radius 60 $img->circle(x => 200, y => 150, r => 60, color => [0, 128, 255]); # an arc is a pie slice from d1 to d2 degrees $img->arc(x => 200, y => 150, r => 80, d1 => 0, d2 => 120, color => 'yellow'); # a polygon from a list of [x, y] points $img->polygon(points => [[300, 40], [380, 40], [340, 110]], color => [120, 200, 120]); # a polyline is an open path; it takes no fill $img->polyline(points => [[300, 130], [340, 200], [380, 130]], color => 'black', aa => 1); # flood fill from a seed point out to a border $img->flood_fill(x => 5, y => 5, color => [245, 245, 245]); ``` Two traps worth stating once. `box` is filled only when you pass `filled => 1` (or a `fill =>` pattern); without it you get an outline. `polyline` draws an open path and does not accept `fill`, unlike `polygon` which closes and can fill. When a shape comes out as an outline you expected filled, or a fill silently does nothing, one of these two is why. ## Loading, scaling, and saving Reading and writing infer the format from the filename extension, or you can force it with `type =>`: ```perl my $photo = Imager->new; $photo->read(file => 'input.jpg') or die $photo->errstr; # scale by a factor, or to fit a box my $thumb = $photo->scale(scalefactor => 0.25); my $fit = $photo->scale(xpixels => 200, ypixels => 200, type => 'min'); $thumb->write(file => 'thumb.png') or die $thumb->errstr; ``` `scale` returns a new image; it does not modify the original. The `type => 'min'` form scales so the image fits inside the given box preserving aspect ratio; `'max'` fills the box (cropping the overflow when you then crop); `'nonprop'` ignores aspect ratio and stretches to exactly the pixels you named. ## Filters `filter` applies an effect in place, named by `type =>`. The [convolution](raster-algorithms.md) from the algorithms chapter is here as built-in Gaussian blur and unsharp masking, plus a general `conv` for your own kernel: ```perl # Gaussian blur; larger stddev is more blur $img->filter(type => 'gaussian', stddev => 2.5); # unsharp mask to sharpen; both params optional $img->filter(type => 'unsharpmask', stddev => 2.0, scale => 1.0); # your own 1-D convolution coefficients (a horizontal blur here) $img->filter(type => 'conv', coef => [0.25, 0.5, 0.25]); # contrast, mosaic (pixelate), and inversion are all filters too $img->filter(type => 'contrast', intensity => 1.4); $img->filter(type => 'mosaic', size => 8); $img->filter(type => 'hardinvert'); ``` The full set includes `gaussian`, `gaussian2` (separate x and y deviations), `conv`, `unsharpmask`, `contrast`, `mosaic`, `noise`, `hardinvert`, `autolevels`, `postlevels`, and the procedural texture generators `fountain`, `gradgen`, `radnoise`, and `turbnoise`. Reach for the named filter before writing your own pixel loop; only drop to a `conv` coefficient list or manual access when nothing built in fits. ## A complete program Putting it together: a small poster with a background, some shapes, a blur pass, and a saved thumbnail. ```perl use strict; use warnings; use Imager; my $img = Imager->new(xsize => 400, ysize => 300, channels => 4) or die Imager->errstr; $img->box(color => [30, 30, 60], filled => 1); # dark bg $img->circle(x => 120, y => 150, r => 70, color => [255, 200, 60]); $img->circle(x => 260, y => 150, r => 70, color => [60, 200, 255]); $img->filter(type => 'gaussian', stddev => 1.2); # soften $img->line(x1 => 0, y1 => 250, x2 => 399, y2 => 250, color => 'white', aa => 1); $img->write(file => 'poster.png') or die $img->errstr; $img->scale(scalefactor => 0.5)->write(file => 'poster-thumb.png') or die $img->errstr; ``` ## When Imager is the wrong tool `Imager` is raster, so it has the raster limitation: it has a fixed resolution, and scaling past it degrades. For resolution-independent output (a logo that must print crisply at any size, a diagram destined for the web as markup) you want a vector tool, covered in [Cairo and SVG](vector-cairo-svg.md). For an existing codebase built on `GD` or ImageMagick, or for their specific strengths, see the [next chapter](raster-gd-magick.md). And when the drawing needs to appear in a live window rather than a file, that is the [GUI toolkits chapter](gui-toolkits.md). For everything that is «make or modify a bitmap on disk», `Imager` is the answer.