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

Unified Diff: ui/gfx/color_space.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_space.h ('k') | ui/gfx/color_transform.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/color_space.cc
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc
index 077e92759050d2de9fd69bcbfea80799014a7fd5..62ddbe0679d8e94430fa73e9213fbce48c6e8f26 100644
--- a/ui/gfx/color_space.cc
+++ b/ui/gfx/color_space.cc
@@ -13,6 +13,26 @@
namespace gfx {
+namespace {
+
+SkColorSpaceTransferFn InvertTransferFn(SkColorSpaceTransferFn fn) {
+ SkColorSpaceTransferFn fn_inv = {0};
+ if (fn.fA > 0 && fn.fG > 0) {
+ double a_to_the_g = pow(fn.fA, fn.fG);
+ fn_inv.fA = 1.f / a_to_the_g;
+ fn_inv.fB = -fn.fE / a_to_the_g;
+ fn_inv.fG = 1.f / fn.fG;
+ }
+ fn_inv.fD = fn.fC * fn.fD + fn.fF;
+ fn_inv.fE = -fn.fB / fn.fA;
+ if (fn.fC != 0) {
+ fn_inv.fC = 1.f / fn.fC;
+ fn_inv.fF = -fn.fF / fn.fC;
+ }
+ return fn_inv;
+}
+};
+
ColorSpace::PrimaryID ColorSpace::PrimaryIDFromInt(int primary_id) {
if (primary_id < 0 || primary_id > static_cast<int>(PrimaryID::LAST))
return PrimaryID::UNKNOWN;
@@ -40,9 +60,7 @@ ColorSpace::MatrixID ColorSpace::MatrixIDFromInt(int matrix_id) {
return static_cast<MatrixID>(matrix_id);
}
-ColorSpace::ColorSpace() {
- memset(custom_primary_matrix_, 0, sizeof(custom_primary_matrix_));
-}
+ColorSpace::ColorSpace() {}
ColorSpace::ColorSpace(PrimaryID primaries,
TransferID transfer,
@@ -51,19 +69,13 @@ ColorSpace::ColorSpace(PrimaryID primaries,
: primaries_(primaries),
transfer_(transfer),
matrix_(matrix),
- range_(range) {
- memset(custom_primary_matrix_, 0, sizeof(custom_primary_matrix_));
- // TODO: Set profile_id_
-}
+ range_(range) {}
ColorSpace::ColorSpace(int primaries, int transfer, int matrix, RangeID range)
: primaries_(PrimaryIDFromInt(primaries)),
transfer_(TransferIDFromInt(transfer)),
matrix_(MatrixIDFromInt(matrix)),
- range_(range) {
- memset(custom_primary_matrix_, 0, sizeof(custom_primary_matrix_));
- // TODO: Set profile_id_
-}
+ range_(range) {}
ColorSpace::ColorSpace(const ColorSpace& other)
: primaries_(other.primaries_),
@@ -71,19 +83,23 @@ ColorSpace::ColorSpace(const ColorSpace& other)
matrix_(other.matrix_),
range_(other.range_),
icc_profile_id_(other.icc_profile_id_),
- sk_color_space_(other.sk_color_space_) {
- memcpy(custom_primary_matrix_, other.custom_primary_matrix_,
- sizeof(custom_primary_matrix_));
+ icc_profile_sk_color_space_(other.icc_profile_sk_color_space_) {
+ if (transfer_ == TransferID::CUSTOM) {
+ memcpy(custom_transfer_params_, other.custom_transfer_params_,
+ sizeof(custom_transfer_params_));
+ }
+ if (primaries_ == PrimaryID::CUSTOM) {
+ memcpy(custom_primary_matrix_, other.custom_primary_matrix_,
+ sizeof(custom_primary_matrix_));
+ }
}
ColorSpace::~ColorSpace() = default;
// static
ColorSpace ColorSpace::CreateSRGB() {
- ColorSpace result(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB,
+ return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB,
RangeID::FULL);
- result.sk_color_space_ = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
- return result;
}
// static
@@ -124,6 +140,10 @@ bool ColorSpace::operator==(const ColorSpace& other) const {
memcmp(custom_primary_matrix_, other.custom_primary_matrix_,
sizeof(custom_primary_matrix_)))
return false;
+ if (transfer_ == TransferID::CUSTOM &&
+ memcmp(custom_transfer_params_, other.custom_transfer_params_,
+ sizeof(custom_transfer_params_)))
+ return false;
return true;
}
@@ -163,9 +183,70 @@ bool ColorSpace::operator<(const ColorSpace& other) const {
if (primary_result > 0)
return false;
}
+ if (transfer_ == TransferID::CUSTOM) {
+ int transfer_result =
+ memcmp(custom_transfer_params_, other.custom_transfer_params_,
+ sizeof(custom_transfer_params_));
+ if (transfer_result < 0)
+ return true;
+ if (transfer_result > 0)
+ return false;
+ }
return false;
}
+sk_sp<SkColorSpace> ColorSpace::ToSkColorSpace() const {
+ // If we got a specific SkColorSpace from the ICCProfile that this color space
+ // was created from, use that.
+ if (icc_profile_sk_color_space_)
+ return icc_profile_sk_color_space_;
+
+ // Unspecified color spaces correspond to the null SkColorSpace.
+ if (primaries_ == PrimaryID::UNSPECIFIED ||
+ transfer_ == TransferID::UNSPECIFIED) {
+ return nullptr;
+ }
+
+ // Handle only full-range RGB spaces.
+ if (matrix_ != MatrixID::RGB) {
+ DLOG(ERROR) << "Not creating non-RGB SkColorSpace";
+ return nullptr;
+ }
+ if (range_ != RangeID::FULL) {
+ DLOG(ERROR) << "Not creating non-full-range SkColorSpace";
+ return nullptr;
+ }
+
+ // Use the named SRGB and linear-SRGB instead of the generic constructors.
+ if (primaries_ == PrimaryID::BT709) {
+ if (transfer_ == TransferID::IEC61966_2_1)
+ return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
+ if (transfer_ == TransferID::LINEAR || transfer_ == TransferID::LINEAR_HDR)
+ return SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
+ }
+
+ SkMatrix44 to_xyz_d50;
+ GetPrimaryMatrix(&to_xyz_d50);
+
+ // Use the named sRGB and linear transfer functions.
+ if (transfer_ == TransferID::IEC61966_2_1) {
+ return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
+ to_xyz_d50);
+ }
+ if (transfer_ == TransferID::LINEAR || transfer_ == TransferID::LINEAR_HDR) {
+ return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ to_xyz_d50);
+ }
+
+ // Use the parametric transfer function if no other option is available.
+ SkColorSpaceTransferFn fn;
+ if (!GetTransferFunction(&fn)) {
+ DLOG(ERROR) << "Failed to parameterize transfer function for SkColorSpace";
+ return nullptr;
+ }
+ return SkColorSpace::MakeRGB(fn, to_xyz_d50);
+}
+
ColorSpace ColorSpace::FromSkColorSpace(
const sk_sp<SkColorSpace>& sk_color_space) {
if (!sk_color_space)
@@ -181,4 +262,222 @@ ColorSpace ColorSpace::FromSkColorSpace(
return icc_profile.GetColorSpace();
}
+void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const {
+ SkColorSpacePrimaries primaries = {0};
+ switch (primaries_) {
+ case ColorSpace::PrimaryID::CUSTOM:
+ to_XYZD50->set3x3RowMajorf(custom_primary_matrix_);
+ return;
+
+ 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;
+ }
+ primaries.toXYZD50(to_XYZD50);
+}
+
+bool ColorSpace::GetTransferFunction(SkColorSpaceTransferFn* fn) const {
+ // Default to F(x) = pow(x, 1)
+ fn->fA = 1;
+ fn->fB = 0;
+ fn->fC = 1;
+ fn->fD = 0;
+ fn->fE = 0;
+ fn->fF = 0;
+ fn->fG = 1;
+
+ switch (transfer_) {
+ case ColorSpace::TransferID::CUSTOM:
+ fn->fA = custom_transfer_params_[0];
+ fn->fB = custom_transfer_params_[1];
+ fn->fC = custom_transfer_params_[2];
+ fn->fD = custom_transfer_params_[3];
+ fn->fE = custom_transfer_params_[4];
+ fn->fF = custom_transfer_params_[5];
+ fn->fG = custom_transfer_params_[6];
+ return true;
+ case ColorSpace::TransferID::LINEAR:
+ case ColorSpace::TransferID::LINEAR_HDR:
+ return true;
+ case ColorSpace::TransferID::GAMMA22:
+ fn->fG = 2.2f;
+ return true;
+ case ColorSpace::TransferID::GAMMA24:
+ fn->fG = 2.4f;
+ return true;
+ case ColorSpace::TransferID::GAMMA28:
+ fn->fG = 2.8f;
+ return true;
+ 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:
+ fn->fA = 0.909672431050f;
+ fn->fB = 0.090327568950f;
+ fn->fC = 0.222222222222f;
+ fn->fD = 0.081242862158f;
+ fn->fG = 2.222222222222f;
+ return true;
+ case ColorSpace::TransferID::SMPTE240M:
+ fn->fA = 0.899626676224f;
+ fn->fB = 0.100373323776f;
+ fn->fC = 0.250000000000f;
+ fn->fD = 0.091286342118f;
+ fn->fG = 2.222222222222f;
+ return true;
+ case ColorSpace::TransferID::IEC61966_2_1:
+ fn->fA = 0.947867345704f;
+ fn->fB = 0.052132654296f;
+ fn->fC = 0.077399380805f;
+ fn->fD = 0.040449937172f;
+ fn->fG = 2.400000000000f;
+ return true;
+ case ColorSpace::TransferID::SMPTEST428_1:
+ fn->fA = 0.225615407568f;
+ fn->fE = -1.091041666667f;
+ fn->fG = 2.600000000000f;
+ return true;
+ case ColorSpace::TransferID::IEC61966_2_4:
+ // This could potentially be represented the same as IEC61966_2_1, but
+ // it handles negative values differently.
+ break;
+ case ColorSpace::TransferID::ARIB_STD_B67:
+ case ColorSpace::TransferID::BT1361_ECG:
+ case ColorSpace::TransferID::LOG:
+ case ColorSpace::TransferID::LOG_SQRT:
+ case ColorSpace::TransferID::SMPTEST2084:
+ case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
+ break;
+ }
+
+ return false;
+}
+
+bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const {
+ if (!GetTransferFunction(fn))
+ return false;
+ *fn = InvertTransferFn(*fn);
+ return true;
+}
+
} // namespace gfx
« no previous file with comments | « ui/gfx/color_space.h ('k') | ui/gfx/color_transform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698