Defining image filters

Filters describe image operations that can be applied on images saved as page attachments. These operations may include actions such as crop, resize, watermark, etc. The filters then serve as building blocks when creating image variant definitions.

By default, no filters are included in the system. To add a new filter, you need to create a class in the Xperience project and implement the filter in code.

Creating a crop filter

The following example describes how to create a basic filter that crops images based on the provided width. The cropping is applied on the center of the image. The example uses the built-in ImageHelper library to perform the image operation.

Start by preparing a separate project for custom classes in your Xperience solution:

  1. Open your Xperience administration solution in Visual Studio (using the WebApp.sln file).
  2. Add a custom assembly (Class Library project) with class discovery enabled to the solution, or re-use an existing assembly.
  3. Reference the custom project from the CMSApp Xperience project.

You can now add your filters (and other classes related to responsive images) under the custom project.

  1. Create a new class under your custom project. For example, name the class CropImageFilter.cs.

  2. Add using statements for the following namespaces:

    using System;
    using System.IO;
    
    using CMS.Core;
    using CMS.Helpers;
    using CMS.ResponsiveImages;
    
  3. Make the class implement the IImageFilter interface (available in the CMS.ResponsiveImages namespace).

  4. Provide a property for setting the image width and set the property in the constructor of the filter class.

    /// <summary>
    /// Sample filter for cropping images.
    /// </summary>
    public class CropImageFilter : IImageFilter
    {
        private int Width { get; set; }
    
        public CropImageFilter(int width)
        {
            Width = width;
        }
        
        ...
    }
  5. Implement the ApplyFilter method required by the interface. The ApplyFilter method defines the actions applied to the image data.

    ApplyFilter return values

    Return values of the following types in the ApplyFilter method:

    • ImageContainer – when the filter is applied successfully, return a new ImageContainer object.
    • null – if the filter was not applied, return null to signify that the image data was not modified. Returning a null value means that the filter returns unmodified input image data.
    • ImageFilterException – if the application of the filter fails or the filter cannot be applied, throw an ImageFilterException exception with an appropriate error message.
    public ImageContainer ApplyFilter(ImageContainer container)
    {
        try
        {
            using (Stream imageStream = container.OpenReadStream())
            {
                ImageHelper imageHelper = new ImageHelper(BinaryData.GetByteArrayFromStream(imageStream));
    
                // Calculates the correct image height to maintain aspect ratio
                int[] dimensions = imageHelper.EnsureImageDimensions(Width, 0, 0);
                int croppedWidth = dimensions[0];
                int croppedHeight = dimensions[1];
    
                // Crops the center of the image to the specified size
                byte[] trimmedImage = imageHelper.GetTrimmedImageData(croppedWidth, croppedHeight, ImageHelper.ImageTrimAreaEnum.MiddleCenter);
    
                using (MemoryStream croppedImageData = new MemoryStream(trimmedImage))
                {
                    // Updates image metadata to reflect the new image size, maintains the MIME type and extension
                    ImageMetadata croppedImageMetadata = new ImageMetadata(croppedWidth, croppedHeight, container.Metadata.MimeType, container.Metadata.Extension);
    
                    // Returns the modified image data
                    return new ImageContainer(croppedImageData, croppedImageMetadata);
                }
            }
        }
        catch (ArgumentException ex)
        {
            throw new ImageFilterException("Failed to crop the image.", ex);
        }
    }    
  6. Save the new class and build your custom project.

With the crop filter prepared, you can now use it to create image variant definitions.