Support e-sRGB 16 bit PNG in ImageDecoder |
||
Issue description16 bit PNGs in e-sRGB color space decode fine to 8888, but fail to decode to F16, hence they are excluded from PNGImageDecoder unit tests. Apparently, in case of e-sRGB, ImageDecoder falls into color transformation code path, which is not the case for other color spaces when ColorBehavior is set to kTag.
,
Oct 9
The problem is not with e-sRGB, it is with the profile of the images color converted in Adobe Photoshop 18. Source image in sRGB: https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_opaque.png Converted to e-sRGB using Photoshop 18: https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_opaque.png Skia fiddle that shows skcms_Parse() successfully(?) parses the embedded profile but SkColorSpace::Make(profile) fails to return a valid color space. I'll generate some 16 bit e-sRGB samples with SkEncoder and I expect them to pass the tests. Still I think we need to fix this since Photoshop can be an important source of e-sRGB images.
,
Oct 9
Link to skia fiddle was missed :) https://fiddle.skia.org/c/d36076e979ef9f71a5436242204133fe
,
Oct 9
Yeah, that image has a profile that Skia cannot work with (or even represent with an SkColorSpace), but skcms can take it as an input. I think you might want to check for these situations and use skcms to transform to a known good SkColorSpace.
Here's the skcms iccdump for that profile:
~/skcms (public↑1|✔) $ out/clang/iccdump ~/Desktop/2x2_16bit_e-sRGB_opaque.png
Profile name from .png: 'e-sRGB'
Size : 0x00001D24 : 7460
Data color space : 0x52474220 : 'RGB '
PCS : 0x58595A20 : 'XYZ '
Tag count : 0x0000000B : 11
Tag : Type : Size : Offset
------ : ------ : ------ : --------
'cprt' : 'mluc' : 110 : 264
'desc' : 'mluc' : 40 : 376
'wtpt' : 'XYZ ' : 20 : 416
'bkpt' : 'XYZ ' : 20 : 436
'chad' : 'sf32' : 44 : 456
'A2B0' : 'mAB ' : 1688 : 500
'A2B2' : 'mAB ' : 1688 : 500
'A2B1' : 'mAB ' : 1688 : 2188
'B2A0' : 'mBA ' : 1792 : 3876
'B2A2' : 'mBA ' : 1792 : 3876
'B2A1' : 'mBA ' : 1792 : 5668
A2B : "M", Matrix, "B"
"M" : 3 inputs
M0 : 16-bit table with 256 entries
~= : 2.360165, 0.04138637, 0.2936969, 1.290439, 0.05490196, 0.01433209, 0 (Max error: 15.9174) (D-gap: -2.75224e-05)
M1 : 16-bit table with 256 entries
~= : 2.360165, 0.04138637, 0.2936969, 1.290439, 0.05490196, 0.01433209, 0 (Max error: 15.9174) (D-gap: -2.75224e-05)
M2 : 16-bit table with 256 entries
~= : 2.360165, 0.04138637, 0.2936969, 1.290439, 0.05490196, 0.01433209, 0 (Max error: 15.9174) (D-gap: -2.75224e-05)
Mtrx : | 0.959396958 0.847338140 0.314814538 -0.503105104 |
| 0.489433438 1.577521086 0.133390293 -0.521812081 |
| 0.030578148 0.213589266 1.570868373 -0.430443883 |
"B" : 3 outputs
B0 : 1, 1, 0, 0, 0, 0, 0 (~Identity)
B1 : 1, 1, 0, 0, 0, 0, 0 (~Identity)
B2 : 1, 1, 0, 0, 0, 0, 0 (~Identity)
252 random bytes transformed to linear XYZD50 bytes:
003012 e8ff0c 335505 00000c 000032 5a3300 2d9d18
8c3b0f 000000 884609 dcd000 274100 0c230c 3510c0
da9ed9 4255b8 7a8838 213706 000041 ae7b00 cd60e5
ac4e06 000012 ffff67 a327c2 a9ff22 00008a 41762b
24240e 150b1e 000028 96983f bcff76 bc577c 2d7f00
759ca3 192d05 430000 4bc020 000000 00006a 07073b
000093 000000 395b77 000000 051300 4a2400 b165bb
ffe249 e87eff 6a3305 236514 56a826 000000 86ff10
519615 8a5b00 010006 160d00 000011 000000 281403
57456b 4a245b 215600 2a004c 000000 0e0d39 4b51b0
0f2201 220ea4 00000e 590b00 5ec900 000000 4a46ef
84fe0a 31130c 151f18 633206 53b228 492302 424da1
,
Oct 9
IIUC, the check is already there and we fall back to sRGB: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/image-decoders/image_decoder.cc?l=621 Still it appears that skcms reads the embedded color profile as something different than sRGB, causing skcmsTransform to change the pixels even though the source image does not have any values outside [0,1]: (this is what PNGImageReader reads) 0.6414435035, 0.6857862211, 0.747005417, 1, // Top left pixel 0.877347982, 0.8382848859, 0.6494087129, 1, // Top right pixel 0.735194934, 0.9353933013, 0.9374380102, 1, // Bottom left pixel 0.9209277485, 0.9575799191, 0.9264515145, 1 // Bottom right pixel
,
Oct 9
Right, that's not a profile that we can recognize as sRGB. Eyeballing the 3D overlap between this profile and sRGB, it's not entirely clear to me that we'd want to. In general I don't think it makes much sense to think of A2B profiles like this in the context of extending past [0,1], at least not without matching them against if we have to go through a table lookup anywhere, that kind of defeats "extending" past the table range. Looking at this a little more closely, this is a somewhat unusual A2B profile that I think could actually be backported to be a TRC+XYZ profile. Let me run through that math and hopefully that'll let me compare against sRGB a little more sensibly.
,
Oct 9
err, that should be "...without matching them against a parametric form. If we have to ..."
,
Oct 9
Oops, I was mistaken about being able to backport that profile to TRC+XYZ for comparison. But, it still stands that there are colors in sRGB that this profile cannot represent, and colors this profile can represent that are outside sRGB. That conversion in photoshop doesn't appear to have preserved the colors. Here's what the two files you uploaded look like on my screen, the original sRGB on the left and the e-sRGB on the right.
,
Oct 11
I replaced the e-sRGB files created with Adobe Photoshop with new samples created using SkPngEncoder. Everything works fine now. https://chromium-review.googlesource.com/c/chromium/src/+/1276885 |
||
►
Sign in to add a comment |
||
Comment 1 by scroggo@chromium.org
, Aug 16The IsTag section of ImageDecoder::ColorTransform() says // This will most likely be equal to the |src_profile|. // In that case, we skip the xform when we check for equality below. It sounds like for the other color spaces, we ended up able to skip the transform, but e-sRGB is going to require one.