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.47k stars 538 forks source link

[BUG] Linear PNG colors too dark in dev/update-skia in most image viewers #1238

Open ziriax opened 4 years ago

ziriax commented 4 years ago

Description

When I switch existing code that uses 1.68 to the dev/update-skia branch, the PNGs that are saved are too dark.

We are rendering in linear color space, using 16-bit floats.

If we convert the PNGs to sRGB before saving, we get the same colors.

Code

const int width = 512;
const int height = 512;
var imageInfo = new SKImageInfo(width, height, SKColorType.RgbaF16, SKAlphaType.Premul, SKColorSpace.CreateSrgbLinear());
using var bitmap = new SKBitmap(imageInfo);
using var canvas = new SKCanvas(bitmap);
using var paint = new SKPaint { Color = SKColors.Purple};
canvas.DrawRect(0,0,width,height, paint);
using var data = bitmap.PeekPixels().Encode(new SKPngEncoderOptions());
using var stream = File.Create("output.png");
data.SaveTo(stream);

Expected Behavior

When opening the output.png image on Windows, in e.g. IrfanView, Paint, Photo Viewer, Visual Studio 2019, Paint.NET, etc.., the colors should be purple.

Actual Behavior

When opening the output.png image, the colors are very dark purple.

Note that the colors are correcty displayed in modern browsers, but since the behavior changed, I felt like reporting this.

Basic Information

mattleibow commented 4 years ago

This is interesting... I'll investigate. But this might also be a question for https://groups.google.com/forum/#!forum/skia-discuss as they may now of any internal changes.

Maybe it is the codec? Maybe it is the pixel data? Might be interesting to draw this with v1 and then save the raw bytes to a file and then upgrade to v2 and compare. If they are different, it may be how the conversions work in the pixel writing... But, the fact that you say that it works in modern browsers makes me wonder if something in the encoded file has changed. Maybe only now they included the colorspace and only the new browsers can see it. Or it might actually be the png. Did you try the others, like webp and jpeg?

But thanks for the issue. If it is a new "feature" then at least we have a heads up. And if it is a bug, then we can track any changes.

ziriax commented 4 years ago

Yes, the first thing I did was to compare both PNG files. These are very different. Strangely enough, copying the color space data from the correct PNG to the bad one didn't fix this... But I have to dig deeper, and indeed ask in Skia because this is not a SkiaSharp issue it seems.

JPEG and WebP seem to work, and copying the PNG to a F16 sRGB bitmap and then saving also works.

But I think you are right, most likely they now copy the linear colorspace info to the PNG, and WIC most likely doesn't understand this.

So this seems like a Windows bug :-)

mattleibow commented 4 years ago

Oh... Did you actually test on other platforms? Maybe attach the png and then I can test if you don't have all the bits.

ziriax commented 4 years ago

No I only tested this on Windows. I'm trying to reproduce it via remote desktop, but I can't, the PNG that looked too dark yesterday looks fine via remote desktop! So maybe this is because of color profiles on my monitors. Will know as soon as I go back to the office.

ziriax commented 4 years ago

This the PNG that is too dark on Windows (it will display correctly in your browser).

output

I'm trying to encode this on Linux too, but having a hard time building the latest version.

mattleibow commented 4 years ago

This the PNG that is too dark on Windows (it will display correctly in your browser).

I see the difference... crazy!

I'm trying to encode this on Linux too, but having a hard time building the latest version.

Just open another issue if you are having problems building... Maybe I need to update docs or maybe there is a bug somewhere in my script.

mattleibow commented 4 years ago

Ooh, GIMP popped this up when opening:

image

ziriax commented 4 years ago

I was about to try the same, lol.

I'm now opening this image with WIC, to see what it reports...

ziriax commented 4 years ago

Okay, when I try to create a WIC color space transform from the embedded PNG color profile to sRGB, I get the exception:

HRESULT: [0x800707DB], Message: The specified color profile is invalid.

I will ask around in the Google Skia mailing list.

mattleibow commented 4 years ago

FYI: https://groups.google.com/forum/#!topic/skia-discuss/b8JtsaOw7_o

ziriax commented 4 years ago

FYI: The in.jpeg image is a four channel image, most likely either CMYK or YCCK.

It can't be decoded into RGB with the "official" JPEG decoder from either libjpeg9 or libjpegturbo.

So I guess what happens is that Skia, GIMP and Chrome decode this into a 4 channel RGBA, and when saving, A is lost. Could you try to save as PNG and see if the image indeed contains alpha?

It seems the JPEG decoders need to be modified to understand special markers exported by software like Adobe Illustrator etc (as is the case with this in.jpeg)

A related very old related heated discussion: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718604

ziriax commented 4 years ago

FYI: This is the exif info of in.jpeg

ExifTool Version Number         : 10.80
File Name                       : in.jpeg
Directory                       : .
File Size                       : 227 kB
File Modification Date/Time     : 1979:12:31 22:00:00+01:00
File Access Date/Time           : 2020:09:16 12:35:01+02:00
File Inode Change Date/Time     : 2020:09:16 12:07:55+02:00
File Permissions                : rwxrwxrwx
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
X Resolution                    : 600
Displayed Units X               : inches
Y Resolution                    : 600
Displayed Units Y               : inches
XMP Toolkit                     : Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00
Format                          : image/jpeg
Title                           : Print
Metadata Date                   : 2014:02:04 10:33:21-05:00
Modify Date                     : 2014:02:04 15:33:48Z
Create Date                     : 2014:02:04 10:33:21-05:00
Creator Tool                    : Adobe Illustrator CS5
Thumbnail Width                 : 256
Thumbnail Height                : 64
Thumbnail Format                : JPEG
Thumbnail Image                 : (Binary data 7764 bytes, use -b option to extract)
Instance ID                     : xmp.iid:95B457A4CE8CE311BFA184FB07A8BCEC
Document ID                     : xmp.did:95B457A4CE8CE311BFA184FB07A8BCEC
Original Document ID            : uuid:5D20892493BFDB11914A8590D31508C8
Rendition Class                 : proof:pdf
Derived From Instance ID        : xmp.iid:19CC85F7493AE31180E9B4424EB11E91
Derived From Document ID        : xmp.did:19CC85F7493AE31180E9B4424EB11E91
Derived From Original Document ID: uuid:5D20892493BFDB11914A8590D31508C8
Derived From Rendition Class    : proof:pdf
History Action                  : saved, saved, converted, converted, saved
History Instance ID             : xmp.iid:17CC85F7493AE31180E9B4424EB11E91, xmp.iid:19CC85F7493AE31180E9B4424EB11E91, xmp.iid:95B457A4CE8CE311BFA184FB07A8BCEC
History When                    : 2013:10:22 13:09:03-04:00, 2013:10:22 13:10:05-04:00, 2014:02:04 10:33:21-05:00
History Software Agent          : Adobe Illustrator CS6 (Windows), Adobe Illustrator CS6 (Windows), Adobe Illustrator CS5
History Changed                 : /, /, /
History Parameters              : from application/postscript to application/vnd.adobe.illustrator, from application/postscript to application/vnd.adobe.illustrator
Startup Profile                 : Print
Producer                        : Adobe PDF library 10.01
DCT Encode Version              : 100
APP14 Flags 0                   : Encoded with Blend=1 downsampling
APP14 Flags 1                   : (none)
Color Transform                 : Unknown (RGB or CMYK)
Image Width                     : 1352
Image Height                    : 327
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 4
Image Size                      : 1352x327
Megapixels                      : 0.442