1Imager::Cookbook(3) User Contributed Perl Documentation Imager::Cookbook(3)
2
3
4
6 Imager::Cookbook - recipes working with Imager
7
9 Various simple and not so simple ways to do things with Imager.
10
12 This is described in detail in Imager::Files.
13
14 Reading an image from a file
15 my $image = Imager->new;
16
17 $image->read(file=>$filename) or die $image->errstr;
18
19 Or:
20
21 my $image = Imager->new(file => $filename)
22 or die Imager->errstr;
23
24 See Imager::Files.
25
26 Writing an image to a file
27 $image->write(file=>$filename) or die $image->errstr;
28
29 Write an animated GIF
30 # build an array of images to use in the gif
31 my @images;
32 # synthesize the images or read them from files, it doesn't matter
33 ...
34
35 # write the gif
36 Imager->write_multi({ file=>$filename, type=>'gif' }, @images)
37 or die Imager->errstr;
38
39 See "Writing an animated GIF" in Imager::Files for a more detailed
40 example.
41
42 Reading multiple images from one file
43 Some formats, like GIF and TIFF support multiple images per file. Use
44 the read_multi() method to read them:
45
46 my @images = Imager->read_multi(file=>$filename)
47 or die Imager->errstr;
48
49 Converting from one file format to another
50 This is as simple as reading the original file and writing the new
51 file, for single images:
52
53 my $image = Imager->new;
54 # Imager auto-detects the input file type
55 $image->read(file => $input_filename)
56 or die $image->errstr;
57 # Imager derives the output file format from the filename
58 $image->write(file => $output_filename)
59 or die $image->errstr;
60
61 # or you can supply a type parameter:
62 $image->write(file => $output_filename, type => 'gif')
63 or die $image->errstr;
64
65 The main issue that can occur with this is if the input file has
66 transparency and the output file format doesn't support that. This can
67 be a problem when converting from GIF files to JPEG files for example.
68
69 By default, if the output format doesn't support transparency, Imager
70 will compose the image onto a black background. You can override that
71 by supplying an "i_background" option to "write()" or "write_multi()":
72
73 $image->write(file => "foo.jpg", i_background => "#808080")
74 or die $image->errstr;
75
76 Some formats support multiple files, so if you want to convert from say
77 TIFF to JPEG, you'll need multiple output files:
78
79 my @images = Imager->read_multi(file => 'input.tif')
80 or die Imager->errstr;
81 my $index = 1;
82 for my $image (@images) {
83 $image->write(file => sprintf('output%02d.jpg', $index++))
84 or die $image->errstr;
85 }
86
87 Transparent PNG
88 To save to a transparent PNG (or GIF or TIFF) you need to start with an
89 image with transparency.
90
91 To make a transparent image, create an image object with 2 or 4
92 channels:
93
94 # RGB with alpha channel
95 my $rgba = Imager->new(xsize => $width, ysize => $height, channels => 4);
96
97 # Gray with alpha channel
98 my $graya = Imager->new(xsize => $width, ysize => $height, channels => 2);
99
100 By default, the created image will be transparent.
101
102 Otherwise, if you have an existing image file with transparency, simply
103 read it, and the transparency will be preserved.
104
106 Creating an image
107 To create a simple RGB image, supply the image width and height to the
108 new() method:
109
110 my $rgb = Imager->new(xsize=>$width, ysize=>$height);
111
112 If you also want an alpha channel:
113
114 my $rgb_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>4);
115
116 To make a gray-scale image:
117
118 my $gray = Imager->new(xsize=>$width, ysize=>$height, channels=>1);
119
120 and a gray-scale image with an alpha channel:
121
122 my $gray_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>2);
123
124 When a new image is created this way all samples are set to zero -
125 black for 1 or 3 channel images, transparent black for 2 or 4 channel
126 images.
127
128 You can also create paletted images and images with more than 8-bits
129 per channel, see Imager::ImageTypes for more details.
130
131 Setting the background of a new image
132 To set the background of a new image to a solid color, use the box()
133 method with no limits, and "filled=>1":
134
135 $image->box(filled=>1, color=>$color);
136
137 As always, a color can be specified as an Imager::Color object:
138
139 my $white = Imager::Color->new(255, 255, 255);
140 $image->box(filled=>1, color=>$white);
141
142 or you supply any single scalar that Imager::Color's new() method
143 accepts as a color description:
144
145 $image->box(filled=>1, color=>'white');
146 $image->box(filled=>1, color=>'#FF0000');
147 $image->box(filled=>1, color=>[ 255, 255, 255 ]);
148
149 You can also fill the image with a fill object:
150
151 use Imager::Fill;
152 # create the fill object
153 my $fill = Imager::Fill->new(hatch=>'check1x1')
154 $image->box(fill=>$fill);
155
156 # let Imager create one automatically
157 $image->box(fill=>{ hatch=>'check1x1' });
158
159 See Imager::Fill for information on Imager's fill objects.
160
162 As with any CGI script it's up to you to validate data and set limits
163 on any parameters supplied to Imager.
164
165 For example, if you allow the caller to set the size of an output image
166 you should limit the size to prevent the client from specifying an
167 image size that will consume all available memory.
168
169 This is beside any other controls you need over access to data.
170
171 See CGI for a module useful for processing CGI submitted data.
172
173 Returning an image from a CGI script
174 This is similar to writing to a file, but you also need to supply the
175 information needed by the web browser to identify the file format:
176
177 my $img = ....; # create the image and generate the contents
178 ++$|; # make sure the content type isn't buffered
179 print "Content-Type: image/png\n\n";
180 binmode STDOUT;
181 $img->write(fd=>fileno(STDOUT), type=>'png')
182 or die $img->errstr;
183
184 You need to set the Content-Type header depending on the file format
185 you send to the web browser.
186
187 If you want to supply a content-length header, write the image to a
188 scalar as a buffer:
189
190 my $img = ....; # create the image and generate the contents
191 my $data;
192 $img->write(type=>'png', data=>\$data)
193 or die $img->errstr;
194 print "Content-Type: image/png\n";
195 print "Content-Length: ",length($data),"\n\n";
196 binmode STDOUT;
197 print $data;
198
199 See "samples/samp-scale.cgi" and "samples/samp-image.cgi" for a couple
200 of simple examples of producing an image from CGI.
201
202 Inserting a CGI image in a page
203 There's occasionally confusion on how to display an image generated by
204 Imager in a page generated by a CGI.
205
206 Your web browser handles this process as two requests, one for the HTML
207 page, and another for the image itself.
208
209 Each request needs to perform validation since an attacker can control
210 the values supplied to both requests.
211
212 How you make the data available to the image generation code depends on
213 your application.
214
215 See "samples/samp-form.cgi" and "samples/samp-image.cgi" in the Imager
216 distribution for one approach. The POD in "samp-form.cgi" also
217 discusses some of the issues involved.
218
219 Parsing an image posted via CGI
220 "WARNING": file format attacks have become a common attack vector, make
221 sure you have up to date image file format libraries, otherwise trying
222 to parse uploaded files, whether with Imager or some other tool, may
223 result in a remote attacker being able to run their own code on your
224 system.
225
226 If your HTML form uses the correct magic, it can upload files to your
227 CGI script, in particular, you need to use " method="post" " and
228 "enctype="multipart/form-data"" in the "form" tag, and use
229 "type="file"" in the "input", for example:
230
231 <form action="/cgi-bin/yourprogram" method="post"
232 enctype="multipart/form-data">
233 <input type="file" name="myimage" />
234 <input type="submit value="Upload Image" />
235 </form>
236
237 To process the form:
238
239 1. first check that the user supplied a file
240
241 2. get the file handle
242
243 3. have Imager read the image
244
245 # returns the client's name for the file, don't open this locally
246 my $cgi = CGI->new;
247 # 1. check the user supplied a file
248 my $filename = $cgi->param('myimage');
249 if ($filename) {
250 # 2. get the file handle
251 my $fh = $cgi->upload('myimage');
252 if ($fh) {
253 binmode $fh;
254
255 # 3. have Imager read the image
256 my $img = Imager->new;
257 if ($img->read(fh=>$fh)) {
258 # we can now process the image
259 }
260 }
261 # else, you probably have an incorrect form or input tag
262 }
263 # else, the user didn't select a file
264
265 See "samples/samp-scale.cgi" and "samples/samp-tags.cgi" in the Imager
266 distribution for example code.
267
268 You may also want to set limits on the size of the image read, using
269 Imager's "set_file_limits" method, documented in "set_file_limits()" in
270 Imager::Files. For example:
271
272 # limit to 10 million bytes of memory usage
273 Imager->set_file_limits(bytes => 10_000_000);
274
275 # limit to 1024 x 1024
276 Imager->set_file_limits(width => 1024, height => 1024);
277
279 Adding a border to an image
280 First make a new image with space for the border:
281
282 my $border_width = ...;
283 my $border_height = ...;
284 my $out = Imager->new(xsize => $source->getwidth() + 2 * $border_width,
285 ysize => $source->getheight() + 2 * $border_height,
286 bits => $source->bits,
287 channels => $source->getchannels);
288
289 Then paste the source image into the new image:
290
291 $out->paste(left => $border_width,
292 top => $border_height,
293 img => $source);
294
295 Whether you draw the border before or after pasting the original image
296 depends on whether you want the border to overlap the image, for
297 example a semi-transparent border drawn after pasting the source image
298 could overlap the edge without hiding it.
299
300 If you want a solid border you could just fill the image before pasting
301 the source for simplicity:
302
303 $out->box(filled=>1, color=>'red');
304 $out->paste(left => $border_width,
305 top => $border_height,
306 img => $source);
307
309 Drawing text
310 Aligning text
311 Measuring text
312 Word wrapping text
313 Shearing (slanting) or Rotating text
314 This requires that you have Imager installed with FreeType 2.x support
315 installed, and that the font be created using the FreeType 2.x driver,
316 for example:
317
318 my $font = Imager::Font->new(file=>$fontfile, type=>'ft2');
319
320 First you need a transformation matrix, for shearing that could be:
321
322 my $angle_in_radians = ...;
323 my $tan_angle = sin($angle_rads) / cos($angle_rads);
324 # shear horizontally, supply this as y instead to do it vertically
325 my $matrix = Imager::Matrix2d->shear(x=>$tan_angle);
326
327 For rotation that would be:
328
329 my $matrix = Imager::Matrix2d->rotate(radians => $angle_in_radians);
330
331 or:
332
333 my $matrix = Imager::Matrix2d->rotate(degrees => $angle_in_degrees);
334
335 Feed that to the font object:
336
337 $font->transform(matrix => $matrix);
338
339 and draw the text as normal:
340
341 $image->string(string => $text,
342 x => $where_x,
343 y => $where_y,
344 color => $color,
345 font => $font);
346
347 See samples/slant_text.pl for a comprehensive example, including
348 calculating the transformed bounding box to create an image to fit the
349 transformed text into.
350
352 Shearing an image
353 Convert to gray-scale
354 To convert an RGB image to a gray-scale image, use the convert method:
355
356 my $grey = $image->convert(preset => 'gray');
357
358 convert() returns a new image.
359
360 See: "Color transformations" in Imager::Transformations
361
363 Image format
364 When Imager reads a file it does a magic number check to determine the
365 file type, so "foo.png" could actually be a GIF image, and Imager will
366 read it anyway.
367
368 You can check the actual format of the image by looking at the
369 "i_format" tag.
370
371 my $format = $image->tags(name=>'i_format');
372
373 Image spatial resolution
374 Most image file formats store information about the physical size of
375 the pixels, though in some cases that information isn't useful.
376
377 Imager stores this information in the tags "i_xres" and "i_yres", and
378 this is always stored in dots per inch.
379
380 Some formats, including TIFF and JPEG allow you to change the units
381 spatial resolution information is stored in, if you set the tag that
382 changes this the Imager will convert "i_xres" and "i_yres" to those
383 units when it writes the file.
384
385 For example to set the resolution to 300 dpi:
386
387 $image->settag(name => 'i_xres', value => 300);
388 $image->settag(name => 'i_yres', value => 300);
389
390 If you want the file format to store the resolution in some other unit,
391 for example you can write a TIFF file that stores the resolution in
392 pixels per centimeter, you would do:
393
394 # 150 pixels/cm
395 $image->settag(name => 'i_xres', value => 150 * 2.54);
396 $image->settag(name => 'i_yres', value => 150 * 2.54);
397 $image->settag(name => 'tiff_resolutionunit', value => 3);
398
399 Keywords: DPI
400
402 Replacing a color with transparency
403 To replace a color with transparency you can use the "difference()" in
404 Imager::Filters method.
405
406 # make a work image the same size as our input
407 my $work = Imager->new(xsize => $in->getwidth, ysize => $in->getheight,
408 channels => $in->getchannels);
409 # and fill it with the color we want transparent
410 $work->box(filled => 1, color => $color);
411
412 # get an image with that color replaced with transparent black
413 my $out = $work->difference(other => $in);
414
416 Drop Shadows
417 This can be used for a glow effect as well.
418
419 First create a new image, either with an alpha channel (if you want
420 transparency behind the shadow) or without, if you want a background
421 color:
422
423 my $out = Imager->new
424 (
425 xsize => $shadow_size * 2 + $src->getwidth,
426 ysize => $shadow_size * 2 + $src->getheight,
427 channels => 4,
428 );
429 # fill it with your background color, if you want one
430 # $out->box(filled => 1, color => $back_color);
431
432 Make a work image to render the shadow on:
433
434 my $shadow_work = Imager->new
435 (
436 xsize => $back->getwidth,
437 ysize => $back->getheight,
438 channels => 1,
439 );
440
441 Extract the alpha channel from the source image, first the alpha
442 version:
443
444 my $alpha = $src->convert(preset => "alpha");
445
446 and draw that on the work shadow:
447
448 $shadow_work->paste
449 (
450 src => $slpha,
451 left => $shadow_size,
452 top => $shadow_size,
453 );
454
455 otherwise just draw a box for the non-alpha source:
456
457 $shadow_work->box
458 (
459 filled => 1,
460 color => [ 255 ],
461 xmin => $shadow_size,
462 ymin => $shadow_size,
463 xmax => $shadow_size + $src->getwidth() - 1,
464 ymax => $shadow_size + $src->getheight() - 1,
465 );
466
467 Blur the work shadow:
468
469 $shadow_work->filter(type => "gaussian", stddev => $shadow_size);
470
471 Convert it to an RGB image with alpha:
472
473 $shadow_work = $shadow_work->convert
474 (
475 matrix => [ [ 0, $red / 255 ],
476 [ 0, $green / 255 ],
477 [ 0, $blue / 255 ],
478 [ 1 ] ]
479 );
480
481 Draw that on the output image:
482
483 $out->rubthrough(src => $shadow_work);
484
485 Draw our original image on the output image, perhaps with an offset:
486
487 $out->rubthrough
488 (
489 src => $src,
490 tx => $shadow_size + $x_offset,
491 ty => $shadow_size + $y_offset,
492 );
493
494 See samples/drop_shadow.pl for an example of this recipe.
495
497 Tony Cook <tony@develop-help.com>
498
500 Imager, Imager::Files, Imager::Draw.
501
502
503
504perl v5.32.0 2020-07-28 Imager::Cookbook(3)