Commit ac3c37d5 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Make ICCProfile no longer store a ColorSpace directly

Make ICCProfile store the primaries and transfer function that it
read or computed directly, rather than storing a ColorSpace object.
Construct the ColorSpace object when requested, rather than storing it.

Store an approximate (or guessed) primary matrix and transfer function
for ICC_BASED ColorSpace objects. When computing the parametric
approximation of an ICC_BASED ColorSpace object, use these values
directly, rather than having to look them up from original ICCProfile.

Bug: 766736
Change-Id: I21d6dfaa38706f814f6c9dd54517806e99366113
Reviewed-on: https://chromium-review.googlesource.com/745311Reviewed-by: default avatarFredrik Hubinette <hubbe@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512958}
parent 5768afb3
This diff is collapsed.
...@@ -53,7 +53,8 @@ class COLOR_SPACE_EXPORT ColorSpace { ...@@ -53,7 +53,8 @@ class COLOR_SPACE_EXPORT ColorSpace {
CUSTOM, CUSTOM,
// For color spaces defined by an ICC profile which cannot be represented // For color spaces defined by an ICC profile which cannot be represented
// parametrically. Any ColorTransform using this color space will use the // parametrically. Any ColorTransform using this color space will use the
// ICC profile directly to compute a transform LUT. // ICC profile directly to compute a transform LUT. A parametric
// approximation of these primaries is stored in |custom_primary_matrix_|.
ICC_BASED, ICC_BASED,
LAST = ICC_BASED, LAST = ICC_BASED,
}; };
...@@ -89,7 +90,8 @@ class COLOR_SPACE_EXPORT ColorSpace { ...@@ -89,7 +90,8 @@ class COLOR_SPACE_EXPORT ColorSpace {
LINEAR_HDR, LINEAR_HDR,
// A parametric transfer function defined by |custom_transfer_params_|. // A parametric transfer function defined by |custom_transfer_params_|.
CUSTOM, CUSTOM,
// See PrimaryID::ICC_BASED. // See PrimaryID::ICC_BASED. A parametric approximation of the transfer
// function is stored in |custom_transfer_params_|.
ICC_BASED, ICC_BASED,
LAST = ICC_BASED, LAST = ICC_BASED,
}; };
...@@ -171,9 +173,6 @@ class COLOR_SPACE_EXPORT ColorSpace { ...@@ -171,9 +173,6 @@ class COLOR_SPACE_EXPORT ColorSpace {
// Returns true if the encoded values can be outside of the 0.0-1.0 range. // Returns true if the encoded values can be outside of the 0.0-1.0 range.
bool FullRangeEncodedValues() const; bool FullRangeEncodedValues() const;
// Returns true if this color space can be represented parametrically.
bool IsParametric() const;
// Return a parametric approximation of this color space (if it is not already // Return a parametric approximation of this color space (if it is not already
// parametric). // parametric).
ColorSpace GetParametricApproximation() const; ColorSpace GetParametricApproximation() const;
...@@ -208,6 +207,7 @@ class COLOR_SPACE_EXPORT ColorSpace { ...@@ -208,6 +207,7 @@ class COLOR_SPACE_EXPORT ColorSpace {
void GetRangeAdjustMatrix(SkMatrix44* matrix) const; void GetRangeAdjustMatrix(SkMatrix44* matrix) const;
private: private:
void SetCustomPrimaries(const SkMatrix44& to_XYZD50);
void SetCustomTransferFunction(const SkColorSpaceTransferFn& fn); void SetCustomTransferFunction(const SkColorSpaceTransferFn& fn);
// Returns true if the transfer function is defined by an // Returns true if the transfer function is defined by an
...@@ -219,12 +219,12 @@ class COLOR_SPACE_EXPORT ColorSpace { ...@@ -219,12 +219,12 @@ class COLOR_SPACE_EXPORT ColorSpace {
MatrixID matrix_ = MatrixID::INVALID; MatrixID matrix_ = MatrixID::INVALID;
RangeID range_ = RangeID::INVALID; RangeID range_ = RangeID::INVALID;
// Only used if primaries_ is PrimaryID::CUSTOM. // Only used if primaries_ is PrimaryID::CUSTOM or PrimaryID::ICC_BASED.
float custom_primary_matrix_[9] = {0, 0, 0, 0, 0, 0, 0, 0}; float custom_primary_matrix_[9] = {0, 0, 0, 0, 0, 0, 0, 0};
// Only used if transfer_ is TransferID::CUSTOM. This array consists of the A // Only used if transfer_ is TransferID::CUSTOM or PrimaryID::ICC_BASED.
// through G entries of the SkColorSpaceTransferFn structure in alphabetical // This array consists of the A through G entries of the
// order. // SkColorSpaceTransferFn structure in alphabetical order.
float custom_transfer_params_[7] = {0, 0, 0, 0, 0, 0, 0}; float custom_transfer_params_[7] = {0, 0, 0, 0, 0, 0, 0};
// This is used to look up the ICCProfile from which this ColorSpace was // This is used to look up the ICCProfile from which this ColorSpace was
......
...@@ -252,8 +252,9 @@ TEST(SimpleColorSpace, ICCProfileOnlyColorSpin) { ...@@ -252,8 +252,9 @@ TEST(SimpleColorSpace, ICCProfileOnlyColorSpin) {
const float kEpsilon = 2.5f / 255.f; const float kEpsilon = 2.5f / 255.f;
ICCProfile icc_profile = ICCProfileForTestingNoAnalyticTrFn(); ICCProfile icc_profile = ICCProfileForTestingNoAnalyticTrFn();
ColorSpace icc_space = icc_profile.GetColorSpace(); ColorSpace icc_space = icc_profile.GetColorSpace();
ColorSpace colorspin = ColorSpace colorspin = ICCProfileForTestingColorSpin()
ICCProfileForTestingColorSpin().GetParametricColorSpace(); .GetColorSpace()
.GetParametricApproximation();
ColorTransform::TriStim input_value(0.25f, 0.5f, 0.75f); ColorTransform::TriStim input_value(0.25f, 0.5f, 0.75f);
ColorTransform::TriStim transformed_value = input_value; ColorTransform::TriStim transformed_value = input_value;
......
...@@ -54,17 +54,6 @@ class ICCProfileCache { ...@@ -54,17 +54,6 @@ class ICCProfileCache {
if (!icc_profile->id_) if (!icc_profile->id_)
icc_profile->id_ = next_unused_id_++; icc_profile->id_ = next_unused_id_++;
// Ensure that GetColorSpace() point back to this ICCProfile.
gfx::ColorSpace& color_space = icc_profile->color_space_;
color_space.icc_profile_id_ = icc_profile->id_;
// Ensure that the GetParametricColorSpace() point back to this ICCProfile
// only if the parametric version is accurate.
if (color_space.primaries_ != ColorSpace::PrimaryID::ICC_BASED &&
color_space.transfer_ != ColorSpace::TransferID::ICC_BASED) {
icc_profile->parametric_color_space_.icc_profile_id_ = icc_profile->id_;
}
Entry entry; Entry entry;
entry.icc_profile = *icc_profile; entry.icc_profile = *icc_profile;
id_to_icc_profile_mru_.Put(icc_profile->id_, entry); id_to_icc_profile_mru_.Put(icc_profile->id_, entry);
...@@ -201,76 +190,69 @@ static base::LazyInstance<ICCProfileCache>::DestructorAtExit g_cache = ...@@ -201,76 +190,69 @@ static base::LazyInstance<ICCProfileCache>::DestructorAtExit g_cache =
} // namespace } // namespace
// static ICCProfile::AnalyzeResult ICCProfile::Initialize() {
ICCProfile::AnalyzeResult ICCProfile::ExtractColorSpaces( // Start out with no parametric data.
const std::vector<char>& data, primaries_ = gfx::ColorSpace::PrimaryID::INVALID;
gfx::ColorSpace* parametric_color_space, transfer_ = gfx::ColorSpace::TransferID::INVALID;
float* parametric_tr_fn_max_error,
sk_sp<SkColorSpace>* useable_sk_color_space) {
// Initialize the output parameters as invalid.
*parametric_color_space = gfx::ColorSpace();
*parametric_tr_fn_max_error = 0;
*useable_sk_color_space = nullptr;
// Parse the profile and attempt to create a SkColorSpaceXform out of it. // Parse the profile and attempt to create a SkColorSpaceXform out of it.
sk_sp<SkColorSpace> sk_srgb_color_space = SkColorSpace::MakeSRGB(); sk_sp<SkColorSpace> sk_srgb_color_space = SkColorSpace::MakeSRGB();
sk_sp<SkICC> sk_icc = SkICC::Make(data.data(), data.size()); sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size());
if (!sk_icc) { if (!sk_icc) {
DLOG(ERROR) << "Failed to parse ICC profile to SkICC."; DLOG(ERROR) << "Failed to parse ICC profile to SkICC.";
return kICCFailedToParse; return kICCFailedToParse;
} }
sk_sp<SkColorSpace> sk_icc_color_space = sk_color_space_ = SkColorSpace::MakeICC(data_.data(), data_.size());
SkColorSpace::MakeICC(data.data(), data.size()); if (!sk_color_space_) {
if (!sk_icc_color_space) {
DLOG(ERROR) << "Failed to parse ICC profile to SkColorSpace."; DLOG(ERROR) << "Failed to parse ICC profile to SkColorSpace.";
return kICCFailedToExtractSkColorSpace; return kICCFailedToExtractSkColorSpace;
} }
// If our SkColorSpace representation is sRGB then return that.
if (SkColorSpace::Equals(sk_srgb_color_space.get(), sk_color_space_.get())) {
primaries_ = gfx::ColorSpace::PrimaryID::BT709;
transfer_ = gfx::ColorSpace::TransferID::IEC61966_2_1;
return kICCExtractedSRGBColorSpace;
}
std::unique_ptr<SkColorSpaceXform> sk_color_space_xform = std::unique_ptr<SkColorSpaceXform> sk_color_space_xform =
SkColorSpaceXform::New(sk_srgb_color_space.get(), SkColorSpaceXform::New(sk_srgb_color_space.get(), sk_color_space_.get());
sk_icc_color_space.get());
if (!sk_color_space_xform) { if (!sk_color_space_xform) {
DLOG(ERROR) << "Parsed ICC profile but can't create SkColorSpaceXform."; DLOG(ERROR) << "Parsed ICC profile but can't create SkColorSpaceXform.";
return kICCFailedToCreateXform; return kICCFailedToCreateXform;
} }
// Because this SkColorSpace can be used to construct a transform, mark it // Because this SkColorSpace can be used to construct a transform, we can use
// as "useable". Mark the "best approximation" as sRGB to start. // it to create a LUT based color transform, at the very least. If we fail to
*useable_sk_color_space = sk_icc_color_space; // get any better approximation, we'll use sRGB as our approximation.
*parametric_color_space = ColorSpace::CreateSRGB(); primaries_ = ColorSpace::PrimaryID::ICC_BASED;
transfer_ = ColorSpace::TransferID::ICC_BASED;
// If our SkColorSpace representation is sRGB then return that. ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_);
if (SkColorSpace::Equals(sk_srgb_color_space.get(), ColorSpace::CreateSRGB().GetTransferFunction(&transfer_fn_);
sk_icc_color_space.get())) {
return kICCExtractedSRGBColorSpace;
}
// A primary matrix is required for our parametric approximation. // A primary matrix is required for our parametric representations. Use it if
// it exists.
SkMatrix44 to_XYZD50_matrix; SkMatrix44 to_XYZD50_matrix;
if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) { if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) {
DLOG(ERROR) << "Failed to extract ICC profile primary matrix."; DLOG(ERROR) << "Failed to extract ICC profile primary matrix.";
return kICCFailedToExtractMatrix; return kICCFailedToExtractMatrix;
} }
primaries_ = ColorSpace::PrimaryID::CUSTOM;
to_XYZD50_ = to_XYZD50_matrix;
// Try to directly extract a numerical transfer function. // Try to directly extract a numerical transfer function. Use it if it
// exists.
SkColorSpaceTransferFn exact_tr_fn; SkColorSpaceTransferFn exact_tr_fn;
if (sk_icc->isNumericalTransferFn(&exact_tr_fn)) { if (sk_icc->isNumericalTransferFn(&exact_tr_fn)) {
*parametric_color_space = transfer_ = ColorSpace::TransferID::CUSTOM;
gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, exact_tr_fn); transfer_fn_ = exact_tr_fn;
return kICCExtractedMatrixAndAnalyticTrFn; return kICCExtractedMatrixAndAnalyticTrFn;
} }
// If we fail to get a transfer function, use the sRGB transfer function,
// and return false to indicate that the gfx::ColorSpace isn't accurate, but
// we can construct accurate LUT transforms using the underlying
// SkColorSpace.
*parametric_color_space = gfx::ColorSpace::CreateCustom(
to_XYZD50_matrix, ColorSpace::TransferID::IEC61966_2_1);
// Attempt to fit a parametric transfer function to the table data in the // Attempt to fit a parametric transfer function to the table data in the
// profile. // profile.
SkColorSpaceTransferFn approx_tr_fn; SkColorSpaceTransferFn approx_tr_fn;
if (!SkApproximateTransferFn(sk_icc, parametric_tr_fn_max_error, if (!SkApproximateTransferFn(sk_icc, &transfer_fn_error_, &approx_tr_fn)) {
&approx_tr_fn)) {
DLOG(ERROR) << "Failed approximate transfer function."; DLOG(ERROR) << "Failed approximate transfer function.";
return kICCFailedToConvergeToApproximateTrFn; return kICCFailedToConvergeToApproximateTrFn;
} }
...@@ -278,16 +260,16 @@ ICCProfile::AnalyzeResult ICCProfile::ExtractColorSpaces( ...@@ -278,16 +260,16 @@ ICCProfile::AnalyzeResult ICCProfile::ExtractColorSpaces(
// If this converged, but has too high error, use the sRGB transfer function // If this converged, but has too high error, use the sRGB transfer function
// from above. // from above.
const float kMaxError = 2.f / 256.f; const float kMaxError = 2.f / 256.f;
if (*parametric_tr_fn_max_error >= kMaxError) { if (transfer_fn_error_ >= kMaxError) {
DLOG(ERROR) << "Failed to accurately approximate transfer function, error: " DLOG(ERROR) << "Failed to accurately approximate transfer function, error: "
<< 256.f * (*parametric_tr_fn_max_error) << "/256"; << 256.f * transfer_fn_error_ << "/256";
return kICCFailedToApproximateTrFnAccurately; return kICCFailedToApproximateTrFnAccurately;
}; };
// If the error is sufficiently low, declare that the approximation is // If the error is sufficiently low, declare that the approximation is
// accurate. // accurate.
*parametric_color_space = transfer_ = ColorSpace::TransferID::CUSTOM;
gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, approx_tr_fn); transfer_fn_ = approx_tr_fn;
return kICCExtractedMatrixAndApproximatedTrFn; return kICCExtractedMatrixAndApproximatedTrFn;
} }
...@@ -346,14 +328,28 @@ const std::vector<char>& ICCProfile::GetData() const { ...@@ -346,14 +328,28 @@ const std::vector<char>& ICCProfile::GetData() const {
return data_; return data_;
} }
const ColorSpace& ICCProfile::GetColorSpace() const { ColorSpace ICCProfile::GetColorSpace() const {
g_cache.Get().TouchEntry(*this); g_cache.Get().TouchEntry(*this);
return color_space_;
}
const ColorSpace& ICCProfile::GetParametricColorSpace() const { ColorSpace color_space;
g_cache.Get().TouchEntry(*this); if (!IsValid())
return parametric_color_space_; return color_space;
color_space.icc_profile_id_ = id_;
color_space.icc_profile_sk_color_space_ = sk_color_space_;
DCHECK(color_space.icc_profile_sk_color_space_);
color_space.matrix_ = ColorSpace::MatrixID::RGB;
color_space.range_ = ColorSpace::RangeID::FULL;
if (primaries_ == ColorSpace::PrimaryID::CUSTOM ||
primaries_ == ColorSpace::PrimaryID::ICC_BASED) {
color_space.SetCustomPrimaries(to_XYZD50_);
}
color_space.primaries_ = primaries_;
if (transfer_ == ColorSpace::TransferID::CUSTOM ||
transfer_ == ColorSpace::TransferID::ICC_BASED) {
color_space.SetCustomTransferFunction(transfer_fn_);
}
color_space.transfer_ = transfer_;
return color_space;
} }
// static // static
...@@ -376,34 +372,7 @@ void ICCProfile::ComputeColorSpaceAndCache() { ...@@ -376,34 +372,7 @@ void ICCProfile::ComputeColorSpaceAndCache() {
return; return;
// Parse the ICC profile // Parse the ICC profile
sk_sp<SkColorSpace> useable_sk_color_space; analyze_result_ = Initialize();
analyze_result_ =
ExtractColorSpaces(data_, &parametric_color_space_,
&parametric_tr_fn_error_, &useable_sk_color_space);
switch (analyze_result_) {
case kICCExtractedSRGBColorSpace:
case kICCExtractedMatrixAndAnalyticTrFn:
case kICCExtractedMatrixAndApproximatedTrFn:
// Successfully and accurately extracted color space.
color_space_ = parametric_color_space_;
break;
case kICCFailedToExtractRawTrFn:
case kICCFailedToExtractMatrix:
case kICCFailedToConvergeToApproximateTrFn:
case kICCFailedToApproximateTrFnAccurately:
// Successfully but extracted a color space, but it isn't accurate enough.
color_space_ = ColorSpace(ColorSpace::PrimaryID::ICC_BASED,
ColorSpace::TransferID::ICC_BASED);
color_space_.icc_profile_sk_color_space_ = useable_sk_color_space;
break;
case kICCFailedToParse:
case kICCFailedToExtractSkColorSpace:
case kICCFailedToCreateXform:
// Can't even use this color space as a LUT.
DCHECK(!parametric_color_space_.IsValid());
color_space_ = parametric_color_space_;
break;
}
// Add to the cache. // Add to the cache.
g_cache.Get().InsertAndSetIdIfNeeded(this); g_cache.Get().InsertAndSetIdIfNeeded(this);
...@@ -429,7 +398,7 @@ void ICCProfile::HistogramDisplay(int64_t display_id) const { ...@@ -429,7 +398,7 @@ void ICCProfile::HistogramDisplay(int64_t display_id) const {
if (nonlinear_fit_converged) { if (nonlinear_fit_converged) {
UMA_HISTOGRAM_CUSTOM_COUNTS( UMA_HISTOGRAM_CUSTOM_COUNTS(
"Blink.ColorSpace.Destination.NonlinearFitError", "Blink.ColorSpace.Destination.NonlinearFitError",
static_cast<int>(parametric_tr_fn_error_ * 255), 0, 127, 16); static_cast<int>(transfer_fn_error_ * 255), 0, 127, 16);
} }
} }
......
...@@ -52,12 +52,7 @@ class COLOR_SPACE_EXPORT ICCProfile { ...@@ -52,12 +52,7 @@ class COLOR_SPACE_EXPORT ICCProfile {
// Return a ColorSpace that references this ICCProfile. ColorTransforms // Return a ColorSpace that references this ICCProfile. ColorTransforms
// created using this ColorSpace will match this ICCProfile precisely. // created using this ColorSpace will match this ICCProfile precisely.
const ColorSpace& GetColorSpace() const; ColorSpace GetColorSpace() const;
// Return a ColorSpace that is the best parametric approximation of this
// ICCProfile. The resulting ColorSpace will reference this ICCProfile only
// if the parametric approximation is almost exact.
const ColorSpace& GetParametricColorSpace() const;
const std::vector<char>& GetData() const; const std::vector<char>& GetData() const;
...@@ -103,12 +98,7 @@ class COLOR_SPACE_EXPORT ICCProfile { ...@@ -103,12 +98,7 @@ class COLOR_SPACE_EXPORT ICCProfile {
size_t size, size_t size,
uint64_t id); uint64_t id);
static AnalyzeResult ExtractColorSpaces( AnalyzeResult Initialize();
const std::vector<char>& data,
gfx::ColorSpace* parametric_color_space,
float* parametric_tr_fn_max_error,
sk_sp<SkColorSpace>* useable_sk_color_space);
void ComputeColorSpaceAndCache(); void ComputeColorSpaceAndCache();
// This globally identifies this ICC profile. It is used to look up this ICC // This globally identifies this ICC profile. It is used to look up this ICC
...@@ -120,18 +110,21 @@ class COLOR_SPACE_EXPORT ICCProfile { ...@@ -120,18 +110,21 @@ class COLOR_SPACE_EXPORT ICCProfile {
// The result of attepting to extract a color space from the color profile. // The result of attepting to extract a color space from the color profile.
AnalyzeResult analyze_result_ = kICCFailedToParse; AnalyzeResult analyze_result_ = kICCFailedToParse;
// |color_space| always links back to this ICC profile, and its SkColorSpace // Results of Skia parsing the ICC profile data.
// is always equal to the SkColorSpace created from this ICCProfile. sk_sp<SkColorSpace> sk_color_space_;
gfx::ColorSpace color_space_;
// The best-fit parametric primaries.
gfx::ColorSpace::PrimaryID primaries_;
SkMatrix44 to_XYZD50_;
// |parametric_color_space_| will only link back to this ICC profile if it // The best-fit parametric transfer function.
// is accurate, and its SkColorSpace will always be parametrically created. gfx::ColorSpace::TransferID transfer_;
gfx::ColorSpace parametric_color_space_; SkColorSpaceTransferFn transfer_fn_;
// The L-infinity error of the parametric color space fit. This is undefined // The L-infinity error of the parametric color space fit. This is undefined
// unless |analyze_result_| is kICCFailedToApproximateTrFnAccurately or // unless |analyze_result_| is kICCFailedToApproximateTrFnAccurately or
// kICCExtractedMatrixAndApproximatedTrFn. // kICCExtractedMatrixAndApproximatedTrFn.
float parametric_tr_fn_error_ = -1; float transfer_fn_error_ = 0;
FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, BT709toSRGBICC); FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, BT709toSRGBICC);
FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace); FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace);
......
...@@ -32,8 +32,12 @@ TEST(ICCProfile, SRGB) { ...@@ -32,8 +32,12 @@ TEST(ICCProfile, SRGB) {
EXPECT_EQ(icc_profile.GetColorSpace().ToSkColorSpace().get(), EXPECT_EQ(icc_profile.GetColorSpace().ToSkColorSpace().get(),
sk_color_space.get()); sk_color_space.get());
// The parametric generating code should recognize that this is SRGB. // The parametric generating code should recognize that this is SRGB.
EXPECT_EQ(icc_profile.GetParametricColorSpace(), ColorSpace::CreateSRGB()); EXPECT_EQ(icc_profile.GetColorSpace().GetParametricApproximation(),
EXPECT_EQ(icc_profile.GetParametricColorSpace().ToSkColorSpace().get(), ColorSpace::CreateSRGB());
EXPECT_EQ(icc_profile.GetColorSpace()
.GetParametricApproximation()
.ToSkColorSpace()
.get(),
sk_color_space.get()); sk_color_space.get());
// The generated color space should recognize that this is SRGB. // The generated color space should recognize that this is SRGB.
EXPECT_EQ(color_space.ToSkColorSpace().get(), sk_color_space.get()); EXPECT_EQ(color_space.ToSkColorSpace().get(), sk_color_space.get());
...@@ -78,7 +82,8 @@ TEST(ICCProfile, ParametricVersusExact) { ...@@ -78,7 +82,8 @@ TEST(ICCProfile, ParametricVersusExact) {
// This ICC profile has three transfer functions that differ enough that the // This ICC profile has three transfer functions that differ enough that the
// parametric color space is considered inaccurate. // parametric color space is considered inaccurate.
ICCProfile multi_tr_fn = ICCProfileForTestingNoAnalyticTrFn(); ICCProfile multi_tr_fn = ICCProfileForTestingNoAnalyticTrFn();
EXPECT_NE(multi_tr_fn.GetColorSpace(), multi_tr_fn.GetParametricColorSpace()); EXPECT_NE(multi_tr_fn.GetColorSpace(),
multi_tr_fn.GetColorSpace().GetParametricApproximation());
ICCProfile multi_tr_fn_color_space; ICCProfile multi_tr_fn_color_space;
EXPECT_TRUE( EXPECT_TRUE(
...@@ -86,35 +91,40 @@ TEST(ICCProfile, ParametricVersusExact) { ...@@ -86,35 +91,40 @@ TEST(ICCProfile, ParametricVersusExact) {
EXPECT_EQ(multi_tr_fn_color_space, multi_tr_fn); EXPECT_EQ(multi_tr_fn_color_space, multi_tr_fn);
ICCProfile multi_tr_fn_parametric_color_space; ICCProfile multi_tr_fn_parametric_color_space;
EXPECT_TRUE(multi_tr_fn.GetParametricColorSpace().GetICCProfile( EXPECT_TRUE(
&multi_tr_fn_parametric_color_space)); multi_tr_fn.GetColorSpace().GetParametricApproximation().GetICCProfile(
&multi_tr_fn_parametric_color_space));
EXPECT_NE(multi_tr_fn_parametric_color_space, multi_tr_fn); EXPECT_NE(multi_tr_fn_parametric_color_space, multi_tr_fn);
// This ICC profile has a transfer function with T(1) that is greater than 1 // This ICC profile has a transfer function with T(1) that is greater than 1
// in the approximation, but is still close enough to be considered accurate. // in the approximation, but is still close enough to be considered accurate.
ICCProfile overshoot = ICCProfileForTestingOvershoot(); ICCProfile overshoot = ICCProfileForTestingOvershoot();
EXPECT_EQ(overshoot.GetColorSpace(), overshoot.GetParametricColorSpace()); EXPECT_EQ(overshoot.GetColorSpace(),
overshoot.GetColorSpace().GetParametricApproximation());
ICCProfile overshoot_color_space; ICCProfile overshoot_color_space;
EXPECT_TRUE(overshoot.GetColorSpace().GetICCProfile(&overshoot_color_space)); EXPECT_TRUE(overshoot.GetColorSpace().GetICCProfile(&overshoot_color_space));
EXPECT_EQ(overshoot_color_space, overshoot); EXPECT_EQ(overshoot_color_space, overshoot);
ICCProfile overshoot_parametric_color_space; ICCProfile overshoot_parametric_color_space;
EXPECT_TRUE(overshoot.GetParametricColorSpace().GetICCProfile( EXPECT_TRUE(
&overshoot_parametric_color_space)); overshoot.GetColorSpace().GetParametricApproximation().GetICCProfile(
&overshoot_parametric_color_space));
EXPECT_EQ(overshoot_parametric_color_space, overshoot); EXPECT_EQ(overshoot_parametric_color_space, overshoot);
// This ICC profile is precisely represented by the parametric color space. // This ICC profile is precisely represented by the parametric color space.
ICCProfile accurate = ICCProfileForTestingAdobeRGB(); ICCProfile accurate = ICCProfileForTestingAdobeRGB();
EXPECT_EQ(accurate.GetColorSpace(), accurate.GetParametricColorSpace()); EXPECT_EQ(accurate.GetColorSpace(),
accurate.GetColorSpace().GetParametricApproximation());
ICCProfile accurate_color_space; ICCProfile accurate_color_space;
EXPECT_TRUE(accurate.GetColorSpace().GetICCProfile(&accurate_color_space)); EXPECT_TRUE(accurate.GetColorSpace().GetICCProfile(&accurate_color_space));
EXPECT_EQ(accurate_color_space, accurate); EXPECT_EQ(accurate_color_space, accurate);
ICCProfile accurate_parametric_color_space; ICCProfile accurate_parametric_color_space;
EXPECT_TRUE(accurate.GetParametricColorSpace().GetICCProfile( EXPECT_TRUE(
&accurate_parametric_color_space)); accurate.GetColorSpace().GetParametricApproximation().GetICCProfile(
&accurate_parametric_color_space));
EXPECT_EQ(accurate_parametric_color_space, accurate); EXPECT_EQ(accurate_parametric_color_space, accurate);
// This ICC profile has only an A2B representation. We cannot create an // This ICC profile has only an A2B representation. We cannot create an
...@@ -136,12 +146,15 @@ TEST(ICCProfile, GarbageData) { ...@@ -136,12 +146,15 @@ TEST(ICCProfile, GarbageData) {
ICCProfile::FromData(bad_data.data(), bad_data.size()); ICCProfile::FromData(bad_data.data(), bad_data.size());
EXPECT_FALSE(garbage_profile.IsValid()); EXPECT_FALSE(garbage_profile.IsValid());
EXPECT_FALSE(garbage_profile.GetColorSpace().IsValid()); EXPECT_FALSE(garbage_profile.GetColorSpace().IsValid());
EXPECT_FALSE(garbage_profile.GetParametricColorSpace().IsValid()); EXPECT_FALSE(
garbage_profile.GetColorSpace().GetParametricApproximation().IsValid());
ICCProfile default_ctor_profile; ICCProfile default_ctor_profile;
EXPECT_FALSE(default_ctor_profile.IsValid()); EXPECT_FALSE(default_ctor_profile.IsValid());
EXPECT_FALSE(default_ctor_profile.GetColorSpace().IsValid()); EXPECT_FALSE(default_ctor_profile.GetColorSpace().IsValid());
EXPECT_FALSE(default_ctor_profile.GetParametricColorSpace().IsValid()); EXPECT_FALSE(default_ctor_profile.GetColorSpace()
.GetParametricApproximation()
.IsValid());
} }
TEST(ICCProfile, GenericRGB) { TEST(ICCProfile, GenericRGB) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment