NAME
   Plack::Middleware::Image::Scale - Resize jpeg and png images on the fly

VERSION
   version 0.005

SYNOPSIS
       ## example1.psgi

       builder {
           enable 'ConditionalGET';
           enable 'Image::Scale';
           enable 'Static', path => qr{^/images/};
           $app;
       };

   A request to /images/foo_40x40.png will use images/foo.(png|jpg|gif) as
   original, scale it to 40x40 px size and convert to PNG format.

       ## example2.psgi

       my $thumber = builder {
           enable 'ConditionalGET';
           enable 'Image::Scale',
               width => 200, height => 100,
               flags => { fill => 'ff00ff' };
           Plack::App::File->new( root => 'images' );
       };

       builder {
           mount '/thumbs' => $thumber;
           mount '/' => $app;
       };

   A request to /thumbs/foo_x.png will use images/foo.(png|jpg|gif) as
   original, scale it small enough to fit 200x100 px size, fill extra
   borders (top/down or left/right, depending on the original image aspect
   ratio) with cyan background, and convert to PNG format. Also clipping is
   available, see "CONFIGURATION".

       ## example3.psgi

       my %imagesize = Config::General->new('imagesize.conf')->getall;

       builder {
           enable 'ConditionalGET';
           enable 'Image::Scale', path => sub {
               s{^(.+)_(.+)\.(jpg|png)$}{$1.$3} || return;
               ( my %entry = %{$imagesize{$2} || {}} ) || return;
               return delete @entry{'width','height'}, \%entry;
           };
           enable 'Static', path => qr{^/images/};
           $app;
       };

   A request to /images/foo_medium.png will use images/foo.(png|jpg|gif) as
   original. The size and flags are taken from the configuration file as
   parsed by Config::General.

       ## imagesize.conf

       <medium>
           width   200
           height  100
           crop
       </medium>
       <big>
           width   300
           height  100
           crop
       </big>
       <thumbred>
           width   50
           height  100
           fill    ff0000
       </thumbred>

   But you might want to use a simple config format, for example:

       $imagesize = {
           small  => [  10,  10 ],
           medium => [  50,  50 ],
           big    => [ 100, 100, 'crop']
       };

       # [...]
       enable 'Image::Scale', path => sub {
           s{^(.+)_(.+)e.(jpg|png)$}{$1.$3} || return;
           return @{ $imgsizes->{$2} || [] };
       };

DESCRIPTION
   Scale and convert images to the requested format on the fly. By default
   the size and other scaling parameters are extracted from the request
   URI. Scaling is done with Image::Scale.

   The original image is not modified or even accessed directly by this
   module. The converted image is not cached, but the request can be
   validated (If-Modified-Since) against original image without doing the
   image processing, or even reading the file content from the filesystem.
   This middleware should be used together a cache proxy, that caches the
   converted images for all clients, and implements content validation.

   The response headers (like Last-Modified or ETag) are from the original
   image, but body is replaced with a PSGI content filter to do the image
   processing. The original image is fetched from next middleware layer or
   application with a normal PSGI request. You can use
   Plack::Middleware::Static, or Catalyst::Plugin::Static::Simple for
   example.

   See "CONFIGURATION" for various size/format specifications that can be
   used in the request URI, and "ATTRIBUTES" for common configuration
   options that you can give as named parameters to the "enable".

ATTRIBUTES
 match
   Only matching URIs are processed with this module. The match is done
   against PATH_INFO. Non-matching requests are delegated to the next
   middleware layer or application.

   Must be a RegexpRef, or CodeRef, that may return 3 values (regexp
   captures or normal return values). The request path is passed to the
   CodeRef in $_, and can be rewritten during match. This is used to strip
   off the image parameters from the URI. Rewritten URI is used for
   fetching the original image. Empty array means no match.

   First and second captures are the desired width and height of the
   resulting image. Third capture is an optional flag string. See
   "CONFIGURATION".

 orig_ext
   ArrayRef of possible original image formats. See "fetch_orig".

 memory_limit
   Memory limit for the image scaling in bytes, as defined in Image::Scale.

 jpeg_quality
   JPEG quality, as defined in Image::Scale.

 width
   Use this to set and override image width.

 height
   Use this to set and override image height.

 flags
   Use this to set and override image processing flags.

METHODS
 fetch_orig
   Call parameters: PSGI request HashRef $env, Str $basename. Return value:
   PSGI response ArrayRef $res.

   The original image is fetched from the next layer or application. All
   possible extensions defined in "orig_ext" are tried in order, to search
   for the original image. All other responses except a straight 404 (as
   returned by Plack::Middleware::Static for example) are considered
   matches.

 body_scaler
   Call parameters: @args. Return value: CodeRef $cb.

   Create the content filter callback and return a CodeRef to it. The
   filter will buffer the data and call "image_scale" with parameters @args
   when EOF is received, and finally return the converted data.

 image_scale
   Call parameters: ScalarRef $buffer, String $ct, Int $width, Int $height,
   HashRef|Str $flags. Return value: $imagedata

   Read image from $buffer, scale it to $width x $height and return as
   content-type $ct. Optional $flags to specify image processing options
   like background fills or cropping. $flags can be a HashRef or

CONFIGURATION
   The default match pattern for URI is
   "*...**basename*_*width*x*height*-*flags*.*ext*".

   If URI doesn't match, the request is passed through. Any number of flags
   can be specified, separated with "-". Flags can be boolean (exists or
   doesn't exist), or have a numerical value. Flag name and value are
   separated with a zero-width word to number boundary. For example "z20"
   specifies flag "z" with value 20.

 basename
   Original image is requested from URI *basename*.*orig_ext*, where
   *orig_ext* is list of filename extensions. See "orig_ext".

 width
   Width of the output image. If not defined, it can be anything (to
   preserve the image aspect ratio).

 height
   Height of the output image. If not defined, it can be anything (to
   preserve the image aspect ratio).

 flags: fill
   Image aspect ratio is preserved by scaling the image to fit within the
   specified size. This means scaling to the smaller or the two possible
   sizes that preserve aspect ratio. Extra borders of background color are
   added to fill the requested image size exactly.

       /images/foo_400x200-fill.png

   If fill has a value, it specifies the background color to use. Undefined
   color with png output means transparent background.

 flags: crop
   Image aspect ratio is preserved by scaling and cropping from middle of
   the image. This means scaling to the bigger of the two possible sizes
   that preserve the aspect ratio, and then cropping to the exact size.

 flags: z
   Zoom the specified width or height N percent bigger. For example "z20"
   to zoom 20%. The zooming applies only to width and/or height defined in
   the URI, and does not change the crop size. Image is always cropped to
   the specified pixel width, height or both.

       /images/foo_40x-crop-z20.png

CAVEATS
   The cropping requires Imager. This is a run-time dependency, and
   fallback is not to crop the image to the desired size.

SEE ALSO
   Image::Scale

   Imager

   Plack::App::ImageMagick

AUTHOR
   Panu Ervamaa <[email protected]>

COPYRIGHT AND LICENSE
   This software is copyright (c) 2011 by Panu Ervamaa.

   This is free software; you can redistribute it and/or modify it under
   the same terms as the Perl 5 programming language system itself.