Magnolia 5.3 reached end of life on June 30, 2017. This branch is no longer supported, see End-of-life policy.
The Imaging module simplifies working with images. You don't need to resize and crop each image for teasers and openers by hand. Instead, upload a single source image into the system and let the imaging engine generate variations on-the-fly. Administrators create the rules that determine the sizes of derivatives. Editors save time as they can select an image from the DAM or upload one, and it will be automatically adapted to match the rule.
The Imaging module is bundled with Magnolia and typically already installed. You can download it from our Nexus repository.
Imaging is a Community Edition module. It is typically already installed. Launch the Configuration app and go to /modules/imaging
to check.
Magnolia's built-in digital asset management (DAM) stores images as reusable resources. The stored version of an image is generally the largest and highest quality image available. The source is typically too large to be used on the site as-is so related proxy copies are created. A proxy copy is a lower resolution representation of the source image that can be used in teasers and features to reduce bandwidth requirements.
The Imaging module creates a proxy copy from the source image on-the-fly when the image is requested for the first time and retains the proxy copy for subsequent use. A teaser image is a typical example.It is a small version of the image in the teased article. The Imaging module creates the teaser image according to a pre-configured variation rule. An editor who adds a teaser on a page does not need to manipulate the image. The system knows which image is used on the teased page and creates a resized variation of it automatically.
The Imaging module:
The module also provides a framework to delegate image processing to an external non-Java system, providing a different caching mechanism.
The diagram shows the elements of the Imaging module and how they interrelate (credit: Richard Unger).
ImageGenerator
interface is the entry point for generating images.ImageOperationChain
implements ImageGenerator
and executes an operation chain.ParameterProviderFactory
interface are responsible for instantiating parameter providers for a given environment.ImageStreamer
interface are responsible for pushing the generated image, with the given generator and parameters, to an output stream.Configuration for the Imaging module is at /modules/imaging/config
.
ImagingServlet
is registered in the Magnolia servlet filter chain at /server/filters/servlets/ImagingServlet
. The servlet is responsible for generating images.
Node name | Value |
---|---|
server | |
filters | |
context | |
... | |
servlets | |
ClasspathSpoolServlet | |
... | |
ImagingServlet | |
mappings | |
-.imaging-- | |
pattern | /.imaging/* |
parameters | |
class | info.magnolia.cms.filters.ServletDispatchingFilter |
comment | Imaging Servlet |
enabled | true |
servletClass | info.magnolia.imaging.ImagingServlet |
servletName | ImagingServlet |
Image generator is a component that generates variants from a source image based on configuration. Generators are configured at /modules/imaging/config/generators
:
ImageOperationChain
is the most commonly used generator class. It executes an operation chain and is used by the large
, portrait
and thumbnail
generators.STKImageGenerator
handles image generation for the Standard Templating Kit.
Node name | Value |
---|---|
modules | |
imaging | |
config | |
generators | |
large | |
outputFormat | |
operations | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
portrait | |
thumbnail | |
stk | |
outputFormat | |
parameterProviderFactory | |
class | info.magnolia.module.templatingkit.imaging.generation.STKImageGenerator |
Format refers to the file format the imaging system accepts as an input source and the format the generator produces, such as JPEG or PNG. Supported formats (input and output) are bmp
, gif
, jpeg
, jpg
, png
and wbmp
. You can verify the formats available on your system by installing the Imaging Tools module from Nexus. The Tools > Image I/O plugins app displays a list of supported file extensions.
.Output format is configured differently depending on the image generator:
ImageOperationChain
reads the formatName
property for the desired output format. Set the value of this property to a lowercase file extension such as jpg
or png
. The module will save the generated images in this format even if the source format is different.STKImageGenerator
always generates images in the same format as the source image. So if you upload a jpg, this generator will produce a jpg. This is an STK specific implementation.
Node name | Value |
---|---|
generators | |
large | |
outputFormat | |
formatName | jpg |
quality | 80 |
operations | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
If you need a custom implementation for converting images from one format to another, create your own image generator:
STKImageGenerator
class.getOutputFormat()
method.class
node in configuration to your class' name.JPEG is a lossy image format. It compresses image data by discarding (losing) some of it with the aim of minimizing the amount of data needed to store and transfer the image. The degree of compression can be adjusted, allowing a tradeoff between bandwidth consumption and image quality.
Set the quality
property to the desired quality level. Magnolia uses a percentage-based scale from 0 to 100. Default is 80%. The higher the quality, the less compression is applied during JPEG creation. Compression is always applied in JPG. Some of the original image information is always lost in compression and cannot be restored, possibly affecting image quality. Quality 100 simply means that the system uses the least possible amount of compression, favoring good quality. 0 means maximum compression. Many Magnolia imaging properties such as quality
map to the corresponding methods in javax.imageio.ImageWriteParam.
Image at 80% quality.
Image at 10% quality.
In a progressive JPEG, data is compressed in multiple passes of progressively higher detail. A progressive JPEG has the same quality as a baseline JPEG but displays the image while it is being downloaded, at the cost of a slight increase in file size.
Progressive processing is suited for large images and slow connections. Visitors can see a reasonable preview after receiving only a portion of the image data. If your site uses large images extensively in an image gallery or slideshow, set the progressive
property to true
and see if it improves the user experience. Default value is false
which yields baseline (non-progressive) JPEGs.
Imaging uses and delegates to javax.imageio.ImageWriteParam
. This class supports a compressionType
property that lets you choose which compression type to use.
The imaging engine stores generated images in the imaging
workspace.
The path where generated images are stored dependens on the CachingStrategy . The default path is:
/<generatorName> /<workspaceName> /<path of node or property (nodedata)>
For STK, the path is:
/<themeName> /<variationName> /<workspaceName> /<path of node or property (nodedata)>
For example:
/pop /promo /dam /demo-project /img /bk /Opener /coral-light /jcr:content /generated-image
When the image is rendered on a page, the URL to the generated image is:
/<hostName, contextPath> /.imaging (which is the Imaging servlet default path) /<generatorName> /<path to the cached image>
Here is example image with the URL highlighted. Compare the URL to the path above.
If you are not working on a standard installation, replace localhost:8080/magnoliaAuthor
with <your domain>/<context path>
in all URLs in the rest of this document.
Magnolia caches image resources to improve performance. Any dynamic images generated by the Imaging module are also cached at two levels: in the imaging
workspace and in the actual cache like any other page or document. This means that once the system generates an image, you keep getting the same cached image on subsequent requests.
During testing, you can disable caching of generated images completely. Go to Configuration > /server/filters/servlets/ImagingServlet/parameters
, create a new property storeGeneratedImages
, and set its value to false
.
Node name | Value |
---|---|
server |
|
filters |
|
servlets |
|
ImagingServlet |
|
parameters |
|
storeGeneratedImages | false |
Note that there is still a small delay between any change you make to image configuration and a new image being available. Magnolia's observation mechanism intentionally waits couple of seconds before reading a changed configuration.
The most common image operation is resizing, particularly downsampling. In this process a larger source image is reduced to produce a smaller image for use in teasers and promos. You can also upsample images but be aware that the pixels become increasingly visible, making the image appear "soft".
Cropping removes unwanted areas from an image. The optional crop
property in a variation determines whether cropping should happen. Here's the zoom
variation configuration used on the demo sites. You can find the configuration at STK > Themes/pop/imaging/variations/zoom
.
Node name | Value |
---|---|
pop | |
cssFiles | |
jsFiles | |
imaging | |
zoom | |
crop | false |
height | 600 |
width | 800 |
promo |
The default value is true
which means images will be cropped to accommodate the target dimensions. Cropping is done symmetrically from both sides of the image, focusing on what is in the middle. (dog photo credit: Xavi Talleda)
If you set crop
to false
the engine will not crop the image. The image is resized to the smaller of the two target dimensions while constraining the dimensions. For example, if the original image is 1024 x 800 and you specify a target size 480 x 320 and set crop
to false
, the engine will create an image that is 410 x 320. The image has the same aspect ratio (1.28:1) as the original. Height is the smaller dimension (going from 800 to 320 is a 60% reduction whereas going from 1024 to 480 is a 53% reduction) so height is targeted.
The engine calculates the new width as follows:
target long edge = source long edge / source short edge * target short edge = 1024 / 800 * 320 = 409.6 ≈ 410 (rounded to nearest full pixel)
Aspect ratio refers to the width of the image compared to its height. You should know common aspect ratios in digital photography and video since your source images probably adhere to them.
You may also need to target images for specific device screen resolutions. Here are some common resolutions. Note that a mobile devices is commonly held in portrait orientation, so the iPhone resolution 480x320 is actually more often 320x480.
Width | Height | Device |
---|---|---|
1920 | 1080 | 1080p, 1080i, HD DVD, Blu-ray |
1280 | 720 | 720p, HD DVD, Blu-ray |
1024 | 768 | XGA, Apple iPad |
1024 | 600 | Used in many netbooks |
960 | 640 | Apple iPhone 4, 4th generation iPod Touch |
854 | 480 | Motorola Droid |
800 | 600 | SVGA, Amazon Kindle |
800 | 480 | WGA or WVGA, HTC Touch, Google Nexus One |
640 | 320 | Nokia Series 90 smartphones |
480 | 320 | HVGA, Apple iPhone 3G, iPod Touch |
Ad elements adhere to standard sizes on the Web. Google AdSense provides a nice overview of the different ad elements and their sizes in case you need to generate images for this purpose.
The Imaging module can resize and crop images, overlay text and apply image filters. These are called image operations. Operations are configured in Configuration >/modules/imaging/config/generators
, or in the case of STK, in a theme using variations.
An image operation chain consists of one or more operations. A simple chain can just add some fixed text while a more complex chain can load an image from a remote source, apply filters, add multiple text fields and style them differently. At minimum, an image operation chain must have this structure:
<operation chain name>
: Arbitrary. Name of the operation chain.operations
: Individual operations go under this node. They are executed from top to bottom.<first operation name>
: Arbitrary. Name of first operation. <second operation name>
: Arbitrary. Name of second operation. outputFormat
: Defines the format for generated images.formatName
: File format extension: jpg, png, gif, tif.quality
: JPEG quality as a percentage. Default is 80.parameterProviderFactory
: class
: Fully qualified parameter provider factory class name. See Parameter providers below for alternatives.class
: ImageOperationChain
registers the configuration as an image operation chain.
Node name | Value |
---|---|
modules | |
imaging | |
config | |
generators | |
myOperationChain | |
operations | |
myOperation1 | |
myOperation2 | |
myOperation3 | |
outputFormat | |
formatName | jpg |
quality | 80 |
parameterProviderFactory | |
class | info.magnolia.imaging.parameters.ContentParameterProviderFactory |
class | info.magnolia.imaging.operations.ImageOperationChain |
Parameters are instructions passed to an operation, such as where to load a source image or what text to lay over it. Registering a ParameterProviderFactory allows you to pass parameters from different sources:
ContentParameterProviderFactory
determines the workspace and image node to use based on the request URI. It assumes that the first path element is the name of the image generator or the operation chain, the second is the name of the workspace where the source image node is, and that the rest is the path to the node.BinaryNodeParameterProviderFactory
extracts workspace and UUID from the path. Everything after the uuid is ignored so that one can pass for example, a properly named filename to the imageSTKParameterProviderFactory
is an STK specific parameter implementation for the STK module.Generic syntax for the URL of the generated image is:
http://localhost:8080/magnoliaAuthor/.imaging/<chain name>/<workspace>/<path to image>
All examples below are variations for this URL and an example URL is provided for each. The /<workspace>/<path to image> part is dependent on the parameter provider. As seen in Imaging workspace above, STK decodes this part slightly differently.
Remember that generated images are cached. If you keep getting the same image back even if you modify the examples below, disable caching of copies so you can be sure to get a new image, then refresh the URL.
The simplest image operation is to create an empty canvas. This operation does not use an existing image as a starting point but creates a completely new one.
To create an empty canvas:
emptyCanvas
. The name is arbitrary, use any you like.class
and set its value to info.magnolia.imaging.operations.load.Blank
.height
and set its value. Default is 200.width
and set its value. Default is 200.outputFormat/formatName
to png
or jpg
. PNG supports transparency so the engine creates a transparent PNG by default. Default JPG background color is black.Set parameterProviderFactory/class
property to info.magnolia.imaging.parameters.ContentParameterProviderFactory.
Node name | Value |
---|---|
generators | |
myOperationChain | |
operations | |
emptyCanvas | |
class | info.magnolia.imaging.operations.load.Blank |
height | 160 |
width | 240 |
outputFormat | |
formatName | png |
parameterProviderFactory | |
class | info.magnolia.imaging.parameters.ContentParameterProviderFactory |
class | info.magnolia.imaging.operations.ImageOperationChain |
To view the PNG image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/website/demo-project/about.png. Since a transparent PNG is hard to see, paint over the page with your mouse to see the image outline.
To view the JPG image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/website/demo-project/about.jpg
The website page, in this case /demo-project/about
, must exist in the website
workspace because this is how the ContentParameterProviderFactory
works.
Use the URLImageLoader
class to load an image from an external URL. Identify the URL with the url
property. This example uses http://farm5.static.flickr.com/4052/4638137415_1f776215e8_m.jpg.
Load the image from URL:
loadFromURL
.class
and set its value to info.magnolia.imaging.operations.load.URLImageLoader
.Add property node url
and set its value to the URL.
Node name | Value |
---|---|
generators | |
myOperationChain | |
operations | |
loadFromURL | |
class | info.magnolia.imaging.operations.load.URLImageLoader |
url | http://farm5.static.flickr.com/4052/4638137415_1f776215e8_m.jpg |
outputFormat | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
To view the image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/website/demo-project/about.jpg
The website page, in this case /demo-project/about
, must exist in the website
workspace because this is how the ContentParameterProviderFactory
works.
Use the ClasspathImageLoader
class to load an image from the classpath. Pace the source image in the classpath of the webapp. By default, a Magnolia webapp's classpath contains JARs in /WEB-INF/lib
and any classes and resources in /WEB-INF/classes
. Magnolia will find any image you place in those locations.
Load image from classpath:
/<CATALINA_HOME>/webapps/<contextPath>/WEB-INF/
classes
.loadFromClasspath
.class
and set its value to info.magnolia.imaging.operations.load.ClasspathImageLoader
.Add property node src
and set its value to the name of the image files preceded by a forward slash.
Node name | Value |
---|---|
generators | |
myOperationChain | |
operations | |
loadFromClasspath | |
class | info.magnolia.imaging.operations.load.ClasspathImageLoader |
src | /bird-240.jpg |
outputFormat | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
To view the image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/website/demo-project/about.jpg
The website page, in this case /demo-project/about
, must exist in the website
workspace because this is how the ContentParameterProviderFactory
works.
BoundedResize
is an operation that resizes an existing image without cropping. It resizes the image to either maxHeight
or maxWidth
while honoring the aspect ratio. In this example we first load a 240 x 160 and resize it to maximum width of 150. Width is the longer dimension so it is reduced to 150.
Properties:
class
: info.magnolia.imaging.operations.cropresize.BoundedResize
maxHeight
: Target image maximum height.maxWidth
: Target image maximum width.expand
: Optional. Set to false
to prevent upsampling. If reaching the target dimension would require upsampling a small source image, don't do anything. Upsampling often leads to fuzzy images. When set to false
the BoundedResize operation leaves the image as is. Default value is true
which allows upsampling. Example: Resize without cropping:
myFolder
in the Assets app.myImage.jpg
.loadFromDAM
operation used in Loading an image from DAM workspace above in the operations
node. This is the first operation that provides an image to manipulate.boundedResize
.class
and set its value to info.magnolia.imaging.operations.cropresize.BoundedResize
.maxWidth
and set its value to 150
.Node name | Value |
---|---|
generators | |
myOperationChain | |
operations | |
loadFromDAM | |
class | info.magnolia.imaging.operations.load.FromContent |
propertyName | jcr:content |
boundedResize | |
class | info.magnolia.imaging.operations.cropresize.BoundedResize |
maxHeight | 120 |
maxWidth | 150 |
outputFormat | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
To view the image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/dam/myFolder/myImage.jpg
AutoCropAndResize
is an operation that resizes an existing image to targetWidth
and targetHeight
, cropping it if needed. Instead of the original aspect ratio it honors the target aspect ratio. It crops the image so that the largest possible portion of is kept. It keeps the center part of the image and cuts out from the sides.
If you define only targetWidth
or only targetHeight
, no cropping is done. Cropping happens only when you define both targetWidth
and targetHeight
and their ratio does not match the source ratio.
In this example a 240 x 160 image is auto-cropped and resized to 150 x 150 (a square). Since the original was not a square the resulting image is cropped to match the target ratio. The sides of the image are cut off.
Note how the subject of the image, the dog, is also cut. This is typically not an issue when using mood images that don't have specific focal point which should always be visible. It may be an issue for portraits and product images.
The same rules apply to upscaling: defining target dimensions that are larger than the original creates an enlarged copy. If the ratio of the target dimensions does not match that of the original, cropping happens.
To auto-crop and resize:
myFolder
in the Assets app.myImage.jpg
.loadFromDAM
operation used in Loading an image from DAM workspace above in the operations
node. This is the first operation which provides an image to manipulate.autoCropAndResize
.class
and set its value to info.magnolia.imaging.operations.cropresize.AutoCropAndResize
.targetWidth
and set its value to 150
.Add property node targetHeight
and set its value to 150
.
Node name | Value |
---|---|
generators | |
myOperationChain | |
operations | |
loadFromDAM | |
class | info.magnolia.imaging.operations.load.FromContent |
propertyName | jcr:content |
autoCropAndResize | |
class | info.magnolia.imaging.operations.cropresize.AutoCropAndResize |
targetHeight | 150 |
targetWidth | 150 |
outputFormat | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
To view the image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/dam/myFolder/myImage.jpg
Filters are standard Java BufferedImageOps that apply special effects to an image. The Imaging module ships with JH Labs Filters which can do:
The BufferedImageOpDelegate
class delegates the rendering to an image filter. Some filters have parameters that you can set in a correspondingly named property. See filter documentation on JH Labs website for filter class names and parameters. The source code for filters is included in the filters
JAR that ships with the Imaging module.
In this example we apply three consecutive filters on the street light image used in Loading an image from URL above:
To apply a filter:
class
and set its value to info.magnolia.imaging.operations.BufferedImageOpDelegate
.delegate
. This is the filter operation you delegate to. Add the following properties:class
and set value to fully-qualified filter class name, for example com.jhlabs.image.CausticFilter
. All JH Labs filters start with com.jhlabs.image
. Find the class name in JH Labs documentation.Optional: If the filter supports parameters, add a property named after the parameter and set its value.
Node name | Value |
---|---|
generators | |
myOperationChain | |
operations | |
emptyCanvas | |
causticsFilter | |
delegate | |
amount | 0.9 |
class | com.jhlabs.image.CausticsFilter |
class | info.magnolia.imaging.operations.BufferedImageOpDelegate |
outputFormat | |
parameterProviderFactory | |
class | info.magnolia.imaging.operations.ImageOperationChain |
To view the image, go to http://localhost:8080/magnoliaAuthor/.imaging/myOperationChain/dam/myFolder/myImage.png or another URL depending on how you load the base image.
A variation is an STK specific configuration that defines the size of the target image and tells the imaging engine whether cropping is allowed. Variations are configured in a theme rather than under the Imaging module config
node. This way you can configure image look and feel aspects in the same place as CSS.
For more information on STK variations see Themes > Image variations.
Credits: