aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-01-04 10:53:31 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-04 16:26:58 +0000
commit1e854246e6ce431838de882116b86f085eb7b08e (patch)
tree884fa978dca95b0bd0494af1f9a216dec418725c
parente2b66a769b19780c87a5baf1ecff48158fd63e45 (diff)
Improve detection of color space transfer fns
BUG=skia: Change-Id: I744af0efd4d48a8932b834092ed2dbad13008c1d Reviewed-on: https://skia-review.googlesource.com/6556 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Matt Sarett <msarett@google.com>
-rw-r--r--src/core/SkColorSpace.cpp4
-rw-r--r--src/core/SkColorSpacePriv.h32
-rw-r--r--tests/ColorSpaceTest.cpp54
3 files changed, 82 insertions, 8 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index f6cbf0acac..239a61bcce 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -165,6 +165,10 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const SkColorSpaceTransferFn& coeffs,
return SkColorSpace_Base::MakeRGB(k2Dot2Curve_SkGammaNamed, toXYZD50);
}
+ if (is_almost_linear(coeffs)) {
+ return SkColorSpace_Base::MakeRGB(kLinear_SkGammaNamed, toXYZD50);
+ }
+
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas(3));
SkColorSpaceTransferFn* fn = SkTAddOffset<SkColorSpaceTransferFn>(memory, sizeof(SkGammas));
diff --git a/src/core/SkColorSpacePriv.h b/src/core/SkColorSpacePriv.h
index 9f084e72fc..5b09036ea8 100644
--- a/src/core/SkColorSpacePriv.h
+++ b/src/core/SkColorSpacePriv.h
@@ -51,7 +51,7 @@ static inline bool is_valid_transfer_fn(const SkColorSpaceTransferFn& coeffs) {
}
if (coeffs.fD == 0.0f) {
- // Y = (aX + b)^g + c for always
+ // Y = (aX + b)^g + e for always
if (0.0f == coeffs.fA || 0.0f == coeffs.fG) {
SkColorSpacePrintf("A or G is zero, constant transfer function "
"is nonsense");
@@ -60,16 +60,16 @@ static inline bool is_valid_transfer_fn(const SkColorSpaceTransferFn& coeffs) {
}
if (coeffs.fD >= 1.0f) {
- // Y = eX + f for always
- if (0.0f == coeffs.fE) {
- SkColorSpacePrintf("E is zero, constant transfer function is "
+ // Y = cX + f for always
+ if (0.0f == coeffs.fC) {
+ SkColorSpacePrintf("C is zero, constant transfer function is "
"nonsense");
return false;
}
}
if ((0.0f == coeffs.fA || 0.0f == coeffs.fG) && 0.0f == coeffs.fC) {
- SkColorSpacePrintf("A or G, and E are zero, constant transfer function "
+ SkColorSpacePrintf("A or G, and C are zero, constant transfer function "
"is nonsense");
return false;
}
@@ -100,11 +100,27 @@ static inline bool is_almost_srgb(const SkColorSpaceTransferFn& coeffs) {
static inline bool is_almost_2dot2(const SkColorSpaceTransferFn& coeffs) {
return color_space_almost_equal(1.0f, coeffs.fA) &&
color_space_almost_equal(0.0f, coeffs.fB) &&
- color_space_almost_equal(0.0f, coeffs.fC) &&
- color_space_almost_equal(0.0f, coeffs.fD) &&
color_space_almost_equal(0.0f, coeffs.fE) &&
+ color_space_almost_equal(2.2f, coeffs.fG) &&
+ coeffs.fD <= 0.0f;
+}
+
+static inline bool is_almost_linear(const SkColorSpaceTransferFn& coeffs) {
+ // OutputVal = InputVal ^ 1.0f
+ const bool linearExp =
+ color_space_almost_equal(1.0f, coeffs.fA) &&
+ color_space_almost_equal(0.0f, coeffs.fB) &&
+ color_space_almost_equal(0.0f, coeffs.fE) &&
+ color_space_almost_equal(1.0f, coeffs.fG) &&
+ coeffs.fD <= 0.0f;
+
+ // OutputVal = 1.0f * InputVal
+ const bool linearFn =
+ color_space_almost_equal(1.0f, coeffs.fC) &&
color_space_almost_equal(0.0f, coeffs.fF) &&
- color_space_almost_equal(2.2f, coeffs.fG);
+ coeffs.fD >= 1.0f;
+
+ return linearExp || linearFn;
}
static inline void value_to_parametric(SkColorSpaceTransferFn* coeffs, float exponent) {
diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp
index df253c09e3..ba355cd612 100644
--- a/tests/ColorSpaceTest.cpp
+++ b/tests/ColorSpaceTest.cpp
@@ -10,6 +10,7 @@
#include "SkColorSpace.h"
#include "SkColorSpace_Base.h"
#include "SkColorSpace_XYZ.h"
+#include "SkColorSpacePriv.h"
#include "Test.h"
#include "png.h"
@@ -111,6 +112,17 @@ DEF_TEST(ColorSpaceSRGBCompare, r) {
SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, srgbToxyzD50);
REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace);
+ SkColorSpaceTransferFn srgbFn;
+ srgbFn.fA = (1.0f / 1.055f);
+ srgbFn.fB = (0.055f / 1.055f);
+ srgbFn.fC = (1.0f / 12.92f);
+ srgbFn.fD = 0.04045f;
+ srgbFn.fE = 0.0f;
+ srgbFn.fF = 0.0f;
+ srgbFn.fG = 2.4f;
+ sk_sp<SkColorSpace> rgbColorSpace2 = SkColorSpace::MakeRGB(srgbFn, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace2 == namedColorSpace);
+
// Change a single value from the sRGB matrix
srgbToxyzD50.set(2, 2, 0.5f);
sk_sp<SkColorSpace> strangeColorSpace =
@@ -135,6 +147,28 @@ DEF_TEST(ColorSpaceSRGBLinearCompare, r) {
SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50);
REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace);
+ SkColorSpaceTransferFn linearExpFn;
+ linearExpFn.fA = 1.0f;
+ linearExpFn.fB = 0.0f;
+ linearExpFn.fC = 0.0f;
+ linearExpFn.fD = 0.0f;
+ linearExpFn.fE = 0.0f;
+ linearExpFn.fF = 0.0f;
+ linearExpFn.fG = 1.0f;
+ sk_sp<SkColorSpace> rgbColorSpace2 = SkColorSpace::MakeRGB(linearExpFn, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace2 == namedColorSpace);
+
+ SkColorSpaceTransferFn linearFn;
+ linearFn.fA = 0.0f;
+ linearFn.fB = 0.0f;
+ linearFn.fC = 1.0f;
+ linearFn.fD = 1.0f;
+ linearFn.fE = 0.0f;
+ linearFn.fF = 0.0f;
+ linearFn.fG = 0.0f;
+ sk_sp<SkColorSpace> rgbColorSpace3 = SkColorSpace::MakeRGB(linearFn, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace3 == namedColorSpace);
+
// Change a single value from the sRGB matrix
srgbToxyzD50.set(2, 2, 0.5f);
sk_sp<SkColorSpace> strangeColorSpace =
@@ -142,6 +176,26 @@ DEF_TEST(ColorSpaceSRGBLinearCompare, r) {
REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
}
+DEF_TEST(ColorSpaceAdobeCompare, r) {
+ // Create an sRGB color space by name
+ sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kAdobeRGB_Named);
+
+ // Create an sRGB color space by value
+ SkMatrix44 adobeToxyzD50(SkMatrix44::kUninitialized_Constructor);
+ adobeToxyzD50.set3x3RowMajorf(gAdobeRGB_toXYZD50);
+
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 0.0f;
+ fn.fD = 0.0f;
+ fn.fE = 0.0f;
+ fn.fF = 0.0f;
+ fn.fG = 2.2f;
+ sk_sp<SkColorSpace> rgbColorSpace = SkColorSpace::MakeRGB(fn, adobeToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace);
+}
+
DEF_TEST(ColorSpace_Named, r) {
const struct {
SkColorSpace::Named fNamed;