]> git.imager.perl.org - imager.git/blob - lib/Imager/Cookbook.pod
the cookbook said we couldn't limit image sizes, but we can now. Fix
[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 =head1 IMAGE SYNTHESIS
48
49 =head2 Creating an image
50
51 To create a simple RGB image, supply the image width and height to the
52 new() method:
53
54   my $rgb = Imager->new(xsize=>$width, ysize=>$height);
55
56 If you also want an alpha channel:
57
58   my $rgb_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>4);
59
60 To make a grayscale image:
61
62   my $gray = Imager->new(xsize=>$width, ysize=>$height, channels=>1);
63
64 and a grayscale image with an alpha channel:
65
66   my $gray_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>2);
67
68 When a new image is created this way all samples are set to zero -
69 black for 1 or 3 channel images, transparent black for 2 or 4 channel
70 images.
71
72 You can also create paletted images and images with more than 8-bits
73 per channel, see L<Imager::ImageTypes> for more details.
74
75 =head2 Setting the background of a new image
76
77 To set the background of a new image to a solid color, use the box()
78 method with no limits, and C<< filled=>1 >>:
79
80   $image->box(filled=>1, color=>$color);
81
82 As always, a color can be specified as an L<Imager::Color> object:
83
84   my $white = Imager::Color->new(255, 255, 255);
85   $image->box(filled=>1, color=>$white);
86
87 or you supply any single scalar that Imager::Color's new() method
88 accepts as a color description:
89
90   $image->box(filled=>1, color=>'white');
91   $image->box(filled=>1, color=>'#FF0000');
92   $image->box(filled=>1, color=>[ 255, 255, 255 ]);
93
94 You can also fill the image with a fill object:
95
96   use Imager::Fill;
97   # create the fill object
98   my $fill = Imager::Fill->new(hatch=>'check1x1')
99   $image->box(fill=>$fill);
100
101   # let Imager create one automatically
102   $image->box(fill=>{ hatch=>'check1x1' });
103
104 See L<Imager::Fill> for information on Imager's fill objects.
105
106 =head1 WORLD WIDE WEB
107
108 As with any CGI script it's up to you to validate data and set limits
109 on any parameters supplied to Imager.
110
111 For example, if you allow the caller to set the size of an output
112 image you should limit the size to prevent the client from specifying
113 an image size that will consume all available memory.
114
115 This is beside any any other controls you need over access to data.
116
117 See L<CGI> for a module useful for processing CGI submitted data.
118
119 =head2 Returning an image from a CGI script
120
121 This is similar to writing to a file, but you also need to supply the
122 information needed by the web browser to identify the file format:
123
124   my $img = ....; # create the image and generate the contents
125   ++$|; # make sure the content type isn't buffered
126   print "Content-Type: image/png\n\n";
127   binmode STDOUT;
128   $img->write(fd=>fileno(STDOUT), type=>'png')
129     or die $img->errstr;
130
131 You need to set the Content-Type header depending on the file format
132 you send to the web browser.
133
134 If you want to supply a content-length header, write the image to a
135 scalar as a buffer:
136
137   my $img = ....; # create the image and generate the contents
138   my $data;
139   $img->write(type=>'png', data=>\$data)
140     or die $img->errstr;
141   print "Content-Type: image/png\n";
142   print "Content-Length: ",length($data),"\n\n";
143   binmode STDOUT;
144   print $data;
145
146 See C<samples/samp-scale.cgi> and C<samples/samp-image.cgi> for a
147 couple of simple examples of producing an image from CGI.
148
149 =head2 Inserting a CGI image in a page
150
151 There's occasionally confusion on how to display an image generated by
152 Imager in a page generated by a CGI.
153
154 Your web browser handles this process as two requests, one for the
155 HTML page, and another for the image itself.
156
157 Each request needs to perform validation since an attacker can control
158 the values supplied to both requests.
159
160 How you make the data available to the image generation code depends
161 on your application.
162
163 See C<samples/samp-form.cgi> and C<samples/samp-image.cgi> in the
164 Imager distribution for one approach.  The POD in C<samp-form.cgi>
165 also discusses some of the issues involved.
166
167 =head2 Parsing an image posted via CGI
168
169 C<WARNING>: file format attacks have become a common attack vector,
170 make sure you have up to date image file format libraries, otherwise
171 trying to parse uploaded files, whether with Imager or some other
172 tool, may result in a remote attacker being able to run their own code
173 on your system.
174
175 If your HTML form uses the correct magic, it can upload files to your
176 CGI script, in particular, you need to use C< method="post" > and
177 C<enctype="multipart/form-data"> in the C<form> tag, and use
178 C<type="file"> in the C<input>, for example:
179
180   <form action="/cgi-bin/yourprogram" method="post" 
181         enctype="multipart/form-data">
182     <input type="file" name="myimage" />
183     <input type="submit value="Upload Image" />
184   </form>
185
186 To process the form:
187
188 =over
189
190 =item 1.
191
192 first check that the user supplied a file
193
194 =item 2.
195
196 get the file handle
197
198 =item 3.
199
200 have Imager read the image
201
202 =back
203
204   # returns the client's name for the file, don't open this locally
205   my $cgi = CGI->new;
206   # 1. check the user supplied a file
207   my $filename = $cgi->param('myimage');
208   if ($filename) {
209     # 2. get the file handle
210     my $fh = $cgi->upload('myimage');
211     if ($fh) {
212       binmode $fh;
213       
214       # 3. have Imager read the image
215       my $img = Imager->new;
216       if ($img->read(fh=>$fh)) {
217         # we can now process the image
218       }
219     }
220     # else, you probably have an incorrect form or input tag
221   }
222   # else, the user didn't select a file
223
224 See C<samples/samp-scale.cgi> and C<samples/samp-tags.cgi> in the
225 Imager distribution for example code.
226
227 You may also want to set limits on the size of the image read, using
228 Imager's C<set_file_limits> method, documented in
229 L<Imager::Files/set_file_limits>.  For example:
230
231   # limit to 10 million bytes of memory usage
232   Imager->set_file_limits(bytes => 10_000_000);
233
234   # limit to 1024 x 1024
235   Imager->set_file_limits(width => 1024, height => 1024);
236
237 =head1 DRAWING
238
239 =head2 Adding a border to an image
240
241 First make a new image with space for the border:
242
243   my $border_width = ...;
244   my $border_height = ...;
245   my $out = Imager->new(xsize => $source->getwidth() + 2 * $border_width,
246                         ysize => $source->getheight() + 2 * $border_height,
247                         bits => $source->bits,
248                         channels => $source->getchannels);
249
250 Then paste the source image into the new image:
251
252   $out->paste(left => $border_width,
253               top => $border_height,
254               img => $source);
255
256 Whether you draw the border before or after pasting the original image
257 depends on whether you want the border to overlap the image, for
258 example a semi-tranparent border drawn after pasting the source image
259 could overlap the edge without hiding it.
260
261 If you want a solid border you could just fill the image before
262 pasting the source for simplicity:
263
264   $out->box(filled=>1, color=>'red');
265   $out->paste(left => $border_width,
266               top => $border_height,
267               img => $source);
268
269
270 =head1 TEXT
271
272 =head2 Drawing text
273
274 =head2 Aligning text
275
276 =head2 Measuring text
277
278 =head2 Word wrapping text
279
280 =head2 Shearing (slanting) or Rotating text
281
282 This requires that you have Imager installed with Freetype 2.x support
283 installed, and that the font be created using the Freetype 2.x driver,
284 for example:
285
286   my $font = Imager::Font->new(file=>$fontfile, type=>'ft2');
287
288 First you need a transformation matrix, for shearing that could be:
289
290   my $angle_in_radians = ...;
291   my $tan_angle = sin($angle_rads) / cos($angle_rads);
292   # shear horizontally, supply this as y instead to do it vertically
293   my $matrix = Imager::Matrix2d->shear(x=>$tan_angle);
294
295 For rotation that would be:
296
297   my $matrix = Imager::Matrix2d->rotate(radians => $angle_in_radians);
298
299 or:
300
301   my $matrix = Imager::Matrix2d->rotate(degrees => $angle_in_degrees);
302
303 Feed that to the font object:
304
305   $font->transform(matrix => $matrix);
306
307 and draw the text as normal:
308
309   $image->string(string => $text,
310                  x => $where_x,
311                  y => $where_y,
312                  color => $color,
313                  font => $font);
314
315 See samples/slant_text.pl for a comprehensive example, including
316 calculating the transformed bounding box to create an image to fit the
317 transformed text into.
318
319 =head1 IMAGE TRANSFORMATION
320
321 =head2 Shearing an image
322
323 =head1 METADATA
324
325 =head2 Image spatial resolution
326
327 Keywords: DPI
328
329 =head1 AUTHOR
330
331 Tony Cook <tony@develop-help.com>
332
333 =head1 SEE ALSO
334
335 L<Imager>, L<Imager::Files>, L<Imager::Draw>.
336
337 =cut