2017 © Pedro PelĂĄez
 

craft-plugin imager

Image transforms gone wild

image

aelvan/imager

Image transforms gone wild

  • Friday, July 13, 2018
  • by aelvan
  • Repository
  • 17 Watchers
  • 293 Stars
  • 4,661 Installations
  • PHP
  • 5 Dependents
  • 0 Suggesters
  • 47 Forks
  • 23 Open issues
  • 9 Versions
  • 152 % Grown

The README.md

Imager for Craft

Imager is a plugin for doing image transforms in Craft templates. It does all the things that the built-in image transform functionality do – but more. And it's faster. At least if you want it to be., (*1)

Whenever possible, Imager utilizes the image manipulation library Imagine which Craft comes with and uses for it's own transform functionality., (*2)

Support Open Source. Support Imager. Buy beer.

Imager is licensed under a MIT license, which means that it's completely free open source software, and you can use it for whatever you wish. Unfortunately, Imager doesn't make itself (it ought to, though!). A lot of beer has been consumed since version 1.0.0, and beers are expensive in Norway. Craft 3 is right around the corner, which will result in many late, beer-filled nights to get Imager updated to work with it., (*3)

If you're using Imager and want to support the development, you now have the chance! Head over to Beerpay, and donate a beer or two!, (*4)

Beerpay, (*5)

Features

  • A convenient syntax for doing a bunch of image transforms in one go.
  • Transforms are completely file-based, no database queries needed.
  • You can transform both images in your asset sources, local and cloud-based ones, and external images on any url.
  • Transformed images are placed in their own folder, outside of the asset source folder.
  • You can even upload and serve the transformed images from AWS.
  • Optimize your transformed images automatically with jpegoptim, jpegtran, mozjpeg, optipng, pngquant, gifsicle or TinyPNG and make Google happy!
  • You can use the amazing Imgix to offload handling of images from your server.
  • You can create interlaced/progressive images.
  • You can even transform animated gifs.
  • In addition to jpeg, gif and png, you can save images in webp format (if you have the necessary server requirements).
  • Crop position is relative (in percent) not confined to edges/center (but the built-in keywords still works).
    { width: 600, height: 600, mode: 'crop', position: '20% 65%' }
  • New cropZoom parameter for when you want to get a little closer.
    { width: 600, height: 600, mode: 'crop', position: '20% 65%', cropZoom: 1.5 }
  • New croponly mode. To crop, not resize.
    { width: 600, height: 600, mode: 'croponly', position: '20% 65%' }
  • New letterbox resize mode.
    { width: 600, height: 600, mode: 'letterbox', letterbox: { color: '#000', opacity: 0 } }
  • If you know the aspect ration you want, you don't have to calculate the extra height/width.
    { width: 800, ratio: 16/9 }
  • Basic image effects, including grayscale, negative, blur, sharpen, gamma and colorize.
    { effects: { sharpen: true, gamma: 1.4, colorize: '#ff9933' } }
  • Advanced effetcs, including color blend, tint, sepia, contrast, modulate, normalize, contrast stretch, unsharp mask, posterize and vignette (Imagick imagedriver only).
    { effects: { modulate: [100, 40, 100], colorBlend: ['rgb(255, 153, 51)', 0.5] } }
  • Your own choice of which resize filter to use. Speed vs. quality is up to you (Imagick imagedriver only).
  • Concerned about people copying your images? You can add a watermark to them with Imager.
    { watermark: { image: logo, width: 80, height: 80, position: { right: 30, bottom: 30 }, opacity: 0.8, blendMode: 'multiply' } }
  • Imager also lets you get color information, dominant color and palette, from your images.

For a quick look at what Imager can do, check out the demo site., (*6)

Contents


Installation

  1. Download the zip from this repository, unzip, and put the imager folder in your Craft plugin folder.
  2. Enable the plugin in Craft (Settings > Plugins)
  3. Create a new configuration file in the craft/config folder, named imager.php. Override any settings, the defaults are found in imager/config.php.
  4. Make sure you create the folder where Imager will store the images exists, and is writable. (your public folder)/imager is the default.

Configuration

All configuration settings can be found in the config.php file in the plugin folder (imager/config.php). You can override these settings by creating an imager.php file in your config folder, and overriding parameters as needed., (*7)

imagerSystemPath [string]

Default: $_SERVER['DOCUMENT_ROOT'] . '/imager/'
File system path to the folder where you want to store the transformed images., (*8)

imagerUrl [string]

Default: '/imager/'
Url to the transformed images. The imagerUrl will be prepended to the path and filename of the transformed image. Can be a relative url, or a full url. If you upload files to AWS, you'd set the imagerUrl to the AWS/CloudFront URL, like so:, (*9)

'imagerUrl' => 'http://s3-eu-west-1.amazonaws.com/imagertransforms/',

cacheEnabled [bool]

Default: true
Enables or disables caching of transformed images., (*10)

cacheDuration [int]

Default: 1209600
The cache duration of transformed images., (*11)

cacheDurationRemoteFiles [int]

Default: 1209600
When a remote file is downloaded, it will be cached locally for this duration., (*12)

jpegQuality [int]

Default: 80
Defines the JPEG compression level. Higher values equals better quality and bigger filesizes., (*13)

pngCompressionLevel [int]

Default: 2
Defines the PNG compression level. PNG compression is always lossless, so this setting doesn't have any effect on quality. It only affects speed and filesize. A lower value means faster compression, but bigger filesizes. A value of 0 means "no compression", which is the preferred setting if you're doing any post optimizations of png images (with Optipng or TinyPNG)., (*14)

webpQuality [int]

Default: 80
Defines the WEBP compression level. Higher values equals better quality and bigger filesizes., (*15)

webpImagickOptions [array]

Default: array()
Additional options you want to pass to Imagick when creating webp files. See the ImageMagick documentation for possible options (although, all are not supported by Imagick)., (*16)

Example on how to use it in config files:, (*17)

'webpImagickOptions' => array(
    'lossless' => 'true',
    'method' => '5',
),

Example on how to use it in your template code:, (*18)

{% set webpImage = craft.imager.transformImage(image, { width: 500, format: 'webp', webpImagickOptions: { lossless: 'true', method: '1' } }) %}

useCwebp [bool]

Default: false
If you don't have support for webp in the image driver you're using (GD or Imagick), you can set this to true to use the cwebp command line tool instead. cwebp needs to be installed on the server, but is available on most linux distros., (*19)

When using cwebp, Imager will first create a temprary, high quality, transformed image in the source format (jpeg, png or gif), and then convert this to webp. Since this results in two images being created for each transformed image, the operation is a bit slower (~15-20%) than using the image driver directly., (*20)

cwebpPath [string]

Default: /usr/bin/cwebp
Path to the cwebp binary., (*21)

cwebpOptions [string]

Default: ``
Options to pass o the cwebp binary (use cwebp -longhelp to see available options). Quality (-q) is automatically added based on webpQuality., (*22)

interlace [bool|string]

Default: false
Allowed values: false, true ('line'), 'none', 'line', 'plane', 'partition'
Defines the interlace method for creating progressive images. Imagick is required for the plane and partition methods. See demo here (throttle your connection)., (*23)

GD only supports one interlace mode, so it only makes sense to set a specific interlace mode if you use Imagick., (*24)

allowUpscale [bool]

Default: true
If set to false, images will never be upscaled., (*25)

resizeFilter [string]

Default: 'lanczos'
Allowed values: 'point', 'box', 'triangle', 'hermite', 'hanning', 'hamming', 'blackman', 'gaussian', 'quadratic', 'cubic', 'catrom', 'mitchell', 'lanczos', 'bessel', 'sinc'
Sets the resize filter. Imagick is required. By default Craft uses the lanczos filter for interpolation when resizing. It yields good visual result, but is one of the slower ones. There is a bunch of different filters available, and Imager let's you decide which one to use (lanczos is still the default)., (*26)

The difference in quality and encoding speed varies a lot, so you should choose what is most important for your project, speed or quality. The difference in speed will be more pronounced the bigger the original image is. The difference in quality will be more prononounced the bigger the resulting image is., (*27)

Here's the result of a speed test posted on php.net:, (*28)

FILTER_POINT took: 0.334532976151 seconds
FILTER_BOX took: 0.777871131897 seconds
FILTER_TRIANGLE took: 1.3695909977 seconds
FILTER_HERMITE took: 1.35866093636 seconds
FILTER_HANNING took: 4.88722896576 seconds
FILTER_HAMMING took: 4.88665103912 seconds
FILTER_BLACKMAN took: 4.89026689529 seconds
FILTER_GAUSSIAN took: 1.93553304672 seconds
FILTER_QUADRATIC took: 1.93322920799 seconds
FILTER_CUBIC took: 2.58396601677 seconds
FILTER_CATROM took: 2.58508896828 seconds
FILTER_MITCHELL took: 2.58368492126 seconds
FILTER_LANCZOS took: 3.74232912064 seconds
FILTER_BESSEL took: 4.03305602074 seconds
FILTER_SINC took: 4.90098690987 seconds

smartResizeEnabled [bool]

Default: false
When set to true, the new smartResize method that was added in Craft 2.5 will be used when Imagick is installed. This method is based on the research done by Dave Newton and yields smaller filesizes without any noticeable loss of quality., (*29)

Using smartResize may drastically decrease performance, especially when resizing pngs, and is therefore disabled by default., (*30)

removeMetadata [bool]

Default: false
Strips meta data from image, resulting in smaller images. Only available with Imagick., (*31)

bgColor [string]

Default: ''
If an image is converted from a format that supports transparency, to a format that doesn't, you can specify which background color (in hexadecimal) the resulting image should have., (*32)

position [string]

Default: '50% 50%'
The default focal point to be used when cropping an image. This can either be in percent, where the first value is along the horizontal axis, and the second value is along the vertical axis. Or one of the string values used in Craft's default image transform functionality (ie 'center-center', 'top-right', etc)., (*33)

letterbox [array]

Default: array('color'=>'#000', 'opacity'=>0)
Specifies the color and opacity to use for the background when using the letterbox resize method. Opacity is only applicable when saving the transformed file in png format. Animated gifs will always have transparent backgrounds., (*34)

hashFilename [bool|string]

Default: 'postfix'
Allowed values: true, false, 'postfix'
When doing an transform, Imager creates a filename based on the properties in the transform. By default ('postfix'), the generated part of the filenamed is hashed, and added as a postfix to the original filename. This makes the filename still relevant for SEO purposes, but still reasonably short., (*35)

If set to false, the filename will contain the generated string in clear text. This can result in really long filenames, but is great for debugging purposes., (*36)

