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