$image->read(file=>$filename) or die $image->errstr;
+Or:
+
+ my $image = Imager->new(file => $filename)
+ or die Imager->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.
+=head2 Write an animated GIF
# build an array of images to use in the gif
my @images;
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 GIF files to JPEG files for
+example.
+
+By default, if the output format doesn't support transparency, Imager
+will compose the image onto a black background. You can override that
+by supplying an C<i_background> option to C<write()> or
+C<write_multi()>:
+
+ $image->write(file => "foo.jpg", i_background => "#808080")
+ or die $image->errstr;
+
+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;
+ }
+
+=head2 Transparent PNG
+
+To save to a transparent PNG (or GIF or TIFF) you need to start with
+an image with transparency.
+
+To make a transparent image, create an image object with 2 or 4
+channels:
+
+ # RGB with alpha channel
+ my $rgba = Imager->new(xsize => $width, ysize => $height, channels => 4);
+
+ # Gray with alpha channel
+ my $graya = Imager->new(xsize => $width, ysize => $height, channels => 2);
+
+By default, the created image will be transparent.
+
+Otherwise, if you have an existing image file with transparency,
+simply read it, and the transparency will be preserved.
+
=head1 IMAGE SYNTHESIS
=head2 Creating an image
my $rgb_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>4);
-To make a grayscale image:
+To make a gray-scale image:
my $gray = Imager->new(xsize=>$width, ysize=>$height, channels=>1);
-and a grayscale image with an alpha channel:
+and a gray-scale image with an alpha channel:
my $gray_alpha = Imager->new(xsize=>$width, ysize=>$height, channels=>2);
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.
+This is beside any other controls you need over access to data.
See L<CGI> for a module useful for processing CGI submitted data.
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:
+L<Imager::Files/set_file_limits()>. For example:
# limit to 10 million bytes of memory usage
Imager->set_file_limits(bytes => 10_000_000);
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
+example a semi-transparent 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
=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,
+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');
=head2 Shearing an image
+=head2 Convert to gray-scale
+
+To convert an RGB image to a gray-scale 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.
+file type, so C<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.
Keywords: DPI
+=head1 IMAGE MANIPULATION
+
+=head2 Replacing a color with transparency
+X<replacing colors>
+
+To replace a color with transparency you can use the
+L<Imager::Filters/difference()> method.
+
+ # make a work image the same size as our input
+ my $work = Imager->new(xsize => $in->getwidth, ysize => $in->getheight,
+ channels => $in->getchannels);
+ # and fill it with the color we want transparent
+ $work->box(filled => 1, color => $color);
+
+ # get an image with that color replaced with transparent black
+ my $out = $work->difference(other => $in);
+
+=head1 SPECIAL EFFECTS
+
+=head2 Drop Shadows
+X<drop shadow>X<effects, drop shadow>
+
+This can be used for a glow effect as well.
+
+First create a new image, either with an alpha channel (if you want
+transparency behind the shadow) or without, if you want a background
+color:
+
+ my $out = Imager->new
+ (
+ xsize => $shadow_size * 2 + $src->getwidth,
+ ysize => $shadow_size * 2 + $src->getheight,
+ channels => 4,
+ );
+ # fill it with your background color, if you want one
+ # $out->box(filled => 1, color => $back_color);
+
+Make a work image to render the shadow on:
+
+ my $shadow_work = Imager->new
+ (
+ xsize => $back->getwidth,
+ ysize => $back->getheight,
+ channels => 1,
+ );
+
+Extract the alpha channel from the source image, first the alpha version:
+
+ my $alpha = $src->convert(preset => "alpha");
+
+and draw that on the work shadow:
+
+ $shadow_work->paste
+ (
+ src => $slpha,
+ left => $shadow_size,
+ top => $shadow_size,
+ );
+
+otherwise just draw a box for the non-alpha source:
+
+ $shadow_work->box
+ (
+ filled => 1,
+ color => [ 255 ],
+ xmin => $shadow_size,
+ ymin => $shadow_size,
+ xmax => $shadow_size + $src->getwidth() - 1,
+ ymax => $shadow_size + $src->getheight() - 1,
+ );
+
+Blur the work shadow:
+
+ $shadow_work->filter(type => "gaussian", stddev => $shadow_size);
+
+Convert it to an RGB image with alpha:
+
+ $shadow_work = $shadow_work->convert
+ (
+ matrix => [ [ 0, $red / 255 ],
+ [ 0, $green / 255 ],
+ [ 0, $blue / 255 ],
+ [ 1 ] ]
+ );
+
+Draw that on the output image:
+
+ $out->rubthrough(src => $shadow_work);
+
+Draw our original image on the output image, perhaps with an offset:
+
+ $out->rubthrough
+ (
+ src => $src,
+ tx => $shadow_size + $x_offset,
+ ty => $shadow_size + $y_offset,
+ );
+
+See F<samples/drop_shadow.pl> for an example of this recipe.
+
=head1 AUTHOR
Tony Cook <tony@develop-help.com>