If set to true, the whole filename is hashed. This will result in a short, but obscured, filename., (*37)

hashPath [bool]

Default: false
When enabled, the path of the transformed asset will be hashed., (*38)

hashRemoteUrl [bool|string]

Default: false
Allowed values: true, false, 'host'
When tranforming remote images, the hostname and remote path will be used as path inside your imager system path. If you want to shorten or obfuscate the remote url, you can set this to true or 'host'., (*39)

If you set this to true, the whole url will be hashed and used as the path., (*40)

If set to 'host', only the hostname will be hashed, while the remote path will be kept., (*41)

useRemoteUrlQueryString [bool]

Default: false
By default, query strings on external urls are not used when creating the filename of the transformed file, to improve caching. When enabled, any query string on the external url will be hashed and added as a part of the filename., (*42)

instanceReuseEnabled [bool]

Default: false
By default, both in Imager and Craft's built in transform functionality, the original image is loaded into memory for every transform. This ensures that the quality of the resulting transform is as good as possible., (*43)

If set to true, the original image is only loaded once, and every transform will continue working on the same image instance. This significantly increases performance and memory use, but will most likely decrease quality. See this demo page for an example of how it works., (*44)

noop [bool]

Default: false
Setting noop (no operation) to true makes Imager return the source image untouched. Useful if you don't want to do image transforms in some environments., (*45)

suppressExceptions [bool]

Default: false
By default Imager throws exceptions if file based operations fail, an external image can't be downloaded, etc. If suppressExceptions is set to true, Imager will instead log errors to the log file, and return null to the template., (*46)

convertToRGB [bool]

Default: false
Enable this setting to ensure that transformed images are saved as RGB., (*47)

fillTransforms [bool]

Default: false
Enable this setting to automatically fill a transform array with additional transforms based on fillAttribute and fillInterval., (*48)

fillAttribute [string]

Default: 'width'
Attribute to be used when filling in the transforms array. Can be any valid numeric attribute., (*49)

fillInterval [string]

Default: 200
Interval to be used when filling in the transforms array. This should always be a positive integer, Imager will automatically figure out if the transform has been ordered in an ascending or descending order., (*50)

jpegoptimEnabled [bool]

Default: false
Enable or disable image optimizations with jpegoptim., (*51)

jpegoptimPath [string]

Default: '/usr/bin/jpegoptim'
Sets the path to your jpegoptim executable., (*52)

jpegoptimOptionString [string]

Default: '-s'
Sets the options to use when running jpegoptim. By default it only strips out meta data., (*53)

jpegtranEnabled [bool]

Default: false
Enable or disable image optimizations with jpegtran., (*54)

jpegtranPath [string]

Default: '/usr/bin/jpegtran'
Sets the path to your jpegtran executable., (*55)

jpegtranOptionString [string]

Default: '-optimize -copy none'
Sets the options to use when running jpegtran. By default huffman tables are optimized, and no markers are copied from the source file., (*56)

mozjpegEnabled [bool]

Default: false
Enable or disable image optimizations with mozjpeg., (*57)

mozjpegPath [string]

Default: '/usr/bin/mozjpeg'
Sets the path to your mozjpeg executable., (*58)

mozjpegOptionString [string]

Default: '-optimize -copy none'
Sets the options to use when running mozjpeg. By default huffman tables are optimized, and no markers are copied from the source file., (*59)

optipngEnabled [bool]

Default: false
Enable or disable image optimizations with optipng., (*60)

optipngPath [string]

Default: '/usr/bin/optipng'
Sets the path to your optipng executable., (*61)

optipngOptionString [string]

Default: '-o5'
Sets the options to use when running optipng. By default the image file is optimized with level 5 optimizations., (*62)

pngquantEnabled [bool]

Default: false
Enable or disable image optimizations with pngquant., (*63)

pngquantPath [string]

Default: '/usr/bin/pngquant'
Sets the path to your pngquant executable., (*64)

pngquantOptionString [string]

Default: '--strip --skip-if-larger'
Sets the options to use when running pngquant. Output file (-o) and force overwrite (-f) is added by Imager and should not be set in pngquantOptionString., (*65)

gifsicleEnabled [bool]

Default: false
Enable or disable image optimizations with gifsicle., (*66)

gifsiclePath [string]

Default: '/usr/bin/gifsicle'
Sets the path to your gifsicle executable., (*67)

gifsicleOptionString [string]

Default: '--optimize=3 --colors 256'
Sets the options to use when running gifsicle. Batch mode (-b) is added by Imager and should not be set in gifsicleOptionString., (*68)

tinyPngEnabled [bool]

Default: false
Enable or disable image optimizations with TinyPNG. TinyPNG is a remote service that provides an API for optimizing images., (*69)

tinyPngApiKey [string]

Default: ''
The TinyPNG API key., (*70)

optimizeType [string]

Default: 'task'
Allowed values: 'task', 'runtime'
By default all post-transform optimizations are done as a Craft task that is run after the request has ended. This speeds up the initial transform request, but makes non-optimized images available for a short while until the task has been run. If set to 'runtime', all optimizations will be run immediately., (*71)

skipExecutableExistCheck [string]

Default: false
By default Imager will check if the executables for the post-transform optimizations exists. If you have basedir restrictions on, or for some other reason doesn't want to do this check, set this to true., (*72)

logOptimizations [bool]

Default: false
Logs information about optimizations., (*73)

awsEnabled [bool]

