New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 820233 link

Starred by 13 users

Issue metadata

Status: Assigned
Owner:
Cc:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Mac
Pri: 3
Type: Bug



Sign in to add a comment

Chrome does not support A2B/B2A color profiles

Project Member Reported by ccameron@chromium.org, Mar 8 2018

Issue description

To 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.
 
Webkit-logo-P3.png
76.2 KB View Download
B156HW01 #1 2017-08-07 23-19 2.2 F-S XYZLUT+MTX.icc
723 KB Download

Comment 1 by mtkl...@google.com, Mar 9 2018

For 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

Comment 2 by mtkl...@google.com, Mar 9 2018

Brian, are we favoring the rTRC/gTRC/bTRC here in Skia over the A2B?
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.
TRC_curves.svg
14.5 KB Download
A_curves.svg
72.6 KB Download
Labels: OS-Mac OS-Windows
Summary: ICC profiles with A2B and parametric representations always use the parametric representation (was: Non-parametric ICC profile is interpreted differently in Chrome vs EOG (and others))
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
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.
This is also an issue on Nvidia's GeforeExperience. There's no option to force sRGB mode.


NVIDIA GeForce Experience_2018-03-28_21-28-58.png
659 KB View Download
Monitor profile attached:
ASUS MG279 #1 2018-02-01 18-57 2.2 F-S XYZLUT+MTX.icm
723 KB Download
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.
No problem. Should I create a separate issue? If you need any help testing let me know.

FYI that profile was generated with DisplayCal.
> 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.

Comment 11 by mtkl...@google.com, 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.
Summary: Chrome does not support A2B/B2A color profiles (was: ICC profiles with A2B and parametric representations always use the parametric representation)
Cc: ccameron@chromium.org
 Issue 830168  has been merged into this issue.
> 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.
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).

Comment 16 by hubbe@chromium.org, 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.

> 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.
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