Image processing API
Sitefinity CMS offers an extensible API for image processing.
Image transformations are performed with the IImageProcessor
interface and its default implementation ImageProcessor
.
IImageProcessor
This interface describes the available processing operations that you can use in Sitefinity CMS. It contains two methods - Resize
and ProcessImage
that you need to implement.
ImageProcessor
This classis the default implementation of the IImageProcessor
interface. It is registered in ObjectFactory (IoC) Container, and you can replace it with your implementation. It has three image processing methods, described below with their arguments.
Resize(Image sourceImage, FitToAreaArguments args)
Resizes the image by keeping the ratio between width and height and not overflowing the max limits specified. You use the FitToAreaArguments
class to define the Resize method argument for specifying the desired resize options.
Resize(Image sourceImage, FitToSideArguments args)
Resizes the specified source image by changing one of the sides (width or height) to the desired size and the other side proportionally keeping the ratio. You use the FitToSideArguments
class to define the Resize method argument for specifying the desired resize options.
Crop(Image sourceImage, CropArguments args)
It resizes the side with a smaller change keeping the ratio width/height, and cuts the other side from both sides (to preserve the center of the image) to satisfy the desired width and height. You use CropArguments
class to define the Crop method argument for specifying the desired cropping options.
Image Processing Methods Metadata
You should mark each processing method with attributes that provide additional information to be used by Sitefinity CMS successfully. Below are the different types responsible for the image processing metadata.
ImageProcessingMethod
This class encapsulates the meta-data about an image processing method. It holds information about method arguments and gives the ability to create a new instance of the argument object, parse and serialize, and validate from/to string the image processing parameters.
ImageProcessingProperty
This class defines the metadata for the particular property used as a parameter for the image processing method.
ImageProcessingMethodAttribute
This attribute marks the image processing methods that can be used in Sitefinity CMS. If you extend the ImageProcessor
class, you must mark your custom image processing methods with this attribute. All methods like this will be discovered and exposed automatically for thumbnail generation.
ImageProcessingPropertyAttribute
This attribute specifies the image processing argument for the transformation method. Each property that should be passed as an argument to the processing method should be marked with this attribute.
Image Processing Errors/Exceptions
When the image processing fails for some reason, you use the following types that store the information about the error.
ImageProcessingException
Represents the exception that is thrown when the image processing fails. It contains the processing error information.
ImageProcessingError
This enumeration contains the specific reason for the image processing error. There are two reasons specified:
MethodNotFound
- The generation method could not be found.
MethodGenerationError
- Internal image processing error. The generation method was executed and threw an error.
In the code snippet below you can see a demonstration of a class that extends the default ImageProcessor
and adds a new image processing method:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
using System; |
|
using System.Collections.Generic; |
|
using System.ComponentModel; |
|
using System.Drawing; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Threading.Tasks; |
|
using Telerik.Sitefinity.Modules.Libraries.ImageProcessing; |
|
|
|
namespace Telerik.Sitefinity.Documentation.CodeSnippets.DevGuide.HowTo |
|
{ |
|
/// <summary> |
|
/// Extends the default Sitefinity ImageProcessor with custom methods |
|
/// <example> |
|
/// Here is an example how to replace the default Sitefinity ImageProcessor in the Global.ascx: |
|
/// protected void Application_Start(object sender, EventArgs e) |
|
/// { |
|
/// Bootstrapper.Initialized += Bootstrapper_Initialized; |
|
/// } |
|
/// |
|
/// void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e) |
|
/// { |
|
/// if (e.CommandName == "Bootstrapped") |
|
/// { |
|
/// // Register the new Type of the ImageProcessor |
|
/// ObjectFactory.Container.RegisterType<IImageProcessor, CustomImageProcessor>(new ContainerControlledLifetimeManager()); |
|
/// } |
|
/// } |
|
/// </example> |
|
/// </summary> |
|
public class CustomImageProcessor : ImageProcessor |
|
{ |
|
/// <summary> |
|
/// Resizes the source image and adds a watermark. |
|
/// Calls the base Resize method to resize the image first and than draws a watermark with the specified text at the left top corner. |
|
/// </summary> |
|
/// <param name="sourceImage">The source image.</param> |
|
/// <param name="args">The args.</param> |
|
/// <returns></returns> |
|
[ImageProcessingMethod( |
|
Title = "Resize with Watermark", |
|
DescriptionText = "Generated image will be resized to desired area with watermark at the left top corner.")] |
|
public System.Drawing.Image ResizeWithWatermark(System.Drawing.Image sourceImage, FitToAreaWithWatermarkArguments args) |
|
{ |
|
// Use the the base Resize method that accepts FitToAreaArguments arguments to resize the origianl image |
|
System.Drawing.Image img = this.Resize(sourceImage, args); |
|
|
|
// Draw watermark at the left top corner |
|
Graphics gr = Graphics.FromImage(img); |
|
int emSize = (img.Width / args.WatermarkText.Length); |
|
System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat(StringFormatFlags.NoWrap); |
|
gr.DrawString( |
|
args.WatermarkText, |
|
new Font("Verdana", emSize, FontStyle.Bold), |
|
new SolidBrush(Color.AntiqueWhite), |
|
0, |
|
0, |
|
drawFormat); |
|
|
|
return img; |
|
} |
|
|
|
/// <summary> |
|
/// Overrides the base Resize method in order to hide it form the UI with Browsable(false) attribute. |
|
/// </summary> |
|
/// <param name="sourceImage"></param> |
|
/// <param name="args"></param> |
|
/// <returns></returns> |
|
[Browsable(false)] |
|
public override System.Drawing.Image Resize(System.Drawing.Image sourceImage, FitToAreaArguments args) |
|
{ |
|
return base.Resize(sourceImage, args); |
|
} |
|
|
|
/// <summary> |
|
/// Arguments descriptor class used by ResizeWithWatermark method. |
|
/// Describes the properties manageable by the Sitefinity UI. |
|
/// </summary> |
|
public class FitToAreaWithWatermarkArguments : FitToAreaArguments |
|
{ |
|
[ImageProcessingProperty(Title = "Watermark text", IsRequired = true)] |
|
public string WatermarkText { get; set; } |
|
} |
|
} |
|
} |
IImageProcessorExtender
You implement this interface to extend the image processing capabilities, built into Sitefinity CMS, and write custom logic for image processing. It contains the following members:
TryGetImageFromStream
method
You implement this method to get an image from an input stream. It accepts a stream and an image as an out parameter.
There is also optional options parameter, which is an object of type GetImageOptions
, containing two boolean properties: UseEmbeddedColorManagement
and ValidateImageData
. The properties correspond to the parameters of the FromStream
method.
For more information, see Image.FromStream method.
TrySaveImageToStream
method
You implement this method to save an image to a stream. It accepts the image, the stream, and the required MIME type. The optional SaveImageOptions
object consists of one property – IsThumbnail
. You use it, if you need some custom logic for thumbnails.
In this method, you can transcode the image into another format. If you do this, you must also assign the new MIME type, using the mimeType
parameter.
SupportedImageExtensions
property
This property holds the file extensions which the extender supports. For example, you can implement it as new string[] { ".webp" };
When this property is set, all of the values will appear as options in the Convert image format to…dropdown in the thumbnail settings dialog.
For more information, see WebP images
NOTE: If two or more classes implement the extender interface with the same target formats, Sitefinity CMS uses one of them without any error or message, but it is not specified which one. Therefore, you should not register different implementations for the same target formats.
In the code sample below, you can see how to implement the IImageProcessorExtender
interface and how to register your implementation in the Sitefinity IoC container:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
using System.Drawing; |
|
using System.IO; |
|
using Telerik.Sitefinity.Modules.Libraries.ImageProcessing; |
|
using Telerik.Sitefinity.Modules.Libraries.ImageProcessing.Extender; |
|
|
|
namespace Telerik.Sitefinity.Documentation.CodeSnippets.DevGuide.HowTo |
|
{ |
|
internal class CustomImageProcessorExtender : IImageProcessorExtender |
|
{ |
|
/// <summary> |
|
/// Tries to the get an image from an input stream. |
|
/// </summary> |
|
/// <param name="stream">The stream.</param> |
|
/// <param name="image">The image.</param> |
|
/// <param name="options">Additional options.</param> |
|
/// <returns>True if image is successfully returned; otherwise, false.</returns> |
|
public bool TryGetImageFromStream(Stream stream, out Image image, GetImageOptions options = null) |
|
{ |
|
// Your custom logic here |
|
image = null; |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Tries to the save an image to an input stream. |
|
/// </summary> |
|
/// <param name="image">The image.</param> |
|
/// <param name="stream">The stream.</param> |
|
/// <param name="mimeType">The image MIME type.</param> |
|
/// <param name="options">Additional options.</param> |
|
/// <returns>True if image is successfully saved to the stream; otherwise, false.</returns> |
|
public bool TrySaveImageToStream(Image image, Stream stream, ref string mimeType, SaveImageOptions options = null) |
|
{ |
|
// Your custom logic here |
|
// NOTE: If you need to change the mimeType, return the new one using the ref string mimeType parameter |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the supported target image formats. |
|
/// </summary> |
|
/// <value> |
|
/// A list of the supported target image file extensions. |
|
/// </value> |
|
public string[] SupportedImageExtensions |
|
{ |
|
get |
|
{ |
|
return new string[] { ".custom" }; |
|
} |
|
} |
|
} |
|
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
using System; |
|
using Telerik.Microsoft.Practices.Unity; |
|
using Telerik.Sitefinity.Abstractions; |
|
using Telerik.Sitefinity.Modules.Libraries.ImageProcessing.Extender; |
|
|
|
namespace Telerik.Sitefinity.Documentation.CodeSnippets.DevGuide.HowTo |
|
{ |
|
/// <summary> |
|
/// This class is responsible for registering the WebPImageProcessorExtender in the ObjectFactory on application start. |
|
/// </summary> |
|
public class Initializer |
|
{ |
|
/// <summary> |
|
/// Attach to ObjectFactory_RegisteringIoCTypes event. |
|
/// </summary> |
|
public static void Initialize() |
|
{ |
|
ObjectFactory.RegisteringIoCTypes += ObjectFactory_RegisteringIoCTypes; |
|
} |
|
|
|
private static void ObjectFactory_RegisteringIoCTypes(object sender, EventArgs e) |
|
{ |
|
ObjectFactory.Container.RegisterType( |
|
typeof(IImageProcessorExtender), |
|
typeof(CustomImageProcessorExtender), |
|
nameof(CustomImageProcessorExtender), |
|
lifetimeManager: new ContainerControlledLifetimeManager() |
|
); |
|
} |
|
} |
|
} |