Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Unified Diff: ui/gfx/color_transform.cc

Issue 2652503002: Use SkICC in gfx::ICCProfile and gfx::ColorSpace (Closed)
Patch Set: Rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gfx/color_transform.h ('k') | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/color_transform.cc
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc
index 110521f8d580fab079b86abdf669c97434425a98..2453f46918da8b7a42be5cda7129acabfa80eedb 100644
--- a/ui/gfx/color_transform.cc
+++ b/ui/gfx/color_transform.cc
@@ -21,6 +21,14 @@ extern "C" {
namespace gfx {
+float EvalSkTransferFn(const SkColorSpaceTransferFn& fn, float x) {
+ if (x < 0)
+ return 0;
+ if (x < fn.fD)
+ return fn.fC * x + fn.fF;
+ return powf(fn.fA * x + fn.fB, fn.fG) + fn.fE;
+}
+
Transform Invert(const Transform& t) {
Transform ret = t;
if (!t.GetInverse(&ret)) {
@@ -29,181 +37,12 @@ Transform Invert(const Transform& t) {
return ret;
}
-GFX_EXPORT Transform GetPrimaryMatrix(ColorSpace::PrimaryID id) {
- SkColorSpacePrimaries primaries = {0};
- switch (id) {
- case ColorSpace::PrimaryID::CUSTOM:
- NOTREACHED();
-
- case ColorSpace::PrimaryID::RESERVED0:
- case ColorSpace::PrimaryID::RESERVED:
- case ColorSpace::PrimaryID::UNSPECIFIED:
- case ColorSpace::PrimaryID::UNKNOWN:
- case ColorSpace::PrimaryID::BT709:
- // BT709 is our default case. Put it after the switch just
- // in case we somehow get an id which is not listed in the switch.
- // (We don't want to use "default", because we want the compiler
- // to tell us if we forgot some enum values.)
- primaries.fRX = 0.640f;
- primaries.fRY = 0.330f;
- primaries.fGX = 0.300f;
- primaries.fGY = 0.600f;
- primaries.fBX = 0.150f;
- primaries.fBY = 0.060f;
- primaries.fWX = 0.3127f;
- primaries.fWY = 0.3290f;
- break;
-
- case ColorSpace::PrimaryID::BT470M:
- primaries.fRX = 0.67f;
- primaries.fRY = 0.33f;
- primaries.fGX = 0.21f;
- primaries.fGY = 0.71f;
- primaries.fBX = 0.14f;
- primaries.fBY = 0.08f;
- primaries.fWX = 0.31f;
- primaries.fWY = 0.316f;
- break;
-
- case ColorSpace::PrimaryID::BT470BG:
- primaries.fRX = 0.64f;
- primaries.fRY = 0.33f;
- primaries.fGX = 0.29f;
- primaries.fGY = 0.60f;
- primaries.fBX = 0.15f;
- primaries.fBY = 0.06f;
- primaries.fWX = 0.3127f;
- primaries.fWY = 0.3290f;
- break;
-
- case ColorSpace::PrimaryID::SMPTE170M:
- case ColorSpace::PrimaryID::SMPTE240M:
- primaries.fRX = 0.630f;
- primaries.fRY = 0.340f;
- primaries.fGX = 0.310f;
- primaries.fGY = 0.595f;
- primaries.fBX = 0.155f;
- primaries.fBY = 0.070f;
- primaries.fWX = 0.3127f;
- primaries.fWY = 0.3290f;
- break;
-
- case ColorSpace::PrimaryID::FILM:
- primaries.fRX = 0.681f;
- primaries.fRY = 0.319f;
- primaries.fGX = 0.243f;
- primaries.fGY = 0.692f;
- primaries.fBX = 0.145f;
- primaries.fBY = 0.049f;
- primaries.fWX = 0.310f;
- primaries.fWY = 0.136f;
- break;
-
- case ColorSpace::PrimaryID::BT2020:
- primaries.fRX = 0.708f;
- primaries.fRY = 0.292f;
- primaries.fGX = 0.170f;
- primaries.fGY = 0.797f;
- primaries.fBX = 0.131f;
- primaries.fBY = 0.046f;
- primaries.fWX = 0.3127f;
- primaries.fWY = 0.3290f;
- break;
-
- case ColorSpace::PrimaryID::SMPTEST428_1:
- primaries.fRX = 1.0f;
- primaries.fRY = 0.0f;
- primaries.fGX = 0.0f;
- primaries.fGY = 1.0f;
- primaries.fBX = 0.0f;
- primaries.fBY = 0.0f;
- primaries.fWX = 1.0f / 3.0f;
- primaries.fWY = 1.0f / 3.0f;
- break;
-
- case ColorSpace::PrimaryID::SMPTEST431_2:
- primaries.fRX = 0.680f;
- primaries.fRY = 0.320f;
- primaries.fGX = 0.265f;
- primaries.fGY = 0.690f;
- primaries.fBX = 0.150f;
- primaries.fBY = 0.060f;
- primaries.fWX = 0.314f;
- primaries.fWY = 0.351f;
- break;
-
- case ColorSpace::PrimaryID::SMPTEST432_1:
- primaries.fRX = 0.680f;
- primaries.fRY = 0.320f;
- primaries.fGX = 0.265f;
- primaries.fGY = 0.690f;
- primaries.fBX = 0.150f;
- primaries.fBY = 0.060f;
- primaries.fWX = 0.3127f;
- primaries.fWY = 0.3290f;
- break;
-
- case ColorSpace::PrimaryID::XYZ_D50:
- primaries.fRX = 1.0f;
- primaries.fRY = 0.0f;
- primaries.fGX = 0.0f;
- primaries.fGY = 1.0f;
- primaries.fBX = 0.0f;
- primaries.fBY = 0.0f;
- primaries.fWX = 0.34567f;
- primaries.fWY = 0.35850f;
- break;
- }
-
- SkMatrix44 matrix;
- primaries.toXYZD50(&matrix);
- return Transform(matrix);
-}
-
-GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) {
+float FromLinear(ColorSpace::TransferID id, float v) {
switch (id) {
case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
// Should already be handled.
- NOTREACHED();
- case ColorSpace::TransferID::CUSTOM:
- // TODO(hubbe): Actually implement custom transfer functions.
- case ColorSpace::TransferID::RESERVED0:
- case ColorSpace::TransferID::RESERVED:
- case ColorSpace::TransferID::UNSPECIFIED:
- case ColorSpace::TransferID::UNKNOWN:
- // All unknown values default to BT709
-
- case ColorSpace::TransferID::BT709:
- case ColorSpace::TransferID::SMPTE170M:
- case ColorSpace::TransferID::BT2020_10:
- case ColorSpace::TransferID::BT2020_12:
- // BT709 is our "default" cause, so put the code after the switch
- // to avoid "control reaches end of non-void function" errors.
break;
- case ColorSpace::TransferID::GAMMA22:
- v = fmax(0.0f, v);
- return powf(v, 1.0f / 2.2f);
-
- case ColorSpace::TransferID::GAMMA28:
- v = fmax(0.0f, v);
- return powf(v, 1.0f / 2.8f);
-
- case ColorSpace::TransferID::SMPTE240M: {
- v = fmax(0.0f, v);
- float a = 1.11157219592173128753f;
- float b = 0.02282158552944503135f;
- if (v <= b) {
- return 4.0f * v;
- } else {
- return a * powf(v, 0.45f) - (a - 1.0f);
- }
- }
-
- case ColorSpace::TransferID::LINEAR:
- case ColorSpace::TransferID::LINEAR_HDR:
- return v;
-
case ColorSpace::TransferID::LOG:
if (v < 0.01f)
return 0.0f;
@@ -239,16 +78,6 @@ GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) {
}
}
- case ColorSpace::TransferID::IEC61966_2_1: { // SRGB
- v = fmax(0.0f, v);
- float a = 1.055f;
- float b = 0.0031308f;
- if (v < b) {
- return 12.92f * v;
- } else {
- return a * powf(v, 1.0f / 2.4f) - (a - 1.0f);
- }
- }
case ColorSpace::TransferID::SMPTEST2084: {
// Go from scRGB levels to 0-1.
v *= 80.0f / 10000.0f;
@@ -261,10 +90,6 @@ GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) {
return powf((c1 + c2 * powf(v, m1)) / (1.0f + c3 * powf(v, m1)), m2);
}
- case ColorSpace::TransferID::SMPTEST428_1:
- v = fmax(0.0f, v);
- return powf(48.0f * v + 52.37f, 1.0f / 2.6f);
-
// Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
case ColorSpace::TransferID::ARIB_STD_B67: {
const float a = 0.17883277f;
@@ -277,63 +102,16 @@ GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) {
return a * log(v - b) + c;
}
- // Chrome-specific values below
- case ColorSpace::TransferID::GAMMA24:
- v = fmax(0.0f, v);
- return powf(v, 1.0f / 2.4f);
- }
-
- v = fmax(0.0f, v);
- float a = 1.099296826809442f;
- float b = 0.018053968510807f;
- if (v <= b) {
- return 4.5f * v;
- } else {
- return a * powf(v, 0.45f) - (a - 1.0f);
+ default:
+ // Handled by SkColorSpaceTransferFn.
+ break;
}
+ NOTREACHED();
+ return 0;
}
-GFX_EXPORT float ToLinear(ColorSpace::TransferID id, float v) {
+float ToLinear(ColorSpace::TransferID id, float v) {
switch (id) {
- case ColorSpace::TransferID::CUSTOM:
- // TODO(hubbe): Actually implement custom transfer functions.
- case ColorSpace::TransferID::RESERVED0:
- case ColorSpace::TransferID::RESERVED:
- case ColorSpace::TransferID::UNSPECIFIED:
- case ColorSpace::TransferID::UNKNOWN:
- // All unknown values default to BT709
-
- case ColorSpace::TransferID::BT709:
- case ColorSpace::TransferID::SMPTE170M:
- case ColorSpace::TransferID::BT2020_10:
- case ColorSpace::TransferID::BT2020_12:
- // BT709 is our "default" cause, so put the code after the switch
- // to avoid "control reaches end of non-void function" errors.
- break;
-
- case ColorSpace::TransferID::GAMMA22:
- v = fmax(0.0f, v);
- return powf(v, 2.2f);
-
- case ColorSpace::TransferID::GAMMA28:
- v = fmax(0.0f, v);
- return powf(v, 2.8f);
-
- case ColorSpace::TransferID::SMPTE240M: {
- v = fmax(0.0f, v);
- float a = 1.11157219592173128753f;
- float b = 0.02282158552944503135f;
- if (v <= FromLinear(ColorSpace::TransferID::SMPTE240M, b)) {
- return v / 4.0f;
- } else {
- return powf((v + a - 1.0f) / a, 1.0f / 0.45f);
- }
- }
-
- case ColorSpace::TransferID::LINEAR:
- case ColorSpace::TransferID::LINEAR_HDR:
- return v;
-
case ColorSpace::TransferID::LOG:
if (v < 0.0f)
return 0.0f;
@@ -369,17 +147,6 @@ GFX_EXPORT float ToLinear(ColorSpace::TransferID id, float v) {
}
}
- case ColorSpace::TransferID::IEC61966_2_1: { // SRGB
- v = fmax(0.0f, v);
- float a = 1.055f;
- float b = 0.0031308f;
- if (v < FromLinear(ColorSpace::TransferID::IEC61966_2_1, b)) {
- return v / 12.92f;
- } else {
- return powf((v + a - 1.0f) / a, 2.4f);
- }
- }
-
case ColorSpace::TransferID::SMPTEST2084: {
v = fmax(0.0f, v);
float m1 = (2610.0f / 4096.0f) / 4.0f;
@@ -397,14 +164,6 @@ GFX_EXPORT float ToLinear(ColorSpace::TransferID id, float v) {
return v;
}
- case ColorSpace::TransferID::SMPTEST428_1:
- return (powf(v, 2.6f) - 52.37f) / 48.0f;
-
- // Chrome-specific values below
- case ColorSpace::TransferID::GAMMA24:
- v = fmax(0.0f, v);
- return powf(v, 2.4f);
-
case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
v = fmax(0.0f, v);
return fmin(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f);
@@ -423,16 +182,13 @@ GFX_EXPORT float ToLinear(ColorSpace::TransferID id, float v) {
}
return v_;
}
- }
- v = fmax(0.0f, v);
- float a = 1.099296826809442f;
- float b = 0.018053968510807f;
- if (v < FromLinear(ColorSpace::TransferID::BT709, b)) {
- return v / 4.5f;
- } else {
- return powf((v + a - 1.0f) / a, 1.0f / 0.45f);
+ default:
+ // Handled by SkColorSpaceTransferFn.
+ break;
}
+ NOTREACHED();
+ return 0;
}
GFX_EXPORT Transform GetTransferMatrix(ColorSpace::MatrixID id) {
@@ -619,12 +375,12 @@ class ColorTransformMatrix : public ColorTransformInternal {
class ColorTransformFromLinear : public ColorTransformInternal {
public:
- explicit ColorTransformFromLinear(ColorSpace::TransferID transfer)
- : transfer_(transfer) {
- // Map LINEAR_HDR to LINEAR for optimizations.
- if (transfer_ == ColorSpace::TransferID::LINEAR_HDR) {
+ explicit ColorTransformFromLinear(ColorSpace::TransferID transfer,
+ const SkColorSpaceTransferFn& fn,
+ bool fn_valid)
+ : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) {
+ if (transfer_ == ColorSpace::TransferID::LINEAR_HDR)
transfer_ = ColorSpace::TransferID::LINEAR;
- }
}
bool Prepend(ColorTransformInternal* prev) override {
return prev->Join(*this);
@@ -633,26 +389,36 @@ class ColorTransformFromLinear : public ColorTransformInternal {
bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; }
void transform(ColorTransform::TriStim* colors, size_t num) override {
- for (size_t i = 0; i < num; i++) {
- colors[i].set_x(FromLinear(transfer_, colors[i].x()));
- colors[i].set_y(FromLinear(transfer_, colors[i].y()));
- colors[i].set_z(FromLinear(transfer_, colors[i].z()));
+ if (fn_valid_) {
+ for (size_t i = 0; i < num; i++) {
+ colors[i].set_x(EvalSkTransferFn(fn_, colors[i].x()));
+ colors[i].set_y(EvalSkTransferFn(fn_, colors[i].y()));
+ colors[i].set_z(EvalSkTransferFn(fn_, colors[i].z()));
+ }
+ } else {
+ for (size_t i = 0; i < num; i++) {
+ colors[i].set_x(FromLinear(transfer_, colors[i].x()));
+ colors[i].set_y(FromLinear(transfer_, colors[i].y()));
+ colors[i].set_z(FromLinear(transfer_, colors[i].z()));
+ }
}
}
private:
friend class ColorTransformToLinear;
ColorSpace::TransferID transfer_;
+ SkColorSpaceTransferFn fn_;
+ bool fn_valid_ = false;
};
class ColorTransformToLinear : public ColorTransformInternal {
public:
- explicit ColorTransformToLinear(ColorSpace::TransferID transfer)
- : transfer_(transfer) {
- // Map LINEAR_HDR to LINEAR for optimizations.
- if (transfer_ == ColorSpace::TransferID::LINEAR_HDR) {
+ explicit ColorTransformToLinear(ColorSpace::TransferID transfer,
+ const SkColorSpaceTransferFn& fn,
+ bool fn_valid)
+ : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) {
+ if (transfer_ == ColorSpace::TransferID::LINEAR_HDR)
transfer_ = ColorSpace::TransferID::LINEAR;
- }
}
bool Prepend(ColorTransformInternal* prev) override {
@@ -689,7 +455,13 @@ class ColorTransformToLinear : public ColorTransformInternal {
}
void transform(ColorTransform::TriStim* colors, size_t num) override {
- if (transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) {
+ if (fn_valid_) {
+ for (size_t i = 0; i < num; i++) {
+ colors[i].set_x(EvalSkTransferFn(fn_, colors[i].x()));
+ colors[i].set_y(EvalSkTransferFn(fn_, colors[i].y()));
+ colors[i].set_z(EvalSkTransferFn(fn_, colors[i].z()));
+ }
+ } else if (transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) {
for (size_t i = 0; i < num; i++) {
ColorTransform::TriStim ret(ToLinear(transfer_, colors[i].x()),
ToLinear(transfer_, colors[i].y()),
@@ -715,6 +487,8 @@ class ColorTransformToLinear : public ColorTransformInternal {
private:
ColorSpace::TransferID transfer_;
+ SkColorSpaceTransferFn fn_;
+ bool fn_valid_ = false;
};
// BT2020 Constant Luminance is different than most other
@@ -870,17 +644,9 @@ class TransformBuilder {
class ColorSpaceToColorSpaceTransform {
public:
static Transform GetPrimaryTransform(const ColorSpace& c) {
- if (c.primaries_ == ColorSpace::PrimaryID::CUSTOM) {
- return Transform(c.custom_primary_matrix_[0], c.custom_primary_matrix_[1],
- c.custom_primary_matrix_[2], c.custom_primary_matrix_[3],
- c.custom_primary_matrix_[4], c.custom_primary_matrix_[5],
- c.custom_primary_matrix_[6], c.custom_primary_matrix_[7],
- c.custom_primary_matrix_[8], c.custom_primary_matrix_[9],
- c.custom_primary_matrix_[10],
- c.custom_primary_matrix_[11], 0.0f, 0.0f, 0.0f, 1.0f);
- } else {
- return GetPrimaryMatrix(c.primaries_);
- }
+ SkMatrix44 sk_matrix;
+ c.GetPrimaryMatrix(&sk_matrix);
+ return Transform(sk_matrix);
}
static void ColorSpaceToColorSpace(ColorSpace from,
@@ -923,11 +689,18 @@ class ColorSpaceToColorSpaceTransform {
// TODO(hubbe): shrink gamuts here (never stretch gamuts)
}
+
builder->Append(base::MakeUnique<ColorTransformMatrix>(
GetRangeAdjustMatrix(from.range_, from.matrix_)));
+
builder->Append(base::MakeUnique<ColorTransformMatrix>(
Invert(GetTransferMatrix(from.matrix_))));
- builder->Append(base::MakeUnique<ColorTransformToLinear>(from.transfer_));
+
+ SkColorSpaceTransferFn to_linear_fn;
+ bool to_linear_fn_valid = from.GetTransferFunction(&to_linear_fn);
+ builder->Append(base::MakeUnique<ColorTransformToLinear>(
+ from.transfer_, to_linear_fn, to_linear_fn_valid));
+
if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
// BT2020 CL is a special case.
builder->Append(base::MakeUnique<ColorTransformFromBT2020CL>());
@@ -942,9 +715,14 @@ class ColorSpaceToColorSpaceTransform {
builder->Append(base::MakeUnique<ColorTransformToBT2020CL>());
}
- builder->Append(base::MakeUnique<ColorTransformFromLinear>(to.transfer_));
+ SkColorSpaceTransferFn from_linear_fn;
+ bool from_linear_fn_valid = to.GetInverseTransferFunction(&from_linear_fn);
+ builder->Append(base::MakeUnique<ColorTransformFromLinear>(
+ to.transfer_, from_linear_fn, from_linear_fn_valid));
+
builder->Append(
base::MakeUnique<ColorTransformMatrix>(GetTransferMatrix(to.matrix_)));
+
builder->Append(base::MakeUnique<ColorTransformMatrix>(
Invert(GetRangeAdjustMatrix(to.range_, to.matrix_))));
}
@@ -1040,4 +818,33 @@ std::unique_ptr<ColorTransform> ColorTransform::NewColorTransform(
return builder.GetTransform();
}
+// static
+float ColorTransform::ToLinearForTesting(ColorSpace::TransferID transfer,
+ float v) {
+ ColorSpace space(ColorSpace::PrimaryID::BT709, transfer,
+ ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
+ SkColorSpaceTransferFn to_linear_fn;
+ bool to_linear_fn_valid = space.GetTransferFunction(&to_linear_fn);
+ ColorTransformToLinear to_linear_transform(transfer, to_linear_fn,
+ to_linear_fn_valid);
+ TriStim color(v, v, v);
+ to_linear_transform.transform(&color, 1);
+ return color.x();
+}
+
+// static
+float ColorTransform::FromLinearForTesting(ColorSpace::TransferID transfer,
+ float v) {
+ ColorSpace space(ColorSpace::PrimaryID::BT709, transfer,
+ ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
+ SkColorSpaceTransferFn from_linear_fn;
+ bool from_linear_fn_valid = space.GetInverseTransferFunction(&from_linear_fn);
+
+ ColorTransformFromLinear from_linear_transform(transfer, from_linear_fn,
+ from_linear_fn_valid);
+ TriStim color(v, v, v);
+ from_linear_transform.transform(&color, 1);
+ return color.x();
+}
+
} // namespace gfx
« no previous file with comments | « ui/gfx/color_transform.h ('k') | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698