Skip to content

Commit

Permalink
Adding OKLAB, OKLCH, AdobeRGB and Rec2020 to SkColor4f conversion
Browse files Browse the repository at this point in the history
As part of the support of CSS Color 4, we need to support color spaces
other than sRGB for inputing colors. For that we need to add support
to some other color spaces.

This CL particularly adds support to convert from AdobeRGB to sRGB and
from Rec2020 to sRGB. This CL also adds OKLAB and OKLCH.

There have been added extensive unittests for all those color
transformations, and changing the expectation of some tests that now
should be passing.

Bug: 1358565
Change-Id: I1c44023a2291a9ab619bf263e9cc7a7bb992a95f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3922121
Auto-Submit: Juanmi Huertas <juanmihd@chromium.org>
Reviewed-by: ccameron chromium <ccameron@chromium.org>
Commit-Queue: Juanmi Huertas <juanmihd@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1052457}
  • Loading branch information
Juanmihd authored and Chromium LUCI CQ committed Sep 28, 2022
1 parent df9cb9b commit 6800580
Show file tree
Hide file tree
Showing 5 changed files with 407 additions and 57 deletions.
37 changes: 22 additions & 15 deletions third_party/blink/renderer/platform/graphics/color.cc
Original file line number Diff line number Diff line change
Expand Up @@ -386,35 +386,42 @@ SkColor4f Color::toSkColor4f() const {
switch (serialization_type_) {
case SerializationType::kRGB:
return SkColor4f{param0_, param1_, param2_, alpha_};
case SerializationType::kLab:
return gfx::LabToSkColor4f(param0_, param1_, param2_, alpha_);
case SerializationType::kOKLab:
// TODO(crbug.com/1354622): Implement CSSColor4 types.
// https://www.w3.org/TR/css-color-4/
return SkColor4f{0.0f, 0.0f, 0.0f, 0.0f};
case SerializationType::kLCH:
return gfx::LchToSkColor4f(
param0_, param1_,
param2_is_none_ ? absl::nullopt : absl::optional<float>(param2_),
alpha_);
case SerializationType::kColor:
switch (color_function_space_) {
case ColorFunctionSpace::kSRGB:
return SkColor4f{param0_, param1_, param2_, alpha_};
case ColorFunctionSpace::kSRGBLinear:
return gfx::SRGBLinearToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kDisplayP3:
return gfx::DisplayP3ToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kA98RGB:
return gfx::AdobeRGBToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kProPhotoRGB:
return gfx::ProPhotoToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kRec2020:
return gfx::Rec2020ToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kXYZD50:
return gfx::XYZD50ToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kXYZD65:
return gfx::XYZD65ToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kProPhotoRGB:
return gfx::ProPhotoToSkColor4f(param0_, param1_, param2_, alpha_);
case ColorFunctionSpace::kSRGBLinear:
return gfx::SRGBLinearToSkColor4f(param0_, param1_, param2_, alpha_);
default:
NOTIMPLEMENTED();
return SkColor4f{0.f, 0.f, 0.f, 0.f};
}
case SerializationType::kLab:
return gfx::LabToSkColor4f(param0_, param1_, param2_, alpha_);
case SerializationType::kOKLab:
return gfx::OKLabToSkColor4f(param0_, param1_, param2_, alpha_);
case SerializationType::kLCH:
return gfx::LchToSkColor4f(
param0_, param1_,
param2_is_none_ ? absl::nullopt : absl::optional<float>(param2_),
alpha_);
case SerializationType::kOKLCH:
return gfx::OKLchToSkColor4f(
param0_, param1_,
param2_is_none_ ? absl::nullopt : absl::optional<float>(param2_),
alpha_);
default:
NOTIMPLEMENTED();
return SkColor4f{0.f, 0.f, 0.f, 0.f};
Expand Down
43 changes: 4 additions & 39 deletions third_party/blink/web_tests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -1831,54 +1831,18 @@ crbug.com/1205953 external/wpt/css/css-will-change/will-change-fixpos-cb-positio
crbug.com/1207788 external/wpt/css/css-will-change/will-change-stacking-context-mask-1.html [ Failure ]

# lab color space not yet implemented
crbug.com/1358565 external/wpt/css/css-images/gradient/gradient-eval-003.html [ Failure ]
# color() function not implemented
crbug.com/1068610 external/wpt/css/css-color/predefined-008.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-005.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-011.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-007.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-002.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-012.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-016.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/predefined-006.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/a98rgb-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/a98rgb-002.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/a98rgb-003.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/a98rgb-004.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/lch-008.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/lch-005.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/lch-009.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/lch-010.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/lch-005.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/rec2020-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/rec2020-002.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/rec2020-003.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/rec2020-004.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/rec2020-005.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-009.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-010.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/color-mix-basic-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/color-mix-non-srgb-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/tagged-images-003.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/tagged-images-004.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/color-mix-percents-01.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/color-mix-percents-02.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-002.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-003.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-004.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-005.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-006.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-007.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklab-008.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-001.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-002.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-003.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-004.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-005.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-006.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-007.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-008.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-009.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/oklch-010.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/xyz-003.html [ Failure ]
crbug.com/1068610 external/wpt/css/css-color/xyz-d65-003.html [ Failure ]
crbug.com/1068610 [ Linux ] external/wpt/css/css-color/t422-rgba-a0.6-a.xht [ Failure ]
Expand Down Expand Up @@ -2559,6 +2523,7 @@ crbug.com/630597 external/wpt/css/css-images/image-set/image-set-content-renderi
crbug.com/604875 external/wpt/css/css-images/tiled-gradients.html [ Failure ]

crbug.com/1362022 external/wpt/css/css-images/gradient/gradient-eval-002.html [ Failure ]
crbug.com/1358565 external/wpt/css/css-images/gradient/gradient-eval-003.html [ Failure ]
crbug.com/1362022 external/wpt/css/css-images/gradient/gradient-eval-004.html [ Failure ]
crbug.com/1362022 external/wpt/css/css-images/gradient/gradient-eval-005.html [ Failure ]
crbug.com/1362022 external/wpt/css/css-images/gradient/gradient-eval-006.html [ Failure ]
Expand Down
90 changes: 90 additions & 0 deletions ui/gfx/color_conversions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ std::tuple<float, float, float> ApplyTransferFnProPhoto(float r,
skcms_TransferFunction_eval(&SkNamedTransferFnExt::kProPhotoRGB, b));
}

std::tuple<float, float, float> ApplyTransferFnAdobeRGB(float r,
float g,
float b) {
return std::make_tuple(
skcms_TransferFunction_eval(&SkNamedTransferFn::k2Dot2, r),
skcms_TransferFunction_eval(&SkNamedTransferFn::k2Dot2, g),
skcms_TransferFunction_eval(&SkNamedTransferFn::k2Dot2, b));
}

std::tuple<float, float, float> ApplyTransferFnRec2020(float r,
float g,
float b) {
return std::make_tuple(
skcms_TransferFunction_eval(&SkNamedTransferFn::kRec2020, r),
skcms_TransferFunction_eval(&SkNamedTransferFn::kRec2020, g),
skcms_TransferFunction_eval(&SkNamedTransferFn::kRec2020, b));
}
} // namespace

