mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.17k stars 522 forks source link

[BUG] Webp image color change after resize #2784

Closed MichaelLogutov closed 2 months ago

MichaelLogutov commented 2 months ago

Description

When loading webp image and saving it in jpg without any transformation all colors preserved correctly. But when scale transformation applied colors became darker.

I've tried it on SkiaSharp 2.88.7 and 3.0.0-preview.2.1

Here the source webp image: test.zip Here the results.

Not scaled: test-output-not-scaled Scaled: test-output-scaled

Code

using var bitmap = SKBitmap.Decode(@"c:\Temp\test.webp");

using var bitmap2 = new SKBitmap(new SKImageInfo(bitmap.Info.Width / 2, bitmap.Info.Height / 2));
bitmap.ScalePixels(bitmap2, new SKSamplingOptions(SKFilterMode.Nearest, SKMipmapMode.Nearest));

using (var file = new SKFileWStream(@"c:\Temp\test-output-not-scaled.jpg"))
    bitmap.Encode(file, SKEncodedImageFormat.Jpeg, 100);

using (var file = new SKFileWStream(@"c:\Temp\test-output-scaled.jpg"))
    bitmap2.Encode(file, SKEncodedImageFormat.Jpeg, 100);

Expected Behavior

No response

Actual Behavior

No response

Version of SkiaSharp

3.x (Alpha)

Last Known Good Version of SkiaSharp

2.88.2 (Previous)

IDE / Editor

Other (Please indicate in the description)

Platform / Operating System

Linux, Windows

Platform / Operating System Version

No response

Devices

No response

Relevant Screenshots

No response

Relevant Log Output

No response

Code of Conduct

TommiGustafsson-HMP commented 2 months ago

I think the problem is that your original picture has a color profile, which is lost at some point. If you open your original picture in Photoshop (Elements) and Convert Color Profile -> Remove Profile, the same thing as reported here will happen.

MichaelLogutov commented 2 months ago

Yeah, I think you right. But I can't see why scaling do this.

TommiGustafsson-HMP commented 2 months ago

There seems to be a question on this on StackOverflow: https://stackoverflow.com/questions/50399279/skiasharp-save-image-with-icc-profile

MichaelLogutov commented 2 months ago

That was it. Thanks! Basically, the fix was using image info from original image, thus using it's color space:

using var bitmap = SKBitmap.Decode(@"c:\Temp\test.webp");

using var bitmap2 = new SKBitmap(bitmap.Info.WithSize(bitmap.Info.Width / 2, bitmap.Info.Height / 2));
bitmap.ScalePixels(bitmap2, new SKSamplingOptions(SKFilterMode.Nearest, SKMipmapMode.Nearest));

using (var file = new SKFileWStream(@"c:\Temp\test-output-not-scaled.jpg"))
    bitmap.Encode(file, SKEncodedImageFormat.Jpeg, 100);

using (var file = new SKFileWStream(@"c:\Temp\test-output-scaled.jpg"))
    bitmap2.Encode(file, SKEncodedImageFormat.Jpeg, 100);