Default: false
Enables or disables uploading of transformed images to AWS., (*74)

*Please note; even if images are uploaded to AWS, they will also be stored in the Imager system path for caching and cache breaking purposes. *, (*75)

awsAccessKey [string]

Default: ''
AWS access key., (*76)

awsSecretAccessKey [string]

Default: ''
AWS secret key., (*77)

awsBucket [string]

Default: ''
AWS bucket name., (*78)

awsFolder [string]

Default: ''
Subfolder inside the AWS bucket where you want to put the transformed images., (*79)

awsCacheDuration [int]

Default: 1209600
Cache duration of files on AWS., (*80)

Please note; this has nothing to do with how long a transform is cached, it is only used to tell AWS what HTTP expiry headers to set on the file., (*81)

awsCacheDurationNonOptimized [int]

Default: 300
Cache duration of non-optimized files on AWS. This file will be overwritten with a file with cache duration as specified in awsCacheDuration, once the optimization task has been run., (*82)

awsRequestHeaders [array]

Default: array()
Additional request headers to send to AWS., (*83)

awsStorageType [string]

Default: 'standard'
Allowed values: 'standard', 'rrs'
Sets the AWS storage type., (*84)

gcsEnabled [bool]

Default: false
Enables or disables uploading of transformed images to Google Cloud Storage., (*85)

*Please note; even if images are uploaded to GCS, they will also be stored in the Imager system path for caching and cache breaking purposes. *, (*86)

gcsAccessKey [string]

Default: ''
Google Cloud Storage access key., (*87)

gcsSecretAccessKey [string]

Default: ''
Google Cloud Storage secret key., (*88)

gcsBucket [string]

Default: ''
Google Cloud Storage bucket name., (*89)

gcsFolder [string]

Default: ''
Subfolder inside the Google Cloud Storage bucket where you want to put the transformed images., (*90)

gcsCacheDuration [int]

Default: 1209600
Cache duration of files on Google Cloud Storage., (*91)

Please note; this has nothing to do with how long a transform is cached, it is only used to tell Google what HTTP expiry headers to set on the file., (*92)

gcsCacheDurationNonOptimized [int]

Default: 600
Cache duration of non-optimized files on Google Cloud Storage. This file will be overwritten with a file with cache duration as specified in gcsCacheDuration, once the optimization task has been run., (*93)

cloudfrontInvalidateEnabled [bool]

Default: false
Enabled or disables the sending of invalidation requests to Cloudfront when a transform is generated., (*94)

Please note: Imager has no way of knowing if the file currently on Cloudfront differs from the one being generated, so an invalidation request is sent every time a transform is created. The first 1000 invalidation requests per month is free, after that Amazon will start charging you., (*95)

cloudfrontDistributionId [string]

Default: ''
Set this to your Cloudfront distribution ID if cloudfront invalidation is enabled., (*96)

curlOptions [array]

Default: array()
Allows you to add cURL options to be used when downloading images from an external host., (*97)

Example:, (*98)

'curlOptions' => array(
  CURLOPT_SSL_VERIFYPEER => false,
  CURLOPT_SSLVERSION => 1,
  CURLOPT_SSL_CIPHER_LIST => 'TLSv1'
),

You can also override the default options, which currently is:, (*99)

$defaultOptions = array(
  CURLOPT_HEADER => 0,
  CURLOPT_FOLLOWLOCATION => 1,
  CURLOPT_TIMEOUT => 30
);   

Make sure you don't set CURLOPT_FILE, since it is set by Imager to be the output location for the downloaded file., (*100)

runTasksImmediatelyOnAjaxRequests [bool]

Default: true
Craft automatically runs any pending tasks on normal site requests, but not on ajax-request, leaving any optimization tasks that Imager has created in a queue that is run on the next CP request. By default Imager solves this by triggering runPendingTasks manually if the request was an ajax request, and a task was created (curl needed)., (*101)

If you for some reason want to disable this behavior, change this setting to false., (*102)

clearKey [string]

Default: ''
Key to use when clearing the transform or remote images cache with the controller actions. An empty string means clearing is disabled, (*103)

imgixEnabled [bool]

Default: false
Enables Imgix support. Read more about Imgix support below., (*104)

imgixDomains [array]

Default: null
An array of Imgix source domains., (*105)

imgixDomains [array]

Default: null
An array of Imgix source domains., (*106)

imgixUseHttps [bool]

Default: true
Indicates if generated Imgix URLs should be https or not., (*107)

imgixSignKey [string]

Default: ''
If you've protected your source with secure URLs, you must provide the sign key/token. An empty string indicates that the source is not secure., (*108)

imgixSourceIsWebProxy [bool]

Default: false
Indicates if your Imgix source is a web proxy or not., (*109)

imgixUseCloudSourcePath [bool]

Default: true
If enabled, Imager will prepend the Craft source path to the asset path, before passing it to the Imgix URL builder. This makes it possible to have one Imgix source pulling images from many Craft sources when they are on the same S3 bucket, but in different subfolder., (*110)

imgixShardStrategy [string]

Default: 'cycle'
Allowed values: 'cycle', 'crc'
Determines the sharding strategy if more than one source is used., (*111)

imgixGetExternalImageDimensions [bool]

