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

VERSION
    version 0.003

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

DESCRIPTION
    Suppose that you have images/foo.jpg in your filesystem. With above
    setup you can make request to /images/foo_40x40.png, to receive it as
    scaled to 40x40 and converted to png format. Scaling is done with
    Image::Scale module.

    The converted and/or scaled version is not stored. This middleware
    implements a PSGI content filter to do the processing. The response
    headers (like Last-Modified or ETag) will be from the original image,
    but the image processing happens only if the body is actually used.

    This middleware doesn't access the filesystem at all. The original image
    is fetched from next middleware layer or application. The image requests
    should return a filehandle body for optimal results. You can use
    Plack::Middleware::Static, or "Catalyst::Plugin::Static::Simple" for
    example.

    This means that the response can be validated (with If-Modified-Since or
    If-None-Match) against original image, without doing the expensive image
    processing, or even reading the file content at all. This module should
    be used with a proxy cache that implements validation.

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

    With default configuration, the format of the URI is
    *basename*_*width*x*height*-*flags*.*ext*

    Only *basename*, "x" and *ext* are required. 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.

        /images/foo_40x20-fill0xff0000.png  ## red 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

ATTRIBUTES
  match_path
    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. The value must be a RegexpRef, that
    returns 3 captures. Default value is:

        qr<^(.+)_(.+)\.(png|jpg|jpeg)$>

    First capture is the path and basename of the requested image. The
    original image will be fetched by "fetch_orig" with this argument. See
    "call".

    Second capture is the size specification for the requested image. See
    "match_spec".

    Third capture is the extension for the desired output format. This
    extension is mapped with Plack::MIME to the Content-Type to be used in
    the HTTP response. The content type defined the output format used in
    image processing. Currently only jpeg and png format are supported. See
    "call".

  match_spec
    The size specification captured by "match_path" is matched against this.
    Only matching URIs are processed with this module. The value must be a
    RegexpRef. Default values is:

        qr<^(\d+)?x(\d+)?(?:-(.+))?$>

    First and second captures are the desired width and height of the
    resulting image. Both are optional, but note that the "x" between is
    required.

    Third capture is an optional flag. This value is parsed in the
    "image_scale" method during the conversion.

  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.

METHODS
  call
    Process the request. The original image is fetched from the backend if
    "match_path" and "match_spec" match as specified. Normally you should
    use Plack::Middleware::Static or similar backend, that returns a
    filehandle or otherwise delayed body. Content-Type of the response is
    set according the request.

    The body of the response is replaced with a streaming body that
    implements a content filter to do the actual resizing for the original
    body. This means that if response body gets discarded due to header
    validation (If-Modified-Since or If-None-Match for example), the body
    never needs to be processed.

    However, if the original image has been modified, for example the
    modification date has been changed, the streaming body gets passed to
    the HTTP server (or another middleware layer that needs to read it in),
    and the conversion happens.

  fetch_orig
    The original image is fetched from the next layer or application. The
    basename of the request URI, as matched by "match_path", and all
    possible extensions defined in "orig_ext" are used 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
    Create a content filter callback to do the conversion with specified
    arguments. The callback binds to a closure with a buffer and the
    image_scale arguments. The callback will buffer the response and call
    "image_scale" after an EOF.

  image_scale
    Do the actual scaling and cropping of the image. Arguments are width,
    height and flags, as parsed in "call".

    See "DESCRIPTION" for description of various sizes and flags.

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 <pnu@cpan.org>

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.

