summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl.straw/lib/Imager/Cookbook.pod
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl.straw/lib/Imager/Cookbook.pod')
-rwxr-xr-xMaster/tlpkg/tlperl.straw/lib/Imager/Cookbook.pod429
1 files changed, 429 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl.straw/lib/Imager/Cookbook.pod b/Master/tlpkg/tlperl.straw/lib/Imager/Cookbook.pod
new file mode 100755
index 00000000000..8d9cba4a273
--- /dev/null
+++ b/Master/tlpkg/tlperl.straw/lib/Imager/Cookbook.pod
@@ -0,0 +1,429 @@
+=head1 NAME
+
+Imager::Cookbook - recipes working with Imager
+
+=head1 DESCRIPTION
+
+Various simple and not so simple ways to do things with Imager.
+
+=head1 FILES
+
+This is described in detail in L<Imager::Files>.
+
+=head2 Reading an image from a file
+
+ my $image = Imager->new;
+
+ $image->read(file=>$filename) or die $image->errstr;
+
+See L<Imager::Files>.
+
+=head2 Writing an image to a file
+
+ $image->write(file=>$filename) or die $image->errstr;
+
+=head2 Write an animated gif.
+
+ # build an array of images to use in the gif
+ my @images;
+ # synthesize the images or read them from files, it doesn't matter
+ ...
+
+ # write the gif
+ Imager->write_multi({ file=>$filename, type=>'gif' }, @images)
+ or die Imager->errstr;
+
+See L<Imager::Files/"Writing an animated GIF"> for a more detailed
+example.
+
+=head2 Reading multiple images from one file
+
+Some formats, like GIF and TIFF support multiple images per file. Use
+the L<read_multi()|Imager::Files> method to read them:
+
+ my @images = Imager->read_multi(file=>$filename)
+ or die Imager->errstr;
+
+=head2 Converting from one file format to another
+
+This is as simple as reading the original file and writing the new
+file, for single images:
+
+ my $image = Imager->new;
+ # Imager auto-detects the input file type
+ $image->read(file => $input_filename)
+ or die $image->errstr;
+ # Imager derives the output file format from the filename
+ $image->write(file => $output_filename)
+ or die $image->errstr;
+
+ # or you can supply a type parameter:
+ $image->write(file => $output_filename, type => 'gif')
+ or die $image->errstr;
+
+The main issue that can occur with this is if the input file has
+transparency and the output file format doesn't support that. This
+can be a problem when converting from GIFs to JPEGs for example.
+
+To work around that you can compose the source image onto a background
+color:
+
+ if ($image->getchannels == 4 or $image->getchannels == 2) {
+ my $back = Imager->new(xsize => $image->getwidth,
+ ysize => $image->getheight);
+ # grey background for grayscale images, red for color
+ my $back_color = $image->getchannels == 2 ? [ 128 ] : 'red';
+ $back->box(filled => 1, color => $back_color);
+ $back->rubthrough(src => $image);
+ $image = $back;
+ }
+ # now we can write safely to jpeg or pnm
+
+Some formats support multiple files, so if you want to convert from
+say tiff to jpeg, you'll need multiple output files:
+
+ my @images = Imager->read_multi(file => 'input.tif')
+ or die Imager->errstr;
+ my $index = 1;
+ for my $image (@images) {
+ $image->write(file => sprintf('output%02d.jpg', $index++))
+ or die $image->errstr;
+ }
+
+=head1 IMAGE SYNTHESIS
+
+=head2 Creating an image
+
+To create a simple RGB image, supply the image width and height to the
+new() method:
+
+ my $rgb = Imager->new(xsize=>$width, ysize=>$height);
+
+If you also want an alpha channel:
+
+ my $rgb_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>4);
+
+To make a grayscale image:
+
+ my $gray = Imager->new(xsize=>$width, ysize=>$height, channels=>1);
+
+and a grayscale image with an alpha channel:
+
+ my $gray_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>2);
+
+When a new image is created this way all samples are set to zero -
+black for 1 or 3 channel images, transparent black for 2 or 4 channel
+images.
+
+You can also create paletted images and images with more than 8-bits
+per channel, see L<Imager::ImageTypes> for more details.
+
+=head2 Setting the background of a new image
+
+To set the background of a new image to a solid color, use the box()
+method with no limits, and C<< filled=>1 >>:
+
+ $image->box(filled=>1, color=>$color);
+
+As always, a color can be specified as an L<Imager::Color> object:
+
+ my $white = Imager::Color->new(255, 255, 255);
+ $image->box(filled=>1, color=>$white);
+
+or you supply any single scalar that Imager::Color's new() method
+accepts as a color description:
+
+ $image->box(filled=>1, color=>'white');
+ $image->box(filled=>1, color=>'#FF0000');
+ $image->box(filled=>1, color=>[ 255, 255, 255 ]);
+
+You can also fill the image with a fill object:
+
+ use Imager::Fill;
+ # create the fill object
+ my $fill = Imager::Fill->new(hatch=>'check1x1')
+ $image->box(fill=>$fill);
+
+ # let Imager create one automatically
+ $image->box(fill=>{ hatch=>'check1x1' });
+
+See L<Imager::Fill> for information on Imager's fill objects.
+
+=head1 WORLD WIDE WEB
+
+As with any CGI script it's up to you to validate data and set limits
+on any parameters supplied to Imager.
+
+For example, if you allow the caller to set the size of an output
+image you should limit the size to prevent the client from specifying
+an image size that will consume all available memory.
+
+This is beside any any other controls you need over access to data.
+
+See L<CGI> for a module useful for processing CGI submitted data.
+
+=head2 Returning an image from a CGI script
+
+This is similar to writing to a file, but you also need to supply the
+information needed by the web browser to identify the file format:
+
+ my $img = ....; # create the image and generate the contents
+ ++$|; # make sure the content type isn't buffered
+ print "Content-Type: image/png\n\n";
+ binmode STDOUT;
+ $img->write(fd=>fileno(STDOUT), type=>'png')
+ or die $img->errstr;
+
+You need to set the Content-Type header depending on the file format
+you send to the web browser.
+
+If you want to supply a content-length header, write the image to a
+scalar as a buffer:
+
+ my $img = ....; # create the image and generate the contents
+ my $data;
+ $img->write(type=>'png', data=>\$data)
+ or die $img->errstr;
+ print "Content-Type: image/png\n";
+ print "Content-Length: ",length($data),"\n\n";
+ binmode STDOUT;
+ print $data;
+
+See C<samples/samp-scale.cgi> and C<samples/samp-image.cgi> for a
+couple of simple examples of producing an image from CGI.
+
+=head2 Inserting a CGI image in a page
+
+There's occasionally confusion on how to display an image generated by
+Imager in a page generated by a CGI.
+
+Your web browser handles this process as two requests, one for the
+HTML page, and another for the image itself.
+
+Each request needs to perform validation since an attacker can control
+the values supplied to both requests.
+
+How you make the data available to the image generation code depends
+on your application.
+
+See C<samples/samp-form.cgi> and C<samples/samp-image.cgi> in the
+Imager distribution for one approach. The POD in C<samp-form.cgi>
+also discusses some of the issues involved.
+
+=head2 Parsing an image posted via CGI
+
+C<WARNING>: file format attacks have become a common attack vector,
+make sure you have up to date image file format libraries, otherwise
+trying to parse uploaded files, whether with Imager or some other
+tool, may result in a remote attacker being able to run their own code
+on your system.
+
+If your HTML form uses the correct magic, it can upload files to your
+CGI script, in particular, you need to use C< method="post" > and
+C<enctype="multipart/form-data"> in the C<form> tag, and use
+C<type="file"> in the C<input>, for example:
+
+ <form action="/cgi-bin/yourprogram" method="post"
+ enctype="multipart/form-data">
+ <input type="file" name="myimage" />
+ <input type="submit value="Upload Image" />
+ </form>
+
+To process the form:
+
+=over
+
+=item 1.
+
+first check that the user supplied a file
+
+=item 2.
+
+get the file handle
+
+=item 3.
+
+have Imager read the image
+
+=back
+
+ # returns the client's name for the file, don't open this locally
+ my $cgi = CGI->new;
+ # 1. check the user supplied a file
+ my $filename = $cgi->param('myimage');
+ if ($filename) {
+ # 2. get the file handle
+ my $fh = $cgi->upload('myimage');
+ if ($fh) {
+ binmode $fh;
+
+ # 3. have Imager read the image
+ my $img = Imager->new;
+ if ($img->read(fh=>$fh)) {
+ # we can now process the image
+ }
+ }
+ # else, you probably have an incorrect form or input tag
+ }
+ # else, the user didn't select a file
+
+See C<samples/samp-scale.cgi> and C<samples/samp-tags.cgi> in the
+Imager distribution for example code.
+
+You may also want to set limits on the size of the image read, using
+Imager's C<set_file_limits> method, documented in
+L<Imager::Files/set_file_limits>. For example:
+
+ # limit to 10 million bytes of memory usage
+ Imager->set_file_limits(bytes => 10_000_000);
+
+ # limit to 1024 x 1024
+ Imager->set_file_limits(width => 1024, height => 1024);
+
+=head1 DRAWING
+
+=head2 Adding a border to an image
+
+First make a new image with space for the border:
+
+ my $border_width = ...;
+ my $border_height = ...;
+ my $out = Imager->new(xsize => $source->getwidth() + 2 * $border_width,
+ ysize => $source->getheight() + 2 * $border_height,
+ bits => $source->bits,
+ channels => $source->getchannels);
+
+Then paste the source image into the new image:
+
+ $out->paste(left => $border_width,
+ top => $border_height,
+ img => $source);
+
+Whether you draw the border before or after pasting the original image
+depends on whether you want the border to overlap the image, for
+example a semi-tranparent border drawn after pasting the source image
+could overlap the edge without hiding it.
+
+If you want a solid border you could just fill the image before
+pasting the source for simplicity:
+
+ $out->box(filled=>1, color=>'red');
+ $out->paste(left => $border_width,
+ top => $border_height,
+ img => $source);
+
+
+=head1 TEXT
+
+=head2 Drawing text
+
+=head2 Aligning text
+
+=head2 Measuring text
+
+=head2 Word wrapping text
+
+=head2 Shearing (slanting) or Rotating text
+
+This requires that you have Imager installed with Freetype 2.x support
+installed, and that the font be created using the Freetype 2.x driver,
+for example:
+
+ my $font = Imager::Font->new(file=>$fontfile, type=>'ft2');
+
+First you need a transformation matrix, for shearing that could be:
+
+ my $angle_in_radians = ...;
+ my $tan_angle = sin($angle_rads) / cos($angle_rads);
+ # shear horizontally, supply this as y instead to do it vertically
+ my $matrix = Imager::Matrix2d->shear(x=>$tan_angle);
+
+For rotation that would be:
+
+ my $matrix = Imager::Matrix2d->rotate(radians => $angle_in_radians);
+
+or:
+
+ my $matrix = Imager::Matrix2d->rotate(degrees => $angle_in_degrees);
+
+Feed that to the font object:
+
+ $font->transform(matrix => $matrix);
+
+and draw the text as normal:
+
+ $image->string(string => $text,
+ x => $where_x,
+ y => $where_y,
+ color => $color,
+ font => $font);
+
+See samples/slant_text.pl for a comprehensive example, including
+calculating the transformed bounding box to create an image to fit the
+transformed text into.
+
+=head1 IMAGE TRANSFORMATION
+
+=head2 Shearing an image
+
+=head2 Convert to grayscale
+
+To convert an RGB image to a grayscale image, use the convert method:
+
+ my $grey = $image->convert(preset => 'gray');
+
+convert() returns a new image.
+
+See: L<Imager::Transformations/"Color transformations">
+
+=head1 METADATA
+
+=head2 Image format
+
+When Imager reads a file it does a magic number check to determine the
+file type, so "foo.png" could actually be a GIF image, and Imager will
+read it anyway.
+
+You can check the actual format of the image by looking at the
+C<i_format> tag.
+
+ my $format = $image->tags(name=>'i_format');
+
+=head2 Image spatial resolution
+
+Most image file formats store information about the physical size of
+the pixels, though in some cases that information isn't useful.
+
+Imager stores this information in the tags C<i_xres> and C<i_yres>,
+and this is always stored in dots per inch.
+
+Some formats, including TIFF and JPEG allow you to change the units
+spatial resolution information is stored in, if you set the tag that
+changes this the Imager will convert C<i_xres> and C<i_yres> to those
+units when it writes the file.
+
+For example to set the resolution to 300 dpi:
+
+ $image->settag(name => 'i_xres', value => 300);
+ $image->settag(name => 'i_yres', value => 300);
+
+If you want the file format to store the resolution in some other
+unit, for example you can write a TIFF file that stores the resolution
+in pixels per centimeter, you would do:
+
+ # 150 pixels/cm
+ $image->settag(name => 'i_xres', value => 150 * 2.54);
+ $image->settag(name => 'i_yres', value => 150 * 2.54);
+ $image->settag(name => 'tiff_resolutionunit', value => 3);
+
+Keywords: DPI
+
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=head1 SEE ALSO
+
+L<Imager>, L<Imager::Files>, L<Imager::Draw>.
+
+=cut