Default: true
Imager does its best at determining the dimensions of the transformed images. If the supplied asset is on Craft source, it's easy because Craft records the original dimensions of the image in the database. But if the image is external, it's not that easy. Imager will try to determine the size based on the transform parameters, and if both width and height, or ratio is provided, it'll usually be able to. But if you only transform by one attribute, it may not be possible. In these cases Imager will by default download the source image and check the dimensions to calculate the missing bits., (*112)

By disabling this setting, you're telling Imager to never download external images, and to just give up on trying to figure out the dimensions. If you supplied only width to the transform, height will then be set to 0. If you don't need to use height in your code, that's totally fine, and you've managed to squeeze out a bit more performance., (*113)

imgixDefaultParams [array]

Default: null
You can use this setting to set default parameters that you want passed to all your Imgix transforms. Example:, (*114)

'imgixDefaultParams' => array('auto'=>'compress,format', 'q'=>80)

Usage

If you've ever done an image transform in a Craft template, this probably looks familiar:, (*115)

{% set image = craft.assets().limit(1).first() %}
<img src="{{ image.getUrl({ width: 1000 }) }}">

The same code using Imager would look like this:, (*116)

{% set image = craft.assets().limit(1).first() %}
{% set transformedImage = craft.imager.transformImage(image, { width: 1000 }) %}
<img src="{{ transformedImage.url }}">

So far, it's more code than the Craft way. But, let's say you need to resize the image to six different widths, because you're using and srcset to serve up responsive images (in a modern and futureproof way). And you want the crop position on all the images to be in the bottom-right corner, an aspect ratio of 16:9, and while the large images should have a high jpeg quality, the smaller ones should be more optimized., (*117)

Here's how the code would look with Imager:, (*118)

{% set transformedImages = craft.imager.transformImage(image, [
    { width: 1200 }, 
    { width: 1000 }, 
    { width: 800 }, 
    { width: 600, jpegQuality: 65 }, 
    { width: 400, jpegQuality: 65 }
    ], { ratio: 16/9, position: 'bottom-right', jpegQuality: 80 }) %}

Imager 1.5.0 also introduced a convenient fillTransforms config setting which makes the above code even simpler:, (*119)

{% set transformedImages = craft.imager.transformImage(image, [
    { width: 1200 }, 
    { width: 600, jpegQuality: 65 }, 
    { width: 400, jpegQuality: 65 }
    ], { ratio: 16/9, position: 'bottom-right', jpegQuality: 80 }, 
    { fillTransforms: true }) %}

See the fillTransforms, fillAttribute and fillInterval settings for more information., (*120)

The plugin also includes some additional methods that helps you streamline the creation of responsive images. With the above transformed images, you can output the appropriate srcset like this, with a base64-encoded placeholder in the src attribute:, (*121)

<img src="{{ craft.imager.base64Pixel(16, 9) }}" sizes="100vw" srcset="{{ craft.imager.srcset(transformedImages) }}">

Additional information about the template variables can be found in the "Template variables"-section below., (*122)

Relative image paths

In the above examples, an AssetFileModel is passed to the transformImage method. You can also pass an Imager_ImageModel, path or an url to an image that has already been transformed by Imager. This can be useful for increasing performance, or simplifying your template code. In the below example, an image is first resized and have effects applied to it, before being resized to the final sizes:, (*123)

{% set newBaseImage = craft.imager.transformImage(selectedImage, { 
    width: 1000, 
    height: 1000, 
    effects: { modulate: [110, 100, 100], colorBlend: ['#ffcc33', 0.3], gamma: 1.2 },
    jpegQuality: 95 }) %}

{% set transformedImages = craft.imager.transformImage(newBaseImage, [
    { width: 600, height: 600 },
    { width: 500, height: 500 },
    { width: 400, height: 400 }
    ]) %}

Transforming external images

You can also transform remote images by passing an url for an image to transformImage:, (*124)

{% set externalImage = 'http://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/pia19808-main_tight_crop-monday.jpg' %}

{% set transformedImages = craft.imager.transformImage(externalImage, [
    { width: 600, height: 600 },
    { width: 500, height: 500 },
    { width: 400, height: 400 }
    ]) %}

When transforming external images, the remote image is downloaded to your craft/storage/runtime folder, and cached for the duration selected in the cacheDurationRemoteFiles config parameter., (*125)


Template variables

craft.imager.transformImage(image, transform [, transformDefaults=null, configOverrides=null])

The main transform method. Returns either an Imager_ImageModel (see documentation below) if just one transform object were passed, or an array of Imager_ImageModel if an array were passed. Takes the following parameters:, (*126)

image: Image to be transformed. This can be either an AssetFileModel, a string to a previously transformed Imager image, or a string to an external image.
transform: An object, or an array of objects, containing the transform parameters to be used. See the "Usage"- and "Transform parameters"-sections for more information.
transformDefaults: An object containing any default transform settings that should be applied to each transform. If transform properties given here are specified in an individual transform, the property value of the individual transform will be used.
configOverrides: An object containing any overrides to the default config settings that should be used for this transform. See the "Configuration"-section for information on which settings that can be overridden., (*127)

craft.imager.base64Pixel([width=1, height=1, color='transparent'])

Outputs a base64 encoded SVG image., (*128)

width: Width of the placeholder. Defaults to '1'.
height: Height of the placeholder. Defaults to '1'. color: Color of the placeholder. Defaults to 'transparent'., (*129)

craft.imager.srcset(images [, descriptor='w'])

Outputs a srcset string from an array of transformed images., (*130)

