Chrome does not support A2B/B2A color profiles |
|||
Issue descriptionTo reproduce: - Install the attached ICC profile (from issue 762222 ) - Open the attached image in eog (Eye of Gnome) and Chrome Notice that the colors are different - the light color is 247,42,0 in EOG - the light color is 235,15,2 in Chrome - the dark color is 235,40,0 in EOG - the dark color is 223,0,10 in Chrome This is a non-parametric color space that we fail to accurately approximate (only slightly ... we are off by 2/255, which is much less than the above-noted differences), and use a LUT-based transform for. I still get basically the same results in Chrome even if - dramatically increase the resolution of the LUT - use the parametric approximation (accepting the 2/255 error) We need to understand why we're getting different results here.
,
Mar 9 2018
Brian, are we favoring the rTRC/gTRC/bTRC here in Skia over the A2B?
,
Mar 9 2018
I'm not sure, that depends on some decisions at the Chrome level, I think? Here's the TRC curves (in RGB) (along with the approximation in Magenta). Note that the tables are slightly different from each other. The A2B curves are almost identity, except for strangle noise at the low end of the A curves (also attached). I still don't have a visualizer for the CLUT, but I can imagine that other tools are taking the A2B path and we're using the TRC (tables or approximation), leading to nontrivial differences.
,
Mar 9 2018
Where Chrome has a choice, it favors *TRC over A2B. This particular profile *happens* to go through our LUT scheme, which *could* use the A2B (it uses SkColorSpaceXform::Apply to create a LUT). It does appear that SkColorSpaceXform prefers parametric to A2B [1]. We won't want to use an A2B representation if the parametric scheme is close enough, so we'd need to (empirically?) see how different the two transforms are. So if we were to work on this problem, Chrome would probably want a "prefer A2B representation" flag to specify to SkColorSpaceXform::New, and then Chrome could do the empirical test to decide if it wants to use parametric or A2B. [1] https://cs.chromium.org/chromium/src/third_party/skia/src/core/SkColorSpaceXform.cpp?rcl=b537879c7214efd87840c9a7267ab3b3facda873&l=304
,
Mar 9 2018
Actually, one more point to add is that Chrome doesn't support ICC profiles that don't provide a primary matrix (the reason being that we can only rasterize into a parametric space, and without the primary matrix, we can't even guess a good gamut to use for rasterization ... we had buggy guesses at this earlier, but got rid of them). So I'd put this as a feature request for A2B support.
,
Mar 29 2018
This is also an issue on Nvidia's GeforeExperience. There's no option to force sRGB mode.
,
Mar 29 2018
Monitor profile attached:
,
Mar 29 2018
Thank you for this profile. Although not directly related to this bug, I'm working on improving Chrome's color management, and that file has several extremely tricky characteristics. We're working on handling it better.
,
Mar 29 2018
No problem. Should I create a separate issue? If you need any help testing let me know. FYI that profile was generated with DisplayCal.
,
Apr 13 2018
> except for strangle noise at the low end of the A curves That is not noise. The cLUT has 33 grid steps in each direction, so the A curves match these intervals to follow the curvature of the underlying monitor response. Effectively this increases the cLUT resolution and thus accuracy. It is an implementation detail though. Also note that for display color management (where the display profile is the destination profile), the A2B table is irrelevant. You want to use the B2A table in that case. > ASUS MG279 #1 2018-02-01 18-57 2.2 F-S XYZLUT+MTX.icm This ASUS profile indicates problems with the monitor (e.g. hardware setup), or the instrument used to do the measurements. The embedded measurement data shows that dark red (RGB 64 0 0) and dark blue (RGB 0 0 64) measured darker than black (RGB 0 0 0), which seems very inplausible. The B156HW01 profile on the other hand is fine.
,
Apr 13 2018
> Also note that for display color management (where the display profile is the destination profile), the A2B table is irrelevant. You want to use the B2A table in that case. Our approach to handle complex display profiles is to fit an approximation to the forward transform with a function of a fixed number of parameters, then invert that. I agree it'd be better to approximate B2A directly than approximate A2B and invert, but it's a bit moot because we don't even have the ability to approximate A2B. The best we can do for B2A display profiles right now is ignore the B2A tags entirely, instead approximating and inverting the TRC curves and XYZ matrix.
,
Apr 17 2018
,
Apr 17 2018
,
May 22 2018
> Our approach to handle complex display profiles is to fit an approximation to the forward transform with a function of a fixed number of parameters, then invert that. The problem with those and similar simplified approaches is, quite frankly, that they are all half-assed, and as a direct consequence of that, the results are as well. The question that you really need to ask yourselves, do you really want to (re-)invent something complex like littlCMS, or sampleICC, or Argyll's icclib, from scratch, again, repeating the same mistakes and (poor) decisions that Mozilla made back in the day when they attempted the same thing? I think the answer is a resounding no, unless your goal really is to create another ICC based color management module and re-invent the wheel, and not just getting color management supported (properly!) in Chrome and Chromium.
,
May 22 2018
If our goal were to transform images from one color space to another, then there are several libraries that would do our job. (Though many of them are riddled with security holes). As it turns out, Chrome is much more than an image viewer, and none of those libraries are suited to the task of rasterizing arbitrarily complex web content. Beyond that, because of the rasterization requirements, supporting arbitrary display profiles is likely to be prohibitively expensive. That said, we are evaluating the need for B2A and inverted LUT based TRCs as a final pass (after rasterizing to a less complex intermediate space).
,
May 22 2018
Regardless of what we do, we definitely need to do most of the work from scratch, because chrome does most of it's work on the GPU and as far as I know, none of the existing color management libraries are able to generate GLSL code for the transform. To make matters worse, any table-based transform will perform worse than a formula based one on the gpu. Also, if we're going to raster in a common space and then transform to an output space, we really should try to make the intermediate space have more than 8 bits to avoid adding more banding to the final result.
,
May 22 2018
> If our goal were to transform images from one color space to another Well, but that is part of your goal if you're interested in color management. Transforming pixel data (not necessarily limited to images) from one color space to another. > Though many of them are riddled with security holes I don't buy the security argument unless you are really that certain that you can do a better job at security than the guys maintaining said libraries (it's beside the point, but I'd really like to see a CVE of a known security vulnerability in a current version of those libraries). > none of those libraries are suited to the task of rasterizing arbitrarily complex web content The main point of these libraries is not rasterization though, but to create transforms (from linking profiles together) that can be applied over and over to arbitrary color (pixel) data, while at the same time supporting all the aspects of ICC profiles that are in the respective specification. Implementing that alone is not a trivial task unless you only implement a subset, and then you have the problems that Mozilla had (and to some extent still has now). > (after rasterizing to a less complex intermediate space) As long as you don't base the intermediate space on the display color space that should be fine (i.e. the intermediate space needs to be well-behaved). > Beyond that, because of the rasterization requirements, supporting arbitrary display profiles is likely to be prohibitively expensive. When it's not hardware (GPU) accelerated, maybe. > none of the existing color management libraries are able to generate GLSL code for the transform. True, you need some GLSL boilerplate. > To make matters worse, any table-based transform will perform worse than a formula based one on the gpu. The question is does it matter? My impression is that texture pipelines even on just moderately modern hardware are extremely optimized. I remember my old (long de-commissioned) GeForce Ti 4200 being fast enough to transform the whole desktop in real-time at 60+ fps (on Linux with Compiz and compICC plugin). That was roughly around 2009 if I recall correctly. Perhaps it matters on mobile where battery life is limited and power consumption, not performance, is the main concern, but then again, people that actually would profile their mobile displays likely really care about correct color and would be fine if power consumption increases somewhat. > Also, if we're going to raster in a common space and then transform to an output space, we really should try to make the intermediate space have more than 8 bits to avoid adding more banding to the final result. Definitely.
,
May 22 2018
Re #17: > I remember my old (long de-commissioned) GeForce Ti 4200 being fast enough to transform the whole desktop > in real-time at 60+ fps (on Linux with Compiz and compICC plugin). That was roughly around 2009 if I recall > correctly. Perhaps it matters on mobile where battery life is limited and power consumption, not performance FYI, we did an analysis of battery consumption of compositing with a 3D LUT for color conversion, and, unless the input image was noise (causing indirect texture fetch to blow up the cache), the power impact was - not that bad - measurably worse than just doing shader math (especially for a 64x64x64 LUT) - tiny compared to the power required to update the display https://docs.google.com/document/d/1lTyFs7_BtBAdL0ChoUtq1RVmP_1boGcnpqiNuNY5Ugk/edit?usp=sharing We currently have this code hooked up in our compositor (but it doesn't use the B2A data). |
|||
►
Sign in to add a comment |
|||
Comment 1 by mtkl...@google.com
, Mar 9 2018For reference, ~/skcms (master|✔) $ out/clang/iccdump ~/Downloads/B156HW01\ \#1\ 2017-08-07\ 23-19\ 2.2\ F-S\ XYZLUT+MTX.icc Size : 0x000B4E0C : 740876 CMM type : 0x00000000 : '' Version : 0x02400000 : 2.4.0 Profile class : 0x6D6E7472 : 'mntr' Data color space : 0x52474220 : 'RGB ' PCS : 0x58595A20 : 'XYZ ' Creation date/time : : 2017-08-07 23:31:23 Signature : 0x61637370 : 'acsp' Platform : 0x00000000 : '' Flags : 0x00000000 Device manufacturer : 0x0000AE30 : '' Device model : 0x000040B2 : '' Device attributes : 0x00000000 : 0x00000000 Rendering intent : 0x00000000 : 0 Illuminant X : : 0.964202881 Illuminant Y : : 1 Illuminant Z : : 0.824905396 Creator : 0x00000000 : '' Tag count : 0x00000016 : 22 Tag : Type : Size : Offset ------ : ------ : ------ : -------- 'desc' : 'desc' : 138 : 396 'cprt' : 'text' : 74 : 536 'lumi' : 'XYZ ' : 20 : 612 'wtpt' : 'XYZ ' : 20 : 632 'bkpt' : 'XYZ ' : 20 : 652 'vcgt' : 'vcgt' : 1554 : 672 'A2B0' : 'mft2' : 227980 : 2228 'rXYZ' : 'XYZ ' : 20 : 230208 'gXYZ' : 'XYZ ' : 20 : 230228 'bXYZ' : 'XYZ ' : 20 : 230248 'rTRC' : 'curv' : 524 : 230268 'gTRC' : 'curv' : 524 : 230792 'bTRC' : 'curv' : 524 : 231316 'A2B1' : 'mft2' : 227980 : 2228 'B2A1' : 'mft2' : 241786 : 231840 'B2A0' : 'mft2' : 241786 : 473628 'targ' : 'text' : 23061 : 715416 'DevD' : 'text' : 23061 : 715416 'CIED' : 'text' : 23061 : 715416 'chrm' : 'chrm' : 36 : 738480 'mmod' : 'mmod' : 40 : 738516 'meta' : 'dict' : 2320 : 738556 ~TRC : 2.1826818, 1.02218008, -0.0218680613, 0.182920888, 0.0235294122, 0.00430246489, 0 (Max error: 0.00801050663) rTRC : 16-bit table with 256 entries gTRC : 16-bit table with 256 entries bTRC : 16-bit table with 256 entries XYZ : | 0.616897583 0.204925537 0.142379761 | | 0.293243408 0.653274536 0.053482056 | | 0.008407593 0.083129883 0.733367920 | A2B : "A", CLUT, "B" "A" : 3 inputs A0 : 16-bit table with 2049 entries A1 : 16-bit table with 2049 entries A2 : 16-bit table with 2049 entries CLUT : 33 x 33 x 33 (16 bpp) "B" : 3 outputs B0 : 16-bit table with 2 entries B1 : 16-bit table with 2 entries B2 : 16-bit table with 2 entries