aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/core.gypi1
-rw-r--r--include/core/SkColorSpace.h75
-rw-r--r--src/core/SkColorSpace.cpp115
-rw-r--r--src/core/SkColorSpace.h80
-rw-r--r--src/core/SkColorSpace_Base.h (renamed from src/core/SkColorSpacePriv.h)32
-rw-r--r--tests/ColorSpaceTest.cpp4
6 files changed, 175 insertions, 132 deletions
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 477a9e7108..38aa1b750e 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -76,7 +76,6 @@
'<(skia_src_path)/core/SkColorShader.cpp',
'<(skia_src_path)/core/SkColorShader.h',
'<(skia_src_path)/core/SkColorSpace.cpp',
- '<(skia_src_path)/core/SkColorSpace.h',
'<(skia_src_path)/core/SkColorTable.cpp',
'<(skia_src_path)/core/SkComposeShader.cpp',
'<(skia_src_path)/core/SkConfig8888.cpp',
diff --git a/include/core/SkColorSpace.h b/include/core/SkColorSpace.h
new file mode 100644
index 0000000000..9630fe4c25
--- /dev/null
+++ b/include/core/SkColorSpace.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorSpace_DEFINED
+#define SkColorSpace_DEFINED
+
+#include "SkMatrix44.h"
+#include "SkRefCnt.h"
+#include "../private/SkTemplates.h"
+
+class SkColorSpace : public SkRefCnt {
+public:
+
+ /**
+ * Common, named profiles that we can recognize.
+ */
+ enum Named {
+ kUnknown_Named,
+ kSRGB_Named,
+ kAdobeRGB_Named,
+ };
+
+ /**
+ * Create an SkColorSpace from the src gamma and a transform from src gamut to D50 XYZ.
+ */
+ static sk_sp<SkColorSpace> NewRGB(float gammas[3], const SkMatrix44& toXYZD50);
+
+ /**
+ * Create a common, named SkColorSpace.
+ */
+ static sk_sp<SkColorSpace> NewNamed(Named);
+
+ /**
+ * Create an SkColorSpace from an ICC profile.
+ */
+ static sk_sp<SkColorSpace> NewICC(const void*, size_t);
+
+ enum GammaNamed {
+ kLinear_GammaNamed,
+
+ /**
+ * Gamma curve is a close match to the 2.2f exponential curve. This is by far
+ * the most common gamma, and is used by sRGB and Adobe RGB profiles.
+ */
+ k2Dot2Curve_GammaNamed,
+
+ /**
+ * Gamma is represented by a look-up table, a parametric curve, or an uncommon
+ * exponential curve. Or there is an additional pre-processing step before the
+ * applying the gamma.
+ */
+ kNonStandard_GammaNamed,
+ };
+
+ GammaNamed gammaNamed() const { return fGammaNamed; }
+
+ /**
+ * Returns the matrix used to transform src gamut to XYZ D50.
+ */
+ SkMatrix44 xyz() const { return fToXYZD50; }
+
+protected:
+
+ SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named);
+
+ const GammaNamed fGammaNamed;
+ const SkMatrix44 fToXYZD50;
+ const Named fNamed;
+};
+
+#endif
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 52e4ced85d..e2f983f7b8 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -5,9 +5,8 @@
* found in the LICENSE file.
*/
-#include "SkAtomics.h"
#include "SkColorSpace.h"
-#include "SkColorSpacePriv.h"
+#include "SkColorSpace_Base.h"
#include "SkOnce.h"
static bool color_space_almost_equal(float a, float b) {
@@ -16,22 +15,29 @@ static bool color_space_almost_equal(float a, float b) {
//////////////////////////////////////////////////////////////////////////////////////////////////
-static int32_t gUniqueColorSpaceID;
-
-SkColorSpace::SkColorSpace(sk_sp<SkGammas> gammas, const SkMatrix44& toXYZD50, Named named)
- : fGammas(gammas)
+SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named)
+ : fGammaNamed(kNonStandard_GammaNamed)
, fToXYZD50(toXYZD50)
- , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID))
, fNamed(named)
{}
-SkColorSpace::SkColorSpace(SkColorLookUpTable* colorLUT, sk_sp<SkGammas> gammas,
- const SkMatrix44& toXYZD50)
- : fColorLUT(colorLUT)
+SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkGammas> gammas, const SkMatrix44& toXYZD50,
+ Named named)
+ : INHERITED(kNonStandard_GammaNamed, toXYZD50, named)
+ , fGammas(gammas)
+{}
+
+SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkGammas> gammas, GammaNamed gammaNamed,
+ const SkMatrix44& toXYZD50, Named named)
+ : INHERITED(gammaNamed, toXYZD50, named)
+ , fGammas(gammas)
+{}
+
+SkColorSpace_Base::SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGammas> gammas,
+ const SkMatrix44& toXYZD50)
+ : INHERITED(kNonStandard_GammaNamed, toXYZD50, kUnknown_Named)
+ , fColorLUT(colorLUT)
, fGammas(gammas)
- , fToXYZD50(toXYZD50)
- , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID))
- , fNamed(kUnknown_Named)
{}
const float gSRGB_toXYZD50[] {
@@ -71,33 +77,46 @@ static bool xyz_almost_equal(const SkMatrix44& toXYZD50, const float* standard)
color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f);
}
-static SkOnce gStandardGammasOnce;
-static SkGammas* gStandardGammas;
+static SkOnce g2Dot2CurveGammasOnce;
+static SkGammas* g2Dot2CurveGammas;
+static SkOnce gLinearGammasOnce;
+static SkGammas* gLinearGammas;
sk_sp<SkColorSpace> SkColorSpace::NewRGB(float gammaVals[3], const SkMatrix44& toXYZD50) {
sk_sp<SkGammas> gammas = nullptr;
+ GammaNamed gammaNamed = kNonStandard_GammaNamed;
// Check if we really have sRGB or Adobe RGB
if (color_space_almost_equal(2.2f, gammaVals[0]) &&
color_space_almost_equal(2.2f, gammaVals[1]) &&
color_space_almost_equal(2.2f, gammaVals[2]))
{
- gStandardGammasOnce([] {
- gStandardGammas = new SkGammas(2.2f, 2.2f, 2.2f);
+ g2Dot2CurveGammasOnce([] {
+ g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f);
});
- gammas = sk_ref_sp(gStandardGammas);
+ gammas = sk_ref_sp(g2Dot2CurveGammas);
+ gammaNamed = k2Dot2Curve_GammaNamed;
if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
return SkColorSpace::NewNamed(kSRGB_Named);
} else if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) {
return SkColorSpace::NewNamed(kAdobeRGB_Named);
}
+ } else if (color_space_almost_equal(1.0f, gammaVals[0]) &&
+ color_space_almost_equal(1.0f, gammaVals[1]) &&
+ color_space_almost_equal(1.0f, gammaVals[2]))
+ {
+ gLinearGammasOnce([] {
+ gLinearGammas = new SkGammas(1.0f, 1.0f, 1.0f);
+ });
+ gammas = sk_ref_sp(gLinearGammas);
+ gammaNamed = kLinear_GammaNamed;
}
if (!gammas) {
gammas = sk_sp<SkGammas>(new SkGammas(gammaVals[0], gammaVals[1], gammaVals[2]));
}
- return sk_sp<SkColorSpace>(new SkColorSpace(gammas, toXYZD50, kUnknown_Named));
+ return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammas, gammaNamed, toXYZD50, kUnknown_Named));
}
sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
@@ -108,27 +127,29 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
switch (named) {
case kSRGB_Named: {
- gStandardGammasOnce([] {
- gStandardGammas = new SkGammas(2.2f, 2.2f, 2.2f);
+ g2Dot2CurveGammasOnce([] {
+ g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f);
});
sRGBOnce([] {
SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50);
- sRGB = new SkColorSpace(sk_ref_sp(gStandardGammas), srgbToxyzD50, kSRGB_Named);
+ sRGB = new SkColorSpace_Base(sk_ref_sp(g2Dot2CurveGammas), k2Dot2Curve_GammaNamed,
+ srgbToxyzD50, kSRGB_Named);
});
return sk_ref_sp(sRGB);
}
case kAdobeRGB_Named: {
- gStandardGammasOnce([] {
- gStandardGammas = new SkGammas(2.2f, 2.2f, 2.2f);
+ g2Dot2CurveGammasOnce([] {
+ g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f);
});
adobeRGBOnce([] {
SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Constructor);
adobergbToxyzD50.set3x3ColMajorf(gAdobeRGB_toXYZD50);
- adobeRGB = new SkColorSpace(sk_ref_sp(gStandardGammas), adobergbToxyzD50,
- kAdobeRGB_Named);
+ adobeRGB = new SkColorSpace_Base(sk_ref_sp(g2Dot2CurveGammas),
+ k2Dot2Curve_GammaNamed, adobergbToxyzD50,
+ kAdobeRGB_Named);
});
return sk_ref_sp(adobeRGB);
}
@@ -336,8 +357,7 @@ bool load_xyz(float dst[3], const uint8_t* src, size_t len) {
static const uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', 'v');
static const uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', 'a');
-bool SkColorSpace::LoadGammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src,
- size_t len) {
+bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, size_t len) {
for (uint32_t i = 0; i < numGammas; i++) {
if (len < 12) {
// FIXME (msarett):
@@ -545,8 +565,8 @@ bool SkColorSpace::LoadGammas(SkGammaCurve* gammas, uint32_t numGammas, const ui
static const uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' ');
-bool SkColorSpace::LoadColorLUT(SkColorLookUpTable* colorLUT, uint32_t inputChannels,
- uint32_t outputChannels, const uint8_t* src, size_t len) {
+bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32_t outputChannels,
+ const uint8_t* src, size_t len) {
if (len < 20) {
SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len);
return false;
@@ -620,8 +640,8 @@ bool load_matrix(SkMatrix44* toXYZ, const uint8_t* src, size_t len) {
return true;
}
-bool SkColorSpace::LoadA2B0(SkColorLookUpTable* colorLUT, SkGammaCurve* gammas, SkMatrix44* toXYZ,
- const uint8_t* src, size_t len) {
+bool load_a2b0(SkColorLookUpTable* colorLUT, SkGammaCurve* gammas, SkMatrix44* toXYZ,
+ const uint8_t* src, size_t len) {
if (len < 32) {
SkColorSpacePrintf("A to B tag is too small (%d bytes).", len);
return false;
@@ -662,16 +682,15 @@ bool SkColorSpace::LoadA2B0(SkColorLookUpTable* colorLUT, SkGammaCurve* gammas,
uint32_t offsetToColorLUT = read_big_endian_int(src + 24);
if (0 != offsetToColorLUT && offsetToColorLUT < len) {
- if (!SkColorSpace::LoadColorLUT(colorLUT, inputChannels, outputChannels,
- src + offsetToColorLUT, len - offsetToColorLUT)) {
+ if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offsetToColorLUT,
+ len - offsetToColorLUT)) {
SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n");
}
}
uint32_t offsetToMCurves = read_big_endian_int(src + 20);
if (0 != offsetToMCurves && offsetToMCurves < len) {
- if (!SkColorSpace::LoadGammas(gammas, outputChannels, src + offsetToMCurves,
- len - offsetToMCurves)) {
+ if (!load_gammas(gammas, outputChannels, src + offsetToMCurves, len - offsetToMCurves)) {
SkColorSpacePrintf("Failed to read M curves from A to B tag.\n");
}
}
@@ -750,16 +769,16 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC);
g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC);
b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC);
- if (!r || !SkColorSpace::LoadGammas(&curves[0], 1,
- r->addr((const uint8_t*) base), r->fLength)) {
+ if (!r || !load_gammas(&curves[0], 1, r->addr((const uint8_t*) base), r->fLength))
+ {
SkColorSpacePrintf("Failed to read R gamma tag.\n");
}
- if (!g || !SkColorSpace::LoadGammas(&curves[1], 1,
- g->addr((const uint8_t*) base), g->fLength)) {
+ if (!g || !load_gammas(&curves[1], 1, g->addr((const uint8_t*) base), g->fLength))
+ {
SkColorSpacePrintf("Failed to read G gamma tag.\n");
}
- if (!b || !SkColorSpace::LoadGammas(&curves[2], 1,
- b->addr((const uint8_t*) base), b->fLength)) {
+ if (!b || !load_gammas(&curves[2], 1, b->addr((const uint8_t*) base), b->fLength))
+ {
SkColorSpacePrintf("Failed to read B gamma tag.\n");
}
@@ -776,7 +795,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
gammaVals[2] = gammas->fBlue.fValue;
return SkColorSpace::NewRGB(gammaVals, mat);
} else {
- return sk_sp<SkColorSpace>(new SkColorSpace(gammas, mat, kUnknown_Named));
+ return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammas, mat, kUnknown_Named));
}
}
@@ -786,15 +805,16 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
SkAutoTDelete<SkColorLookUpTable> colorLUT(new SkColorLookUpTable());
SkGammaCurve curves[3];
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
- if (!SkColorSpace::LoadA2B0(colorLUT, curves, &toXYZ,
- a2b0->addr((const uint8_t*) base), a2b0->fLength)) {
+ if (!load_a2b0(colorLUT, curves, &toXYZ, a2b0->addr((const uint8_t*) base),
+ a2b0->fLength)) {
return_null("Failed to parse A2B0 tag");
}
sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::move(curves[1]),
std::move(curves[2])));
if (colorLUT->fTable) {
- return sk_sp<SkColorSpace>(new SkColorSpace(colorLUT.release(), gammas, toXYZ));
+ return sk_sp<SkColorSpace>(new SkColorSpace_Base(colorLUT.release(), gammas,
+ toXYZ));
} else if (gammas->isValues()) {
// When we have values, take advantage of the NewFromRGB initializer.
// This allows us to check for canonical sRGB and Adobe RGB.
@@ -804,7 +824,8 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
gammaVals[2] = gammas->fBlue.fValue;
return SkColorSpace::NewRGB(gammaVals, toXYZ);
} else {
- return sk_sp<SkColorSpace>(new SkColorSpace(gammas, toXYZ, kUnknown_Named));
+ return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammas, toXYZ,
+ kUnknown_Named));
}
}
diff --git a/src/core/SkColorSpace.h b/src/core/SkColorSpace.h
deleted file mode 100644
index 299ffbca71..0000000000
--- a/src/core/SkColorSpace.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkColorSpace_DEFINED
-#define SkColorSpace_DEFINED
-
-// Some terms
-//
-// PCS : Profile Connection Space : where color number values have an absolute meaning.
-// Part of the work float is to convert colors to and from this space...
-// src_linear_unit_floats --> PCS --> PCS' --> dst_linear_unit_floats
-//
-// Some nice documents
-//
-// http://www.cambridgeincolour.com/tutorials/color-space-conversion.htm
-// https://www.w3.org/Graphics/Color/srgb
-// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html
-//
-
-#include "SkMatrix44.h"
-#include "SkRefCnt.h"
-#include "../private/SkTemplates.h"
-
-struct SkColorLookUpTable;
-struct SkGammaCurve;
-struct SkGammas;
-
-class SkColorSpace : public SkRefCnt {
-public:
-
- enum Named {
- kUnknown_Named,
- kSRGB_Named,
- kAdobeRGB_Named,
- };
-
- /**
- * Given the src gamma and a transform from src gamut to D50_XYZ, return a SkColorSpace.
- */
- static sk_sp<SkColorSpace> NewRGB(float gammas[3], const SkMatrix44& toXYZD50);
-
- static sk_sp<SkColorSpace> NewNamed(Named);
- static sk_sp<SkColorSpace> NewICC(const void*, size_t);
-
- /**
- * Used only by test code.
- */
- SkGammas* gammas() const { return fGammas.get(); }
-
- SkMatrix44 xyz() const { return fToXYZD50; }
- Named named() const { return fNamed; }
- uint32_t uniqueID() const { return fUniqueID; }
-
-private:
-
- static bool LoadGammas(SkGammaCurve* gammas, uint32_t num, const uint8_t* src, size_t len);
-
- static bool LoadColorLUT(SkColorLookUpTable* colorLUT, uint32_t inputChannels,
- uint32_t outputChannels, const uint8_t* src, size_t len);
-
- static bool LoadA2B0(SkColorLookUpTable* colorLUT, SkGammaCurve*, SkMatrix44* toXYZ,
- const uint8_t* src, size_t len);
-
- SkColorSpace(sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ, Named);
-
- SkColorSpace(SkColorLookUpTable* colorLUT, sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ);
-
- SkAutoTDelete<SkColorLookUpTable> fColorLUT;
- sk_sp<SkGammas> fGammas;
- const SkMatrix44 fToXYZD50;
-
- const uint32_t fUniqueID;
- const Named fNamed;
-};
-
-#endif
diff --git a/src/core/SkColorSpacePriv.h b/src/core/SkColorSpace_Base.h
index a6274c7823..dbfe7338cd 100644
--- a/src/core/SkColorSpacePriv.h
+++ b/src/core/SkColorSpace_Base.h
@@ -5,8 +5,10 @@
* found in the LICENSE file.
*/
-#ifndef SkColorSpacePriv_DEFINED
-#define SkColorSpacePriv_DEFINED
+#ifndef SkColorSpace_Base_DEFINED
+#define SkColorSpace_Base_DEFINED
+
+#include "SkColorSpace.h"
struct SkGammaCurve {
bool isValue() const {
@@ -108,4 +110,30 @@ struct SkColorLookUpTable {
}
};
+class SkColorSpace_Base : public SkColorSpace {
+public:
+
+ SkGammas* gammas() const { return fGammas.get(); }
+
+private:
+
+ SkColorSpace_Base(sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ, Named);
+
+ SkColorSpace_Base(sk_sp<SkGammas> gammas, GammaNamed gammaNamed, const SkMatrix44& toXYZ,
+ Named);
+
+ SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGammas> gammas,
+ const SkMatrix44& toXYZ);
+
+ SkAutoTDelete<SkColorLookUpTable> fColorLUT;
+ sk_sp<SkGammas> fGammas;
+
+ friend class SkColorSpace;
+ typedef SkColorSpace INHERITED;
+};
+
+static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) {
+ return static_cast<SkColorSpace_Base*>(colorSpace);
+}
+
#endif
diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp
index 698c3e9c61..097ca0929a 100644
--- a/tests/ColorSpaceTest.cpp
+++ b/tests/ColorSpaceTest.cpp
@@ -8,7 +8,7 @@
#include "Resources.h"
#include "SkCodec.h"
#include "SkColorSpace.h"
-#include "SkColorSpacePriv.h"
+#include "SkColorSpace_Base.h"
#include "Test.h"
#include "png.h"
@@ -21,7 +21,7 @@ static void test_space(skiatest::Reporter* r, SkColorSpace* space,
const float red[], const float green[], const float blue[],
const float expectedGammas[]) {
- SkGammas* gammas = space->gammas();
+ SkGammas* gammas = as_CSB(space)->gammas();
REPORTER_ASSERT(r, almost_equal(expectedGammas[0], gammas->fRed.fValue));
REPORTER_ASSERT(r, almost_equal(expectedGammas[1], gammas->fGreen.fValue));
REPORTER_ASSERT(r, almost_equal(expectedGammas[2], gammas->fBlue.fValue));