std::tuple<float, float, float> LchToLab(float l,
Expand Down Expand Up @@ -129,6 +146,38 @@ std::tuple<float, float, float> LabToXYZD50(float l, float a, float b) {
return std::make_tuple(x, y, z);
}

std::tuple<float, float, float> OKLabToXYZD65(float l, float a, float b) {
// Given OKLab, convert to XYZ relative to D65
skcms_Matrix3x3 LMStoXYZ = {
{{1.2268798733741557f, -0.5578149965554813f, 0.28139105017721583f},
{-0.04057576262431372f, 1.1122868293970594f, -0.07171106666151701f},
{-0.07637294974672142f, -0.4214933239627914f, 1.5869240244272418f}}};
skcms_Matrix3x3 OKLabtoLMS = {
{{0.99999999845051981432f, 0.39633779217376785678f,
0.21580375806075880339f},
{1.0000000088817607767f, -0.1055613423236563494f,
-0.063854174771705903402f},
{1.0000000546724109177f, -0.089484182094965759684f,
-1.2914855378640917399f}}};

skcms_Vector3 lab_input{{l / 100.f, a, b}};
skcms_Vector3 lms_intermediate =
skcms_Matrix3x3_apply(&OKLabtoLMS, &lab_input);
lms_intermediate.vals[0] = lms_intermediate.vals[0] *
lms_intermediate.vals[0] *
lms_intermediate.vals[0];
lms_intermediate.vals[1] = lms_intermediate.vals[1] *
lms_intermediate.vals[1] *
lms_intermediate.vals[1];
lms_intermediate.vals[2] = lms_intermediate.vals[2] *
lms_intermediate.vals[2] *
lms_intermediate.vals[2];
skcms_Vector3 xyz_output =
skcms_Matrix3x3_apply(&LMStoXYZ, &lms_intermediate);
return std::make_tuple(xyz_output.vals[0], xyz_output.vals[1],
xyz_output.vals[2]);
}

std::tuple<float, float, float> XYZD50toD65(float x, float y, float z) {
skcms_Vector3 xyz_input{{x, y, z}};
skcms_Vector3 xyz_output =
Expand Down Expand Up @@ -171,6 +220,24 @@ std::tuple<float, float, float> DisplayP3ToXYZD50(float r, float g, float b) {
xyz_output.vals[2]);
}

std::tuple<float, float, float> AdobeRGBToXYZD50(float r, float g, float b) {
auto [r_, g_, b_] = ApplyTransferFnAdobeRGB(r, g, b);
skcms_Vector3 rgb_input{{r_, g_, b_}};
skcms_Vector3 xyz_output =
skcms_Matrix3x3_apply(&SkNamedGamut::kAdobeRGB, &rgb_input);
return std::make_tuple(xyz_output.vals[0], xyz_output.vals[1],
xyz_output.vals[2]);
}

std::tuple<float, float, float> Rec2020ToXYZD50(float r, float g, float b) {
auto [r_, g_, b_] = ApplyTransferFnRec2020(r, g, b);
skcms_Vector3 rgb_input{{r_, g_, b_}};
skcms_Vector3 xyz_output =
skcms_Matrix3x3_apply(&SkNamedGamut::kRec2020, &rgb_input);
return std::make_tuple(xyz_output.vals[0], xyz_output.vals[1],
xyz_output.vals[2]);
}

SkColor4f SRGBLinearToSkColor4f(float r, float g, float b, float alpha) {
auto [srgb_r, srgb_g, srgb_b] = ApplyInverseTransferFnsRGB(r, g, b);
return SkColor4f{srgb_r, srgb_g, srgb_b, alpha};
Expand All @@ -196,6 +263,11 @@ SkColor4f ProPhotoToSkColor4f(float r, float g, float b, float alpha) {
return XYZD50ToSkColor4f(x, y, z, alpha);
}

SkColor4f OKLabToSkColor4f(float l, float a, float b, float alpha) {
auto [x, y, z] = OKLabToXYZD65(l, a, b);
return XYZD65ToSkColor4f(x, y, z, alpha);
}

SkColor4f DisplayP3ToSkColor4f(float r, float g, float b, float alpha) {
auto [x, y, z] = DisplayP3ToXYZD50(r, g, b);
return XYZD50ToSkColor4f(x, y, z, alpha);
Expand All @@ -209,5 +281,23 @@ SkColor4f LchToSkColor4f(float l_input,
auto [x, y, z] = LabToXYZD50(l, a, b);
return XYZD50ToSkColor4f(x, y, z, alpha);
}
SkColor4f AdobeRGBToSkColor4f(float r, float g, float b, float alpha) {
auto [x, y, z] = AdobeRGBToXYZD50(r, g, b);
return XYZD50ToSkColor4f(x, y, z, alpha);
}

SkColor4f Rec2020ToSkColor4f(float r, float g, float b, float alpha) {
auto [x, y, z] = Rec2020ToXYZD50(r, g, b);
return XYZD50ToSkColor4f(x, y, z, alpha);
}

SkColor4f OKLchToSkColor4f(float l_input,
float c,
absl::optional<float> h,
float alpha) {
auto [l, a, b] = LchToLab(l_input, c, h);
auto [x, y, z] = OKLabToXYZD65(l, a, b);
return XYZD65ToSkColor4f(x, y, z, alpha);
}

} // namespace gfx
38 changes: 38 additions & 0 deletions ui/gfx/color_conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ GFX_EXPORT std::tuple<float, float, float> LabToXYZD50(float l,
float a,
float b);

// Method exposed for testing purposes.
GFX_EXPORT std::tuple<float, float, float> OKLabToXYZD65(float l,
float a,
float b);

// Method exposed for testing purposes.
GFX_EXPORT std::tuple<float, float, float> DisplayP3ToXYZD50(float r,
float g,
Expand All @@ -28,6 +33,16 @@ GFX_EXPORT std::tuple<float, float, float> ProPhotoToXYZD50(float r,
float g,
float b);

// Method exposed for testing purposes.
GFX_EXPORT std::tuple<float, float, float> AdobeRGBToXYZD50(float r,
float g,
float b);

// Method exposed for testing purposes.
GFX_EXPORT std::tuple<float, float, float> Rec2020ToXYZD50(float r,
float g,
float b);

// Method exposed for testing purposes.
GFX_EXPORT std::tuple<float, float, float> XYZD50toD65(float x,
float y,
Expand All @@ -48,6 +63,11 @@ GFX_EXPORT std::tuple<float, float, float> LchToLab(float l,
float c,
absl::optional<float> h);

// Method exposed for testing purposes.
GFX_EXPORT std::tuple<float, float, float> OKLchToLab(float l,
float c,
absl::optional<float> h);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f XYZD50ToSkColor4f(float x, float y, float z, float alpha);

Expand All @@ -57,6 +77,9 @@ GFX_EXPORT SkColor4f XYZD65ToSkColor4f(float x, float y, float z, float alpha);
// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f LabToSkColor4f(float l, float a, float b, float alpha);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f OKLabToSkColor4f(float l, float a, float b, float alpha);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f SRGBLinearToSkColor4f(float r,
float g,
Expand All @@ -75,12 +98,27 @@ GFX_EXPORT SkColor4f DisplayP3ToSkColor4f(float r,
float b,
float alpha);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f AdobeRGBToSkColor4f(float r,
float g,
float b,
float alpha);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f Rec2020ToSkColor4f(float r, float g, float b, float alpha);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f LchToSkColor4f(float l,
float a,
absl::optional<float> b,
float alpha);

// Method exposed for blink::color conversions.
GFX_EXPORT SkColor4f OKLchToSkColor4f(float l,
float a,
absl::optional<float> b,
float alpha);

} // namespace gfx

#endif // UI_GFX_COLOR_CONVERSIONS_H_
Loading

0 comments on commit 6800580

Please sign in to comment.