The ImageResizer plugin model encompases several aspects of the resizer pipeline. The most obvious are the ImageBuilder BuilderExtensions, which provide resizing and image manipulation functionality.
All extensions to the resizing process derive from the BuilderExtension base
class, which in turn derives from AbstractImageProcessor. The
AbtractImageProcessor class serves two purposes:
-
It defines 53 virtual methods which indvidual extensions can override as needed. 9 of these methods are for acquiring or beginning the overall process, and the remaining 44 are individual steps of the resizing process.
-
It provides a default implementation for each of these methods that pass the handling of the method on to any sub-extensions attached via a protected "list of
BuilderExtensions" member,exts. This is how theImageBuilderdelegates processing to the resizing plugins.
The descriptions below describe what an extension's implementation is expected to do, if the extension overrides the method.
Called before the source image is loaded. At present, no extensions override this method.
Provides the Stream for the given source. The RemoteReader plugin
implements this in order to support remote URL-based source images.
Called when ImageBuilder.DecodeStream() throws an exception. The FreeImage,
WIC, PsdReader and WebP extensions implement this method in order to support
their respective image types.
Why is the DecodeStream() override not
sufficient? Why does this appear to get handled twice?
Some parsers only tell you that they can't handle a format by throwing an exception. However, if we tell the plugins to not throw exceptions, we won't get any feedback about other categories of problems.
Thus, DecodeStream lets the first appropriate parser take a stab at the problem. The exception is later re-thrown if DecodeStreamFailed can't produce an alternate, working parser.
DecodeStreamFailed indicates that file parsers should not throw any exceptions - they just pass control to the next plugin parser in the line.
Called to decode an image Stream into a Bitmap. The FreeImage, WIC,
PsdReader and WebP extensions implement this method in order to support their
respective image types.
Called after DecodeStream() (and possibly DecodeStreamFailed()) has
converted the Stream into a Bitmap. Implemented by the AutoRotate
extension to flip/rotate the image based on the Exif "Orientation" tag on the
source image.
Called prior to acquiring the destination stream before the resizing process begins. At present, no extensions override this method.
Called (by ImageBuilder.Build()) to start the image processing pipeline.
If overriden, replaces the default ImageBuilder handing of the pipeline.
FreeImage, WIC, and WPF provide override implementations that take over if the
job settings include their value for the builder key.
Called after the destination Bitmap has been created (after
buildToBitmap()) if encoded output is needed. The ImageBuilder
implementation finds and uses an appropriate encoder based on the settings.
The AnimatedGifs extension overrides to provide support for multi-frame
(animated) GIFs.
Called to create the output Bitmap based on the source Bitmap and the
settings. Only overriden by ImageBuilder in order to call Process() and
begin the default resizing pipeline.
All 44 lower-level image resizing methods have an identical signature: they
take an ImageState parameter which can be modified as a part of the
implementation of any of the methods, and return a RequestedAction which
indicates whether the overall handling should be canceled or not.
Many of the methods come in both Xxx() and
Post_Xxx_() forms; a couple also have a Pre_Xxx_()
variation. These will be documented together, calling out only where
implementations provide specific and distinct behavior.
The resizing methods fall into two groups: layout, and render. The layout
methods calculate values on the ImageState's ResizeSettings object,
typically BoxPadding values. After the plugins set these values, the
ImageBuilder implementation turns these BoxPadding values into "rings"
on the ImageState's LayoutBuilder object.
Called at the very beginning of the resizing pipeline, to give extensions a chance to modify the querystring or settings. Not currently implemented by any extensions.
Called to perform any pre-layout work with the source Bitmap. The Faces
plugin implements PostPrepareSourceBitmap() to add a list of Face data to
the ImageState.Data dictionary.
Implemented by ImageBuilder to call the various layout-related methods in
sequence.
Unused.
Called to populate ImageState's copyRect rectangle and other layout data.
The SizeLimiting plugin implements PostLayoutImage() to set the scaling
factor when it exceeds the size limits specified in the configuration. The
SeamCarving plugin implements both methods in order to calculate carving data.
(The Post-version doesn't actually do anything.) The WhitespaceTrimmer plugin
implements both methods in order to find unused pixels around the outside of
the image and update the copyRect value. The WPF plugin implements
LayoutImage(), but only calls the base implementation.
After the plugins get a chance to handle LayoutImage(), ImageBuilder's
implementation calculates the size needed for any cropping and resizing
specified in the settings or querystring, then adds the "image" and
"imageArea" rings.
Called to add padding around the image. No plugins currently implement these methods.
After the plugins get a chance to handle LayoutPadding(), ImageBuilder's
implementation adds any padding requested as a "padding" ring to the
LayoutBuilder.
Called to add space for a border around the image. No plugins currently implement these methods.
After the plugins get a chance to handle LayoutBorder(), ImageBuilder's
implementation adds any padding requested as a "border" ring to the
LayoutBuilder.
Called to add space for effects to the image.
The DropShadow plugin implements LayoutEffects() to add a "shadow" ring to
the layout.
Called to add space for a margin around the image. No plugins currently implement these methods.
After the plugins get a chance to handle LayoutMargin(), ImageBuilder's
implementation adds any margin requested as a "margin" ring to the
LayoutBuilder.
Called to adjust the layout in order to accomodate any requested rotation. No plugins currently implement these methods.
After the plugins get a chance to handle LayoutRotate(), ImageBuilder's
implementation calls LayoutBuilder.Rotate() to rotate all of the rings.
Called to normalize the layout to (0,0). No plugins currently implement these methods.
After the plugins get a chance to handle LayoutNormalize(), ImageBuilder's
implementation calls LayoutBuilder.Normalize() to normalize the layout.
Called to round the layout to whole integers. No plugins currently implement these methods.
Called to indicate the end of the layout-related methods. Only implemented
by ImageBuilder to round the final size to a whole number of pixels and
ensure a minimum 1x1 size.
Called in between the layout and rendering passes.
The SizeLimiting plugin implements this to validate that the final destination size does not exceed the configured limits.
After the plugins get a chance to handle PrepareDestinationBitmap(),
ImageBuilder's implementation creates the destination Bitmap and
Graphics objects.
Called to start the rendering pass.
The RedEye plugin implements this to look for the locations of eyes in the source image. The Faces plugin implements this to detect faces in the source image.
After the plugins get a chance to handle Render(), ImageBuilder's
implementation calls the various render-related methods in sequence.
Called to render the background of the destination image.
The Watermark plugin implements PostRenderBackground() to render any
watermark intended to show over the background.
After the plugins get a chance to handle RenderBackground(),
ImageBuilder's implementation fills the background color in case the source
image includes any transparency.
Called to render any effects.
The DropShadow plugin implements RenderEffects() to draw the shadow to the
destination Graphics object.
ImageBuilder does not override these methods.
Called to render padding around the source image. No plugins currently implement these methods.
After the plugins get a chance to handle RenderPadding(),
ImageBuilder's implementation draws the padding polygon in the destination
Graphics object.
Called to create an ImageAttributes object for the destination image. No
plugins currently implement these methods.
After the plugins get a chance to handle CreateImageAttribues(),
ImageBuilder's implementation creates an ImageAttributes object if it
doesn't already exist.
Called to pre-process the source image before rendering. Any changes should
be saved to the ImageState's preRenderBitmap field.
The SimpleFilters plugin implements this to support rounded corners. The
AdvancedFilters plugin implements PreRenderImage() to support feathered
edges. The SeamCarving plugin implements this to perform seam-carving-based
resizing. The FreeImage plugin implements this to perform FreeImage resizing.
Called to render the source (or preRenderBitmap) image into the "image" ring
in the destination image.
The SpeedOrQuality plugin implements RenderImage() to choose specific
settings that impact the speed when drawing the destination image. If used,
returns RequestedAction.Cancel to prevent ImageBuilder's default handling.
The SimpleFilters plugin implements PostRenderImage() in order to fill the
"image" ring with an overlay color (presumably a not-completely-opaque color).
The AdvancedFilters plugin implements PostRenderImage() in order to provide
a variety of effects, including blur, sharpen, oil painting, noise reduction,
sepia, edge detection, etc. The RedEye plugin implements PostRenderImage()
in order to draw the red-eye reduction effects to the destination image.
(Seems to draw a rectangle?)
The Faces plugin implements PostRenderImage() in order to show the bounds
of the caclulated face rectangles if the "f.show" setting is "true".
After the plugins get a chance to handle RenderImage(), ImageBuilder's
implementation draws either the preRenderBitmap (if it exists) or source
Bitmap into the rectangle specified by the "image" ring in the
LayoutBuilder.
Called to render a border around the destination image. No plugins currently implement these methods.
After the plugins get a chance to handle RenderBorder(), ImageBuilder's
implementation draws the border polygon in the destination Graphics object.
Called to give plugins a last chance to make changes before any overlays are rendered. No plugins currently implement this method.
Called to render any overlays on the destination image.
The Watermark plugin implements this to render any watermark intended to show on top of the image.
ImageBuilder does not provide a default implementation of this method.
Called before the destination Graphics object is flushed into the
destination Bitmap.
The Trial plugin implements this to write "Unlicensed" across the image.
ImageBuilder does not provide a default implementation of this method.
Called to flush the destination Graphics object into the destination
Bitmap. No plugins currently implement these methods.
After the plugins get a chance to handle FlushChanges(), ImageBuilder's
implementation flushes the destination Graphics object and calls
Dispose() on it.
Called for any non-rendering changes to the destination Bitmap.
The CopyMetadataPlugin extension implements this to copy metadata PropertyItems
from the source bitmap to the destination bitmap.
After the plugins get a chance to handle ProcessFinalBitmap(),
ImageBuilder's implementation may perform a final rotation/flip.
Called at the very end of the processing pipeline. No plugins currently implement this method.
ImageBuilder does not provide a default implementation of this method.