Generating image metadata and SVG thumbnails with Episerver DXC Azure Blob storage

Episerver has an ImageData base class that natively supports images. But we needed to extend it to provide metadata fields and display SVG thumbnails. Here's how we did it...

Darren Stahlhut

By Darren Stahlhut 5 minute read

In this blog post, we explain how we extended Episerver to meet some functional requirements and improve the CMS editors' experience of working with images.

So what did we do?

  • Added metadata fields for media and images
    • Description – used as image alt text
    • File Extension – used to show icons for media files
    • File Size – used to display the size in Kb, Mb etc of media files
    • Width and Height – used to build responsive image galleries
  • Added support for vector based images
    •  Displaying SVG thumbnails

Extending the ImageData base class

In Episerver, ImageData is a base class that inherits from EPiServer.Core.MediaData and provides a Content Type to handle any type of image.

When a CMS editor uploads an image in Episerver DXC, the image is stored in Azure Blob storage and Episerver generates a thumbnail to help the CMS editor select images from the Media tab.

Adding Metadata fields

We needed to add metadata to images. To do this we created a new class that inherits from ImageData called ImageFile.

[ContentType(GUID = "0A89E464-56D4-449F-AEA8-2BF774AB8730")]
    [MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png")]
    public class ImageFile : ImageData, IContentMediaMetaData
    {
        /// <summary>
        /// Description of the Image
        /// </summary>
        public virtual string Description { get; set; }

        /// <summary>
        /// File extension of the Image file
        /// </summary>
        [Editable(false)]
        public virtual string FileExtension { get; set; }

        /// <summary>
        /// File size of the Image file
        /// </summary>
        [Editable(false)]
        public virtual int FileSize { get; set; }

        /// <summary>
        /// Width of the Image
        /// </summary>
        [Editable(false)]
        public virtual int Width { get; set; }

        /// <summary>
        /// Height of the Image
        /// </summary>
        [Editable(false)]
        public virtual int Height { get; set; }
    }

You might have noticed we also implemented an interface called IContentMediaMetaData. We wanted to add some metadata fields to all our media, not just images, but you could choose to omit this interface.

    public interface IContentMediaMetaData : IContentMedia
    {
        string FileExtension { get; set; }

        int FileSize { get; set; }
    }

Once this was done, we just had to upload an image in the CMS and our metadata fields were available.

Episerver Image Metadata

Generating metadata

We're always trying to reduce unnecessary CMS editor data entry. The only field we really need a human to manually populate is the Description field. 

So we added some helper methods to automatically populate the File Size, File Extension, Width and Height fields and added an InitializationModule with CreatingContent and SavingContent event handlers to set these field values.

    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class ContentMediaInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            var eventRegistry =
            ServiceLocator.Current.GetInstance<IContentEvents>();

            eventRegistry.CreatingContent += OnCreatingContent;
            eventRegistry.SavingContent += OnSavingContent;

        }

        public void Preload(string[] parameters)
        {
        }

        private void OnSavingContent(object sender, ContentEventArgs e)
        {
            if (e.Content is IContentMediaMetaData)
            {
                MediaHelpers.SetFileMetaData(e.Content as IContentMediaMetaData);
            }
        }

        private static void OnCreatingContent(object sender, ContentEventArgs e)
        {
            if (e.Content is IContentMediaMetaData)
            {
                MediaHelpers.SetFileMetaData(e.Content as IContentMediaMetaData);
            }
        }

        public void Uninitialize(InitializationEngine context)
        {
            var eventRegistry =
                ServiceLocator.Current.GetInstance<IContentEvents>();

            eventRegistry.CreatingContent -= OnCreatingContent;
            eventRegistry.SavingContent -= OnSavingContent;

        }
    }

Now when we upload or even edit an image with the built-in Image Editor, our helper methods will automatically populate the metadata fields. With this automated, we decided to make these fields read only by adding the Attribute [Editable(false)] to the Properties in our ImageFile class.

Episerver Image Generated Metadata

Adding support for Vector based images

If you noticed the MediaDescriptor ExtensionString list on our ImageFile class, you maybe thinking you could just add svg to the list like this... We tried this too!

[MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png,svg")]

While this did allow SVGs to be handled by the ImageFile class, it did present some issues with both thumbnail generation and metadata generation.

  • Thumbnail generation
    Regardless of whether it's a Vector or Raster based image, Episerver will attempt to generate a thumbnail when you upload it. However, in the case of SVGs (vectors), the concept of a thumbnail is not relevant because they are already a scalable object. Episerver generates an empty thumbnail, but we really want it to use the original SVG.

    The following image shows JPG thumbnails compared to SVG thumbnails.
Epsierver Generated Thumbnails
  • Metadata generation
    Similarly, as they are infinitely scalable, Width and Height are not relevant for an SVG. 

To solve these issues,  we added another new Class called VectorImageFile to specifically support vector images, but don't worry, it inherits from the ImageFile class we created previously.

    [ContentType(DisplayName = "VectorImageFile", GUID = "c0b70fd0-0d5b-4c53-83fe-e32ea8faa2d5", Description = "")]
    [MediaDescriptor(ExtensionString = "svg")]
    public class VectorImageFile : ImageFile, IContentMediaMetaData
    {
        /// <summary>
        /// Gets the generated thumbnail for this media.
        /// </summary>
        public override Blob Thumbnail
        {
            get { return BinaryData; }
        }
    }

Take note of the Public Override Blob Thumbnail. As the name suggests, this overrides the base class and returns the BinaryData of the actual SVG rather than a generated thumbnail.

The only thing left to do is to prevent our helper from attempting to set the image Width and Height. This was as simple as adding a condition to our helper to check if the object type is VectorImageFile

if (media is VectorImageFile) return;

So how does all this look in the CMS?

Inside Episerver when we upload images in the Media tab of the Assets pane we now see the following...

JPGs in the Media tab

  • The Description metadata field is available for editing
  • The remaining Metadata fields have be automatically populated
Episerver JPG Metadata Thumbnails

SVGs in the Media tab

  • The Thumbnails are displayed based on the binary data of the actual SVG
  • The Description metadata field is available for editing
  • The Width and Height fields have not been automatically populated
  • The remaining Metadata fields have be automatically populated 
Episerver SVG Metadata Thumbails

Hiding or removing Width and Height fields from VectorImages

Now that the Width and Height fields are not longer being automatically populated, we wanted to hide them, so we were able to simply override them in the Class definition and add a [ScaffoldColumn(false)] or  [Ignore]  attribute to the Properties. 

        [ScaffoldColumn(false)]
        public override int Width { get; set; }

        [ScaffoldColumn(false)]
        public override int Height { get; set; }
Episerver SVG Metadata no dimensions

Wrapping it up

In this blog post we have covered how we have improved the CMS editors' experience when working with raster and vector images in Episerver, and how we extended the ImageData base class include and generate data for Metadata fields. We also added a VectorImage class to allow the CMS to display SVG thumbnails.

Need an agency with Episerver expertise?

Contact Us
Blog

7 reasons why content calendars fail

By Tami Strategy 4 minute read

A content calendar can be an extremely powerful tool – if well set-up and maintained. Content Strategist Tami Iseli outlines some of the factors that can reduce the chances of abandonment.

Blog

How do you handle online forms with Kentico Cloud?

By Andy Strategy, Development, Kentico Cloud 4 minute read

There are a few questions we regularly field when introducing the concept of a headless CMS to people. After explaining the terms 'headless' and 'microservices', we invariably hit the topic of online forms - a staple feature of any traditional web CMS, but curiously absent from the feature list of your modern-day headless CMS.