images: An array of Imager_ImageModel objects, or anything else that support the interface.
descriptior: A string indicating which size descriptor should be used in the srcset. 'w', 'h' and 'w+h' is supported at the moment. Please note that 'h' isn't standards-compliant, but is useful for instance when using Lazysizes and their bgset plugin., (*131)

craft.imager.serverSupportsWebp()

Returns true or false depending on if the server has support for webp or not. This could either indicate built in support for webp in the current image driver, GD or Imagick, or the presence of the cwebp binary if this has been enabled., (*132)

craft.imager.clientSupportsForWebp()

Returns true or false depending on if the client has support for webp or not. This is deducted from the Accept header that the client sends., (*133)

If you use template caching, or any kind of front side cache (Varnish, Fastly, etc), make sure you create different caches based on if the client has support for webp or not. For template caching, adding a string to the key based on this variable, is one way to solve it. Example:, (*134)

{% cache using key "my-content" ~ (craft.imager.clientSupportsForWebp ? "-with-webp") %}  
...
{% endcache %}

craft.imager.getDominantColor(image [, quality=10, colorValue='hex'])

Gets the dominant color of an image. Uses Color Thief for all the magic., (*135)

image: Image to get dominant color from. Can be any of the types that transformImage can handle.
quality: Calculation accuracy of the dominant color. 1 is the highest quality, 10 is the default. Be aware that there is a trade-off between quality and speed/memory consumption!
colorValue: Indicates which data format the returned color is in. Allowed values are 'hex' (default) and 'rgb'. If rgb is selected, the value is an array with red as index 0, green as index 1 and blue as index 2., (*136)

craft.imager.getColorPalette(image [, $colorCount=8, quality=10, colorValue='hex'])

Gets the color palette of an image. Uses Color Thief for all the magic., (*137)

image: Image to get palette from. Can be any of the types that transformImage can handle.
colorCount: Number of colors to include in palette.
quality: Calculation accuracy of the dominant color. 1 is the highest quality, 10 is the default. Be aware that there is a trade-off between quality and speed/memory consumption!
colorValue: Indicates which data format the returned color is in. Allowed values are 'hex' (default) and 'rgb'. If rgb is selected, the value is an array with red as index 0, green as index 1 and blue as index 2., (*138)

craft.imager.hex2rgb(color)

Converts a hexadecimal color value to rgb. Input value must be a string. Output value is an array with red as index 0, green as index 1 and blue as index 2., (*139)

craft.imager.rgb2hex(color)

Converts a rgb color value to hexadecimal. Input value must be an array with red as index 0, green as index 1 and blue as index 2. Output value is a string., (*140)

craft.imager.isAnimated(image)

Returns true or false depending on if the supplied image is animated or not (only gif support at the moment)., (*141)

craft.imager.imgixEnabled()

Returns true or false depending on if Imgix is enabled., (*142)


Transform parameters

The following parameters are available in the transform object., (*143)

format [string]

Default: null
Allowed values: null, 'jpg', 'png', 'gif', 'webp'
Format of the created image. If unset (default) it will be the same format as the source image., (*144)

width [int]

Width of the image, in pixels., (*145)

height [int]

Height of the image, in pixels., (*146)

ratio [int|float]

An aspect ratio (width/height) that is used to calculate the missing size, if width or height is not provided., (*147)

Example:, (*148)

{# Results in an image that is in 16:9 format, 800x450px #}
{% set sixteenbynineImage = craft.imager.transformImage(image, { width: 800, ratio: 16/9 }) %}

mode [string]

Default: 'crop'
Allowed values: 'crop', 'fit', 'stretch', 'croponly', 'letterbox'
The mode that should be used when resizing images., (*149)

'crop': Crops the image to the given size, scaling the image to fill as much as possible of the size. 'fit': Scales the image to fit within the given size while maintaining the aspect ratio of the original image.
'stretch': Scales the image to the given size, stretching it if the aspect ratio is different from the original.
'croponly': Crops the image to the given size without any resizing.
'letterbox': Scales the image to fit within the given size, the same way as 'fit'. It then expands the image to the given size, adding a specified color to either the top/bottom or left/right of the image. The color (and opacity if the image format supports it) can be controlled with the letterbox parameter., (*150)

Example:, (*151)

{% set letterboxImage = craft.imager.transformImage(image, { width: 600, height: 600, mode: 'letterbox', letterbox: { color: '#000000', opacity: 1 } }) %}

cropZoom [float]

Default: 1
By default when cropping, the image will be resized to the smallest size needed to make the image fit the given crop size. By increasing the cropZoom value, the image will be resized to a bigger size before cropping., (*152)

Example: If the original image is 1600x900px, and you resize it to 300x300px with mode 'crop' and a cropZoom value of 1.5, the image will; 1) be resized to 800x450px and 2) a crop of 300x300px will be made (the position depending on the position given)., (*153)

frames [string]

Let's you extract only certain frames from an animated gif. The parameter takes a string in the format 'startFrame/endFrame@frameInterval'. End frame and frame interval is optional. Examples:, (*154)

// Get only first frame of animated gif
{% set transformedImage = craft.imager.transformImage(animatedGif, { width: 300, frames: '0' }) %}

// Get the first ten frames of animated gif
{% set transformedImage = craft.imager.transformImage(animatedGif, { width: 300, frames: '0-9' }) %}

