Imagesharp: Resizing Jpeg file in an Azure Function generates image with deformed colors

Created on 21 Apr 2019  路  6Comments  路  Source: SixLabors/ImageSharp

Prerequisites

  • [x] I have written a descriptive issue title
  • [x] I have verified that I am running the latest version of ImageSharp
  • [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 <-- did my best

Description

I'm implementing an Azure function to resize/shrink images that are dropped into a storage container, and then move the generated image into a different storage container for consumption by our application. The coloring in the bottom half of generated image appears to be inverted - see before and after links below.

Original image before resizing

New image generated after resizing

Steps to Reproduce

The pseudo-code for the Azure function goes like this:

1 - The function is triggered by dropping a file in a storage container designated as the ingestion container for images:

```[FunctionName("productimages-ingestion")]
public async static Task ProductImagesUploadRun(
[BlobTrigger("productimages-ingestion/{fileName}", Connection = "AzureWebJobsStorage")]
Stream imageBlob, string fileName, ILogger log)

2 - You can see the image is available to the code as a `Stream`. We do some quick validation and pass the stream object along to another method responsible for creating a new resized image: 

private static MemoryStream NewImage(
Stream originalImage, IImageEncoder encoder, int height, int width)
{
var resizedImageStream = new MemoryStream();
using (var imageToResize = Image.Load(originalImage))
{
imageToResize.Mutate(x => x.Resize(width, height));
imageToResize.Save(resizedImageStream, encoder);
resizedImageStream.Position = 0;
}
return resizedImageStream;
}

3 - We then save the generated image into the new storage container

var largeImageBlob = cloudBlobContainer.GetBlockBlobReference(sku + "-Large" + extension);
await largeImageBlob.UploadFromStreamAsync(
NewImage(imageBlob, encoder, image.Height / 4, image.Width / 4));

Interestingly, if I try this outside of an Azure Function the issue doesn't occur. I can't put my finger on what is different. 

Tried with a simple file: 

using (Image image = Image.Load("A-16299.jpg"))
{
image.Mutate(x => x.Resize(image.Width / 4, image.Height / 4));
image.Save("A-16299-Resized-File.jpg");
}

then also tried to replicate as closely as possible using streams:

using (MemoryStream ms = new MemoryStream())
{
using (FileStream file = new FileStream("A-16299.jpg", FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
ms.Position = 0;
}

var resizedImageStream = new MemoryStream();
using (Image<Rgba32> imageToResize = Image.Load(ms))
{
    imageToResize.Mutate(x => x.Resize(imageToResize.Width / 4, imageToResize.Height / 4));
    imageToResize.Save(resizedImageStream, new JpegEncoder());
    resizedImageStream.Position = 0;

    using (FileStream file = new FileStream("A-16299-Resized-Stream.jpg", FileMode.Create, FileAccess.Write))
    {
        resizedImageStream.WriteTo(file);
    }
}

}
```

Other interesting tidbit is I asked one of our designers to have a look at the original file in Photoshop and she let me know that there was "extra information" in the file that might have been contributing to this. She saved it out again as a web-friendly JPEG and the issue disappeared. However, that doesn't explain why in my console application I don't see the issue even when dealing with the original / un-fixed file.

Thanks in advance for your help.

System Configuration

  • ImageSharp version: 1.0.0-beta0006
  • Other ImageSharp packages and versions: n/a
  • Environment (Operating system, version and so on): Azure Function
  • .NET Framework version: .NET Core 2.1
  • Additional information: n/a

Most helpful comment

Hi @gdurzi

Would it be possible to test this against our development build? There's bee substancial changes to resizing and jpeg decoding

All 6 comments

Hi @gdurzi

Would it be possible to test this against our development build? There's bee substancial changes to resizing and jpeg decoding

@JimBobSquarePants thanks for the suggestion. I updated the package to dev002592, and had to make some small changes to the code:

var resizedImageStream = new MemoryStream();
using (var imageToResize = Image.Load(originalImageStream, new JpegDecoder()))
{
    imageToResize.Mutate(x => x.Resize(width, height));
    imageToResize.Save(resizedImageStream, new JpegEncoder());
    resizedImageStream.Position = 0;
}
return resizedImageStream;

My code is now throwing the "Missing SOI marker" exception from the JpegDecoderCore class.

https://github.com/SixLabors/ImageSharp/blob/5a85ea72b55255c80ffbec94ea703937759aaf2f/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs#L258

I'll continue to troubleshoot. Thanks!

Why are you specifying the decoder? The library will detect the correct format automatically. Is your original stream in the correct position?

Thanks, @JimBobSquarePants. My bad, I for some reason thought the Load method signature changed with the new package version.

This now works great, here's my updated method:

private static MemoryStream NewImage(Stream originalImageStream, int height, int width)
{
    originalImageStream.Position = 0;
    var resizedImageStream = new MemoryStream();
    using (var imageToResize = Image.Load(originalImageStream))
    {
        imageToResize.Mutate(x => x.Resize(width, height));
        imageToResize.Save(resizedImageStream, new JpegEncoder());
        resizedImageStream.Position = 0;
    }
    return resizedImageStream;
}

Thanks for your help!

@gdurzi Glad you figured it out! 馃憤

Hi, I am still getting this error of deformed lower part with nightly dev builds also. This is happening with JPG versions and not PNG.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xakep139 picture xakep139  路  4Comments

Hawxy picture Hawxy  路  3Comments

Inumedia picture Inumedia  路  3Comments

marcpabst picture marcpabst  路  3Comments

vad3x picture vad3x  路  4Comments