3 Imager::Cookbook - recipes working with Imager
7 Various simple and not so simple ways to do things with Imager.
11 This is described in detail in L<Imager::Files>.
13 =head2 Reading an image from a file
15 my $image = Imager->new;
17 $image->read(file=>$filename) or die $image->errstr;
21 my $image = Imager->new(file => $filename)
22 or die Imager->errstr;
26 =head2 Writing an image to a file
28 $image->write(file=>$filename) or die $image->errstr;
30 =head2 Write an animated GIF
32 # build an array of images to use in the gif
34 # synthesize the images or read them from files, it doesn't matter
38 Imager->write_multi({ file=>$filename, type=>'gif' }, @images)
39 or die Imager->errstr;
41 See L<Imager::Files/"Writing an animated GIF"> for a more detailed
44 =head2 Reading multiple images from one file
46 Some formats, like GIF and TIFF support multiple images per file. Use
47 the L<read_multi()|Imager::Files> method to read them:
49 my @images = Imager->read_multi(file=>$filename)
50 or die Imager->errstr;
52 =head2 Converting from one file format to another
54 This is as simple as reading the original file and writing the new
55 file, for single images:
57 my $image = Imager->new;
58 # Imager auto-detects the input file type
59 $image->read(file => $input_filename)
60 or die $image->errstr;
61 # Imager derives the output file format from the filename
62 $image->write(file => $output_filename)
63 or die $image->errstr;
65 # or you can supply a type parameter:
66 $image->write(file => $output_filename, type => 'gif')
67 or die $image->errstr;
69 The main issue that can occur with this is if the input file has
70 transparency and the output file format doesn't support that. This
71 can be a problem when converting from GIF files to JPEG files for
74 By default, if the output format doesn't support transparency, Imager
75 will compose the image onto a black background. You can override that
76 by supplying an C<i_background> option to C<write()> or
79 $image->write(file => "foo.jpg", i_background => "#808080")
80 or die $image->errstr;
82 Some formats support multiple files, so if you want to convert from
83 say TIFF to JPEG, you'll need multiple output files:
85 my @images = Imager->read_multi(file => 'input.tif')
86 or die Imager->errstr;
88 for my $image (@images) {
89 $image->write(file => sprintf('output%02d.jpg', $index++))
90 or die $image->errstr;
93 =head2 Transparent PNG
95 To save to a transparent PNG (or GIF or TIFF) you need to start with
96 an image with transparency.
98 To make a transparent image, create an image object with 2 or 4
101 # RGB with alpha channel
102 my $rgba = Imager->new(xsize => $width, ysize => $height, channels => 4);
104 # Gray with alpha channel
105 my $graya = Imager->new(xsize => $width, ysize => $height, channels => 2);
107 By default, the created image will be transparent.
109 Otherwise, if you have an existing image file with transparency,
110 simply read it, and the transparency will be preserved.
112 =head1 IMAGE SYNTHESIS
114 =head2 Creating an image
116 To create a simple RGB image, supply the image width and height to the
119 my $rgb = Imager->new(xsize=>$width, ysize=>$height);
121 If you also want an alpha channel:
123 my $rgb_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>4);
125 To make a gray-scale image:
127 my $gray = Imager->new(xsize=>$width, ysize=>$height, channels=>1);
129 and a gray-scale image with an alpha channel:
131 my $gray_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>2);
133 When a new image is created this way all samples are set to zero -
134 black for 1 or 3 channel images, transparent black for 2 or 4 channel
137 You can also create paletted images and images with more than 8-bits
138 per channel, see L<Imager::ImageTypes> for more details.
140 =head2 Setting the background of a new image
142 To set the background of a new image to a solid color, use the box()
143 method with no limits, and C<< filled=>1 >>:
145 $image->box(filled=>1, color=>$color);
147 As always, a color can be specified as an L<Imager::Color> object:
149 my $white = Imager::Color->new(255, 255, 255);
150 $image->box(filled=>1, color=>$white);
152 or you supply any single scalar that Imager::Color's new() method
153 accepts as a color description:
155 $image->box(filled=>1, color=>'white');
156 $image->box(filled=>1, color=>'#FF0000');
157 $image->box(filled=>1, color=>[ 255, 255, 255 ]);
159 You can also fill the image with a fill object:
162 # create the fill object
163 my $fill = Imager::Fill->new(hatch=>'check1x1')
164 $image->box(fill=>$fill);
166 # let Imager create one automatically
167 $image->box(fill=>{ hatch=>'check1x1' });
169 See L<Imager::Fill> for information on Imager's fill objects.
171 =head1 WORLD WIDE WEB
173 As with any CGI script it's up to you to validate data and set limits
174 on any parameters supplied to Imager.
176 For example, if you allow the caller to set the size of an output
177 image you should limit the size to prevent the client from specifying
178 an image size that will consume all available memory.
180 This is beside any other controls you need over access to data.
182 See L<CGI> for a module useful for processing CGI submitted data.
184 =head2 Returning an image from a CGI script
186 This is similar to writing to a file, but you also need to supply the
187 information needed by the web browser to identify the file format:
189 my $img = ....; # create the image and generate the contents
190 ++$|; # make sure the content type isn't buffered
191 print "Content-Type: image/png\n\n";
193 $img->write(fd=>fileno(STDOUT), type=>'png')
196 You need to set the Content-Type header depending on the file format
197 you send to the web browser.
199 If you want to supply a content-length header, write the image to a
202 my $img = ....; # create the image and generate the contents
204 $img->write(type=>'png', data=>\$data)
206 print "Content-Type: image/png\n";
207 print "Content-Length: ",length($data),"\n\n";
211 See C<samples/samp-scale.cgi> and C<samples/samp-image.cgi> for a
212 couple of simple examples of producing an image from CGI.
214 =head2 Inserting a CGI image in a page
216 There's occasionally confusion on how to display an image generated by
217 Imager in a page generated by a CGI.
219 Your web browser handles this process as two requests, one for the
220 HTML page, and another for the image itself.
222 Each request needs to perform validation since an attacker can control
223 the values supplied to both requests.
225 How you make the data available to the image generation code depends
228 See C<samples/samp-form.cgi> and C<samples/samp-image.cgi> in the
229 Imager distribution for one approach. The POD in C<samp-form.cgi>
230 also discusses some of the issues involved.
232 =head2 Parsing an image posted via CGI
234 C<WARNING>: file format attacks have become a common attack vector,
235 make sure you have up to date image file format libraries, otherwise
236 trying to parse uploaded files, whether with Imager or some other
237 tool, may result in a remote attacker being able to run their own code
240 If your HTML form uses the correct magic, it can upload files to your
241 CGI script, in particular, you need to use C< method="post" > and
242 C<enctype="multipart/form-data"> in the C<form> tag, and use
243 C<type="file"> in the C<input>, for example:
245 <form action="/cgi-bin/yourprogram" method="post"
246 enctype="multipart/form-data">
247 <input type="file" name="myimage" />
248 <input type="submit value="Upload Image" />
257 first check that the user supplied a file
265 have Imager read the image
269 # returns the client's name for the file, don't open this locally
271 # 1. check the user supplied a file
272 my $filename = $cgi->param('myimage');
274 # 2. get the file handle
275 my $fh = $cgi->upload('myimage');
279 # 3. have Imager read the image
280 my $img = Imager->new;
281 if ($img->read(fh=>$fh)) {
282 # we can now process the image
285 # else, you probably have an incorrect form or input tag
287 # else, the user didn't select a file
289 See C<samples/samp-scale.cgi> and C<samples/samp-tags.cgi> in the
290 Imager distribution for example code.
292 You may also want to set limits on the size of the image read, using
293 Imager's C<set_file_limits> method, documented in
294 L<Imager::Files/set_file_limits()>. For example:
296 # limit to 10 million bytes of memory usage
297 Imager->set_file_limits(bytes => 10_000_000);
299 # limit to 1024 x 1024
300 Imager->set_file_limits(width => 1024, height => 1024);
304 =head2 Adding a border to an image
306 First make a new image with space for the border:
308 my $border_width = ...;
309 my $border_height = ...;
310 my $out = Imager->new(xsize => $source->getwidth() + 2 * $border_width,
311 ysize => $source->getheight() + 2 * $border_height,
312 bits => $source->bits,
313 channels => $source->getchannels);
315 Then paste the source image into the new image:
317 $out->paste(left => $border_width,
318 top => $border_height,
321 Whether you draw the border before or after pasting the original image
322 depends on whether you want the border to overlap the image, for
323 example a semi-transparent border drawn after pasting the source image
324 could overlap the edge without hiding it.
326 If you want a solid border you could just fill the image before
327 pasting the source for simplicity:
329 $out->box(filled=>1, color=>'red');
330 $out->paste(left => $border_width,
331 top => $border_height,
341 =head2 Measuring text
343 =head2 Word wrapping text
345 =head2 Shearing (slanting) or Rotating text
347 This requires that you have Imager installed with FreeType 2.x support
348 installed, and that the font be created using the FreeType 2.x driver,
351 my $font = Imager::Font->new(file=>$fontfile, type=>'ft2');
353 First you need a transformation matrix, for shearing that could be:
355 my $angle_in_radians = ...;
356 my $tan_angle = sin($angle_rads) / cos($angle_rads);
357 # shear horizontally, supply this as y instead to do it vertically
358 my $matrix = Imager::Matrix2d->shear(x=>$tan_angle);
360 For rotation that would be:
362 my $matrix = Imager::Matrix2d->rotate(radians => $angle_in_radians);
366 my $matrix = Imager::Matrix2d->rotate(degrees => $angle_in_degrees);
368 Feed that to the font object:
370 $font->transform(matrix => $matrix);
372 and draw the text as normal:
374 $image->string(string => $text,
380 See samples/slant_text.pl for a comprehensive example, including
381 calculating the transformed bounding box to create an image to fit the
382 transformed text into.
384 =head1 IMAGE TRANSFORMATION
386 =head2 Shearing an image
388 =head2 Convert to gray-scale
390 To convert an RGB image to a gray-scale image, use the convert method:
392 my $grey = $image->convert(preset => 'gray');
394 convert() returns a new image.
396 See: L<Imager::Transformations/"Color transformations">
402 When Imager reads a file it does a magic number check to determine the
403 file type, so C<foo.png> could actually be a GIF image, and Imager
406 You can check the actual format of the image by looking at the
409 my $format = $image->tags(name=>'i_format');
411 =head2 Image spatial resolution
413 Most image file formats store information about the physical size of
414 the pixels, though in some cases that information isn't useful.
416 Imager stores this information in the tags C<i_xres> and C<i_yres>,
417 and this is always stored in dots per inch.
419 Some formats, including TIFF and JPEG allow you to change the units
420 spatial resolution information is stored in, if you set the tag that
421 changes this the Imager will convert C<i_xres> and C<i_yres> to those
422 units when it writes the file.
424 For example to set the resolution to 300 dpi:
426 $image->settag(name => 'i_xres', value => 300);
427 $image->settag(name => 'i_yres', value => 300);
429 If you want the file format to store the resolution in some other
430 unit, for example you can write a TIFF file that stores the resolution
431 in pixels per centimeter, you would do:
434 $image->settag(name => 'i_xres', value => 150 * 2.54);
435 $image->settag(name => 'i_yres', value => 150 * 2.54);
436 $image->settag(name => 'tiff_resolutionunit', value => 3);
440 =head1 IMAGE MANIPULATION
442 =head2 Replacing a color with transparency
445 To replace a color with transparency you can use the
446 L<Imager::Filters/difference()> method.
448 # make a work image the same size as our input
449 my $work = Imager->new(xsize => $in->getwidth, ysize => $in->getheight,
450 channels => $in->getchannels);
451 # and fill it with the color we want transparent
452 $work->box(filled => 1, color => $color);
454 # get an image with that color replaced with transparent black
455 my $out = $work->difference(other => $in);
457 =head1 SPECIAL EFFECTS
460 X<drop shadow>X<effects, drop shadow>
462 This can be used for a glow effect as well.
464 First create a new image, either with an alpha channel (if you want
465 transparency behind the shadow) or without, if you want a background
468 my $out = Imager->new
470 xsize => $shadow_size * 2 + $src->getwidth,
471 ysize => $shadow_size * 2 + $src->getheight,
474 # fill it with your background color, if you want one
475 # $out->box(filled => 1, color => $back_color);
477 Make a work image to render the shadow on:
479 my $shadow_work = Imager->new
481 xsize => $back->getwidth,
482 ysize => $back->getheight,
486 Extract the alpha channel from the source image, first the alpha version:
488 my $alpha = $src->convert(preset => "alpha");
490 and draw that on the work shadow:
495 left => $shadow_size,
499 otherwise just draw a box for the non-alpha source:
505 xmin => $shadow_size,
506 ymin => $shadow_size,
507 xmax => $shadow_size + $src->getwidth() - 1,
508 ymax => $shadow_size + $src->getheight() - 1,
511 Blur the work shadow:
513 $shadow_work->filter(type => "gaussian", stddev => $shadow_size);
515 Convert it to an RGB image with alpha:
517 $shadow_work = $shadow_work->convert
519 matrix => [ [ 0, $red / 255 ],
525 Draw that on the output image:
527 $out->rubthrough(src => $shadow_work);
529 Draw our original image on the output image, perhaps with an offset:
534 tx => $shadow_size + $x_offset,
535 ty => $shadow_size + $y_offset,
538 See F<samples/drop_shadow.pl> for an example of this recipe.
542 Tony Cook <tony@develop-help.com>
546 L<Imager>, L<Imager::Files>, L<Imager::Draw>.