Imageprocessor: Cannot change image format in OnPostProcessing

Created on 3 Apr 2017  路  7Comments  路  Source: JimBobSquarePants/ImageProcessor

Prerequisites

  • [X] I have written a descriptive issue title
  • [X] I have verified that I am running the latest version of ImageProcessor
  • [X] I have verified if the problem exist in both DEBUG and RELEASE mode
  • [X] I have searched open and closed issues to ensure it has not already been reported

Description

I'm trying to write a hook that will respond with WebP images if the browser sends Accepts: image/webp (or similar). The simplest way to do this looks to be to add an OnPostProcessing handler.

However, the mimetype is retrieved before OnPostProcessing is called, and not updated afterwards. This causes the cache to respond with the wrong format depending on which format was first requested.

Steps to Reproduce

Add handler
```C#
ImageProcessingModule.OnPostProcessing += (object sender, PostProcessingEventArgs e) =>
{
if (!AcceptsWebP(new HttpContextWrapper(e.Context))) return;

    using (var imageFactory = new ImageFactory(false))
    {
        using (var memoryStream = new MemoryStream())
        {
            imageFactory
                .Load(e.ImageStream)
                .Format(new WebPFormat {Quality = 80})
                .Save(memoryStream);

            e.ImageStream.Dispose();

            e.ImageStream = new MemoryStream(memoryStream.ToArray());
            e.ImageExtension = "webp";
        }           
    }
}

```

Set interceptAllRequests="true"
Request (jpeg or png) image Chrome first (accepts WebP)
Then request image with Firefox (doesn't accept WebP) - it is served WebP as it is stored in cache.

System Configuration

  • ImageProcessor version: 2.5.3.0
  • ImageProcessor.Web version (if applicable): 4.8.3.0
  • ImageProcessor.Plugins.WebP: 1.0.5.0
  • ImageProcessor.Web.Plugins.PostProcessor: 1.1.2.0

  • Environment (Operating system, version and so on): Windows 10, but also Windows 2012R2, Windows 2008R2

  • .NET Framework version: 4.5.2
  • Additional information: interceptAllRequests="true"
question

Most helpful comment

As @JimBobSquarePants says, with wide support for the picture element (and polyfills for those without), it makes more sense to use that.

I think I got a PoC working, but it was abandoned as WebP wasn't widely supported at the time, and the client wasn't entirely happy with the results - automatic conversion from (optimized) JPEG to WebP isn't the way to go.

In the end, we saved bytes by serving correctly sized images (the full sized images were being served for 250x250 thumbnails). If you go this route, you're best implement a UI that lets users choose the focus point for the image - that way if resizing/cropping a rectangular image to a square thumbnail, you can retain the important parts of the image.

All 7 comments

Hi @x2764tech

Thanks for raising the issue and taking the time to properly fill in the form. I really appreciate it.

The behaviour you are seeing is actually by design. By the time OnPostProcessing is called the cached image path has already been determined and the format set. The format of the image directly affects this path.

You best bet is to actually tap into a prior event ImageProcessingModule.ValidatingRequest

Within that event you can run your same "accepts" test and edit the querystring accordingly adding format=webp when applicable. That way you will get two cached images. You webp image for browsers that support the format and your optimized (since you have installed the postprocessor) jpeg/png for browsers that do not.

I hope this all makes sense and helps

James

Thanks James! I'll give that a try - I've tried adding an IWebGraphicsProcessor, but it doesn't get called if there's no querystring...

No worries... Yeah, that's expected. The event should be just what you need.

@x2764tech Did you create a solution for this? I'm trying to do the same, and i think it would be a great feature to have by default, if support is detected.

The best way is actually to use a picture element and use the type attribute in combination with separate request urls. No need to read headers and codify anything.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture#The_type_attribute

@JimBobSquarePants thank you for getting back, and i agree. Although on an existing site that might be a lot of html to update.
I ended up looking at the accept header and adding/replacing format=webp to the querystring if the browser had support, including some other constraints.
I can see this having unintended consequences though, so might decide not to use it anyway.

As @JimBobSquarePants says, with wide support for the picture element (and polyfills for those without), it makes more sense to use that.

I think I got a PoC working, but it was abandoned as WebP wasn't widely supported at the time, and the client wasn't entirely happy with the results - automatic conversion from (optimized) JPEG to WebP isn't the way to go.

In the end, we saved bytes by serving correctly sized images (the full sized images were being served for 250x250 thumbnails). If you go this route, you're best implement a UI that lets users choose the focus point for the image - that way if resizing/cropping a rectangular image to a square thumbnail, you can retain the important parts of the image.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jattwood picture jattwood  路  7Comments

SergeBerwert picture SergeBerwert  路  4Comments

DocCaliban picture DocCaliban  路  4Comments

rcharb1 picture rcharb1  路  8Comments

kristianstruct picture kristianstruct  路  4Comments