]> git.imager.perl.org - imager.git/blobdiff - lib/Imager/Cookbook.pod
extend some variable types to avoid overflows for mediancut
[imager.git] / lib / Imager / Cookbook.pod
index aa5a6dc3d28051caf25aa2931af9ce2cc1a8b268..52fd9f2b0dde097e6dbb862e63a3217fb3b40175 100644 (file)
@@ -16,13 +16,18 @@ This is described in detail in L<Imager::Files>.
 
   $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;
@@ -44,6 +49,66 @@ 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 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
@@ -57,11 +122,11 @@ If you also want an alpha channel:
 
   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);
 
@@ -112,7 +177,7 @@ 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.
+This is beside any other controls you need over access to data.
 
 See L<CGI> for a module useful for processing CGI submitted data.
 
@@ -226,7 +291,7 @@ 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:
+L<Imager::Files/set_file_limits()>.  For example:
 
   # limit to 10 million bytes of memory usage
   Imager->set_file_limits(bytes => 10_000_000);
@@ -255,7 +320,7 @@ Then paste the source image into the new image:
 
 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
@@ -279,8 +344,8 @@ pasting the source for simplicity:
 
 =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');
@@ -320,13 +385,23 @@ transformed text into.
 
 =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.
@@ -362,6 +437,106 @@ in pixels per centimeter, you would do:
 
 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>