// Get every fifth frame between frames 0 and 40
{% set transformedImage = craft.imager.transformImage(animatedGif, { width: 300, frames: '0-40@5' }) %}

// Get every fifth frame between the first and the last frame
{% set transformedImage = craft.imager.transformImage(animatedGif, { width: 300, frames: '0-*@5' }) %}

watermark [object]

Default: null
Adds a watermark to your transformed image. Imager expects an object with the following properties:, (*155)

image: The image that is to be used as watermark. Just as the image parameter in the craft.imager.transformImage method, this can be an AssetFileModel, a string to a previously transformed Imager image, or a string to an external image.
width: Width of the watermark, in pixels.
height: Height of the watermark, in pixels.
position: An object which specifies left or right, top or bottom, offsets for the watermark.
opacity: Opacity of the watermark. Only available in Imagick.
blendMode: The blendmode to be used for the watermark. Possible values are 'blend', 'darken', 'lighten', 'modulate', 'multiply', 'overlay', and 'screen'. Only available in Imagick., (*156)

Example:, (*157)

{% set logo = craft.assets({ id: 11 }).first() %}
{% set watermarkedImage = craft.imager.transformImage(image, { 
    width: 600, 
    watermark: { image: logo, width: 80, height: 80, position: { right: 30, bottom: 30 }, opacity: 0.8, blendMode: 'multiply' }
}) %}

See this demo for examples on how the watermark feature works., (*158)

effects [object]

Default: null Adds image adjustments to the transformed image. If multiple adjustments are added, they will be applied in the order they appear in the object. All effects are documented in the Effects section below., (*159)

Example:, (*160)

{% set transformedImage = craft.imager.transformImage(image, { 
    width: 600, 
    effects: { grayscale: true, gamma: 1.5 }
}) %}

preEffects [object]

Default: null
As with the effects, this adds image adjustments to the transformed image, but do so before the image has been resized or otherwise modified. For some adjustments, this will yield a better end result, but usually the trade-off is performance., (*161)

In addition, the following configuration settings can be overridden for each transform:, (*162)

  • jpegQuality
  • pngCompressionLevel
  • cacheEnabled
  • cacheDuration
  • interlace
  • allowUpscale
  • resizeFilter
  • smartResizeEnabled
  • removeMetadata
  • bgColor
  • position
  • letterbox
  • hashFilename
  • hashRemoteUrl

imgixParams [object]

Default: null
Additional parameters that are passed to the Imgix URL API if Imgix is enabled., (*163)


Effects

The following basic adjustments (see demo) works both in GD and Imagick, and are limited to what is available in Imagine:, (*164)

grayscale [bool]

Converts the image to grayscale if set to true., (*165)

negative [bool]

Converts the image to negative if set to true., (*166)

blur [int|float|bool]

Blurs the image. If you're using GD as image driver, blur can only be toggled on/off, either with true/false or 1/0., (*167)

sharpen [bool]

Sharpens the image to grayscale if set to true., (*168)

gamma [int|float]

Adjusts the image gamma., (*169)

colorize [string]

Colorizes the image. Expects a hexadecimal color value., (*170)

The following advanced image adjustments (see demo) are only available when using Imagick:, (*171)

colorBlend [array]

Blends the image with the color and opacity specified. Example:, (*172)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { colorBlend: ['rgb(255, 153, 51)', 0.5] } }) %}

tint [array]

Tints the image using Imagick's tintImage method. Example:, (*173)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { colorBlend: ['rgb(255, 153, 51)', 'rgb(212, 212, 212)'] } }) %}

sepia [int]

Converts the image to sepia tones., (*174)

contrast [bool|int|float]

Increases or decreases the contrast of the image. A value greater than 0 increases contrast while a negative value decreases it., (*175)

modulate [array]

Let's you adjust brightness, saturation and hue with Imagick's modulateImage method. Example (drops saturation by 80%):, (*176)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { modulate: [100, 20, 100] } }) %}

normalize [bool]

Enhances the contrast of the image by normalizing the colorspace. Uses Imagick's normalizeImage method., (*177)

contrastStretch [array]

Enhances the contrast of a color image by adjusting the pixels color to span the entire range of colors available. Uses Imagick's colorStretch method. Example:, (*178)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { contrastStretch: [500*500*0.10, 500*500*0.90] } }) %}

posterize [array]

Reduces image colors by applying the posterize effect. Uses Imagick's posterizeImage method. Example:, (*179)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { posterize: [136, 'no'] } }) %}

The second parameter refers to which dither method is used. Allowed values are:, (*180)

'no': No dithering.
'riemersma': Riemersma dithering.
'floydsteinberg': Floyd–Steinberg dithering., (*181)

unsharpmask [array]

Applies an unsharp mask with Imagick's unsharpMaskImage method. Example:, (*182)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { unsharpMask: [0, 0.5, 1, 0.05] } }) %}

clut [array]

Applies a clut (color lookup table) effect to the image, using Imagick's clutImage method. You probably want to use it together with modulate to get a real duotone effect. Example:, (*183)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { modulate: [100, 0, 100], clut: 'gradient:darkblue-aqua' } }) %}

The parameter is the image definition string sent to Imagick's newPseudoImage method. You can use any valid color values. Example with rgba colors:, (*184)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { modulate: [100, 0, 100], clut: 'gradient:rgba(255,0,0,0.8)-rgba(255,255,0,1)' } }) %}

