Building the Sitecore PNG Optimizer Module

Marco Tana Marco Tana
November 25, 2013
Sitecore , Web Development

One of the Cubers, Jason, mentioned to me that it would be great if there was a way to easily optimize images within Sitecore. He was using a free online service but it was cumbersome. So, I set out to do a quick solution and this module is the result. You can check it out and download it from the Sitecore Marketplace. The Visual Studio 2010 solution is available for download at the end of this post.

This module optimizes PNG images by quantizing 32-bit images to 8-bit. Thus, reducing the file size significantly without a perceptible loss in quality.

This post is not about the actual algorithm of optimizing the image. You can read about that on CodePlex for the project nQuant. Instead, this post is about using Sitecore's less-used features that you may want to utilize in your own projects to create features that simplify content management.

I will be pointing out specific things in the code, so I recommend you download the solution as a reference. Please note that you'll see code that may have been commented out. This is from me trying to convert other image formats to PNG files by using raw bitmaps. It wasn't resulting in an optimized size so I've abandoned it for now until I can find some free library to convert image files to PNG.

Optimize Command

I used a Command to trigger the actual optimization. To do so, create a new class that inherits from the Sitecore.Shell.Framework.Commands.Command.

         public class Optimize : Command

Then, override the Execute method

                  public override void Execute(CommandContext context)

                  {

                           Assert.ArgumentNotNull(context, "context");

                           if ((int)context.Items.Length == 1)

                           {

                                    Item mainItem = context.Items[0];

                                     NameValueCollection nameValueCollection = new NameValueCollection();

                                    string[] item = new string[] { context.Parameters["id"], mainItem.ID.ToString() };

                                     nameValueCollection["id"] = StringUtil.GetString(item);

                                    nameValueCollection["language"] = mainItem.Language.ToString();

                                     nameValueCollection["version"] = mainItem.Version.ToString();

                                     string mode = context.Parameters["mode"];

                                     if (String.IsNullOrEmpty(mode))

                                             Context.ClientPage.Start(this, "Run", nameValueCollection);

                                    else if (mode == "one")

                                              Context.ClientPage.Start(this, "RunOne", nameValueCollection);

                                    return;

                           }

                           else

                           {

                                    return;

                           }

                  }

I populated a NameValueCollection that serves as my parameter. It essentially contains information about the item currently selected in the Content Editor. To be consistent on how Sitecore calls another public method within the page through Sheer, I call Context.ClientPage.Start to either run the optimization on one image or on all the images in the folder. (Hint: I could easily call another method from another object if I'd like to as long as that method follows the pipeline parameters.)

At this point, you would normally put most of the actual logic in the method you call from Execute. So, I'll leave it to you to go through the rest of the code that essentially determines the file type and optimize it if applicable using the nQuant optimizer.

UI Updates

In order to use the new Command, I have to actually bind that with a UI element. I have several options and I opted to use:

- Command template

- Context ribbon button

- Editor button

I could also create a context menu item which is when you right-click on an item but that requires further code.

There are several blog posts out there that detail how to bind the command to various Sitecore UI elements.

Future enhancements:

- auto conversion to PNG files using pipelines

- progress status bar

- context menu item for PNG images

Downloadable Code.

comments powered by Disqus

STRATEGIC PARTNERS