Please note that the alpha value doesn't actually make the color transparent, it just has the effect of moving the gradient's center point towards the color with the least transparency., (*185)

quantize [array|int]

Reduces the number of colors in an image, using Imagick's quantizeImage method. This can help to reduce filesize, especially for gif images. Example:, (*186)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { quantize: 32 } }) %}

The parameter can be an int, indicating the number of colors to reduce to, or an array that corresponds to the functions $numberColors (int), $treedepth (int) and $dither (bool) parameters. Example with default treeDepth, but dithering:, (*187)

{% set transformedImage = craft.imager.transformImage(image, { width: 500, effects: { quantize: [32, 0, true] } }) %}

levels [array]

Adjusts an image's levels, using Imagick's levelImage method. The effect takes an array corresponding to black point, gamma, white point and channel (optional). Example:, (*188)

{% set transformedImage = craft.imager.transformImage(img, { width: 500, effects: { levels: [50, 1, 200, 'blue'] }}) %}

You can use negative values for black point and white point to do a level stretch/offset:, (*189)

{% set transformedImage = craft.imager.transformImage(img, { width: 500, effects: { levels: [-100, 1, 255, 'blue'] }}) %}

Possible values for channel is 'red', 'green', and 'blue'. Omit it all together to adjust levels for all channels., (*190)

vignette [array]

The vignette effect is not yet finalized., (*191)


Imager_ImageModel

The model returned by the craft.imager.transformImage method., (*192)

Public attributes

url: URL to the image.
path: System path to the image file.
extension: File extension.
mimeType: File mime type.
width: Width of the image.
height: Height of the image.
size: Size of the image in bytes., (*193)

Public methods

getUrl() [string]
URL to the image., (*194)

getPath() [string]
System path to the image file., (*195)

getExtension() [string]
File extension., (*196)

getMimeType() [string]
File mime type., (*197)

getWidth() [string]
Width of the image., (*198)

getHeight() [string]
Height of the image., (*199)

getSize($unit='b', $precision='2') [float]
Size of the image. Example:, (*200)

{{ image.getSize() }} B 
{{ image.getSize('k') }} KB 
{{ image.getSize('m', 10) }} MB 
{{ image.getSize('g', 10) }} GB

getDataUri() [string]
Returns a data uri with the image base64 encoded as a string., (*201)

getBase64Encoded() [string]
Returns a string of the base64 encoded image data., (*202)


Imager_ImgixModel

The model returned by the craft.imager.transformImage method if Imgix is enabled. This model has the same signature as the Imager_ImageModel for companilities sake, but does return empty strings for some of its attributes that are not applicable, or not possible to determine., (*203)

Public attributes

url: URL to the image.
path: Returns an empty string.
extension: Returns an empty string.
mimeType: Returns an empty string.
width: Width of the image.
height: Height of the image.
size: Returns an empty string., (*204)

Public methods

getUrl() [string]
URL to the image., (*205)

getPath() [string]
Returns an empty string., (*206)

getExtension() [string]
Returns an empty string., (*207)

getMimeType() [string]
Returns an empty string., (*208)

getWidth() [string]
Width of the image., (*209)

getHeight() [string]
Height of the image., (*210)

getSize($unit='b', $precision='2') [float]
Returns an empty string., (*211)

getDataUri() [string]
Returns an empty string., (*212)

getBase64Encoded() [string]
Returns an empty string., (*213)


Controller actions

Imager has two controller actions, one for clearing the transformed images cache, and one for clearing remote images. You can use this if you wish to clear the cache as part of your deploy process, or similar., (*214)

Both actions needs a parameter key, which is set with the clearKey config setting., (*215)

Clearing transform images cache:, (*216)

http://yourdomain.com/actions/imager/clearTransforms?key=<your_key>

Clearing external images cache:, (*217)

http://yourdomain.com/actions/imager/clearRemoteImages?key=<your_key>

Imgix support

Imager 1.6.0 added support for using Imgix with Imager. When enabled, transforms will no longer be done on your server, instead Imager will create an URL based on Imgix' URL API and Imgix will do the job of transforming your images. This will eliminate all issues with execution timeouts and memory limits that people are running into when doing massive amounts of image transforms., (*218)

For more info about how to set up Imgix support and what it can do, please read the launch article., (*219)


Caching and cache breaking

When caching is enabled (cacheEnabled configuration setting set to true) transformed images are cached for the duration of the cacheDuration configuration setting. If an image file is replaced, the existing transforms will be deleted. If a file is moved, the transforms will also be regenerated, since Imager will not find the transforms in the new location., (*220)

It is possible to manually remove the generated transforms by going to Settings > Clear Caches, selecting "Imager image transform cache" and clicking "Clear!". You can also select the images you want to clear in the Assets element list, and choose "Clear Imager transforms" from the element action dropdown menu., (*221)

When transforming a remote image, the image will be downloaded and cached for the duration of the cacheDurationRemoteFiles configuration setting. You can manually remove the cached remote images by going to Settings > Clear Caches, selecting "Imager remote images cache" and clicking "Clear!"., (*222)


Price, license and support

The plugin is released under the MIT license, meaning you can do what ever you want with it as long as you don't blame me. It's free, which means there is absolutely no support included, but you might get it anyway. Just post an issue here on github if you have one, and I'll see what I can do. It doesn't hurt to donate a beer at Beerpay either. Just saying. :), (*223)


Changelog

See releases.json., (*224)

The Versions