Create a single, unique pointer to sRGB color space

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1945693002

Review-Url: https://codereview.chromium.org/1945693002
This commit is contained in:
msarett 2016-05-03 14:24:47 -07:00 committed by Commit bot
parent 4f16e6361d
commit 02125d10d5
4 changed files with 72 additions and 18 deletions

View File

@ -236,7 +236,7 @@ sk_sp<SkColorSpace> read_color_space(png_structp png_ptr, png_infop info_ptr) {
SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
mat.set3x3ColMajorf(toXYZD50);
return SkColorSpace::NewRGB(mat, std::move(gammas));
return SkColorSpace::NewRGB(std::move(gammas), mat);
}
// Last, check for gamma.
@ -249,7 +249,7 @@ sk_sp<SkColorSpace> read_color_space(png_structp png_ptr, png_infop info_ptr) {
float value = png_inverted_fixed_point_to_float(gamma);
gammas = SkColorSpace::SkGammas(value, value, value);
return SkColorSpace::NewRGB(SkMatrix44::I(), std::move(gammas));
return SkColorSpace::NewRGB(std::move(gammas), SkMatrix44::I());
}
#endif // LIBPNG >= 1.6

View File

@ -7,6 +7,11 @@
#include "SkAtomics.h"
#include "SkColorSpace.h"
#include "SkOncePtr.h"
static bool color_space_almost_equal(float a, float b) {
return SkTAbs(a - b) < 0.01f;
}
void SkFloat3::dump() const {
SkDebugf("[%7.4f %7.4f %7.4f]\n", fVec[0], fVec[1], fVec[2]);
@ -32,23 +37,50 @@ SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, SkGammas gammas,
, fNamed(kUnknown_Named)
{}
sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkMatrix44& toXYZD50, SkGammas gammas) {
return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gammas), toXYZD50, kUnknown_Named));
}
const float gSRGB_toXYZD50[] {
0.4358f, 0.2224f, 0.0139f, // * R
0.3853f, 0.7170f, 0.0971f, // * G
0.1430f, 0.0606f, 0.7139f, // * B
};
SK_DECLARE_STATIC_ONCE_PTR(SkColorSpace, sRGB);
sk_sp<SkColorSpace> SkColorSpace::NewRGB(SkGammas gammas, const SkMatrix44& toXYZD50) {
// Check if we really have sRGB
if (color_space_almost_equal(2.2f, gammas.fRed.fValue) &&
color_space_almost_equal(2.2f, gammas.fGreen.fValue) &&
color_space_almost_equal(2.2f, gammas.fBlue.fValue) &&
color_space_almost_equal(toXYZD50.getFloat(0, 0), gSRGB_toXYZD50[0]) &&
color_space_almost_equal(toXYZD50.getFloat(0, 1), gSRGB_toXYZD50[1]) &&
color_space_almost_equal(toXYZD50.getFloat(0, 2), gSRGB_toXYZD50[2]) &&
color_space_almost_equal(toXYZD50.getFloat(1, 0), gSRGB_toXYZD50[3]) &&
color_space_almost_equal(toXYZD50.getFloat(1, 1), gSRGB_toXYZD50[4]) &&
color_space_almost_equal(toXYZD50.getFloat(1, 2), gSRGB_toXYZD50[5]) &&
color_space_almost_equal(toXYZD50.getFloat(2, 0), gSRGB_toXYZD50[6]) &&
color_space_almost_equal(toXYZD50.getFloat(2, 1), gSRGB_toXYZD50[7]) &&
color_space_almost_equal(toXYZD50.getFloat(2, 2), gSRGB_toXYZD50[8]) &&
color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) &&
color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) &&
color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) &&
color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) &&
color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) &&
color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) &&
color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f))
{
return SkColorSpace::NewNamed(kSRGB_Named);
}
return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gammas), toXYZD50, kUnknown_Named));
}
sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
switch (named) {
case kSRGB_Named: {
SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50);
return sk_sp<SkColorSpace>(new SkColorSpace(SkGammas(2.2f, 2.2f, 2.2f), srgbToxyzD50,
kSRGB_Named));
return sk_ref_sp(sRGB.get([=]{
return new SkColorSpace(SkGammas(2.2f, 2.2f, 2.2f), srgbToxyzD50, kSRGB_Named);
}));
}
default:
break;
@ -89,10 +121,6 @@ static int32_t read_big_endian_int(const uint8_t* ptr) {
return (int32_t) read_big_endian_uint(ptr);
}
static bool color_space_almost_equal(float a, float b) {
return SkTAbs(a - b) < 0.01f;
}
// This is equal to the header size according to the ICC specification (128)
// plus the size of the tag count (4). We include the tag count since we
// always require it to be present anyway.
@ -577,9 +605,10 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
b->addr((const uint8_t*) base), b->fLength)) {
SkColorSpacePrintf("Failed to read B gamma tag.\n");
}
SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
mat.set3x3ColMajorf(toXYZ);
return SkColorSpace::NewRGB(mat, std::move(gammas));
return SkColorSpace::NewRGB(std::move(gammas), mat);
}
// Recognize color profile specified by A2B0 tag.
@ -593,6 +622,12 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
return_null("Failed to parse A2B0 tag");
}
// If there is no colorLUT, use NewRGB. This allows us to check if the
// profile is sRGB.
if (!colorLUT.fTable) {
return SkColorSpace::NewRGB(std::move(gammas), toXYZ);
}
return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT), std::move(gammas),
toXYZ));
}

View File

@ -115,7 +115,7 @@ public:
* Return a colorspace instance, given a transform from linear_RGB to D50_XYZ
* and the src-gamma, return a ColorSpace
*/
static sk_sp<SkColorSpace> NewRGB(const SkMatrix44& toXYZD50, SkGammas gammas);
static sk_sp<SkColorSpace> NewRGB(SkGammas gammas, const SkMatrix44& toXYZD50);
static sk_sp<SkColorSpace> NewNamed(Named);
static sk_sp<SkColorSpace> NewICC(const void*, size_t);

View File

@ -41,13 +41,14 @@ static void test_space(skiatest::Reporter* r, SkColorSpace* space,
}
}
const float g_sRGB_XYZ[] = { 0.4358f, 0.2224f, 0.0139f, // R
0.3853f, 0.7170f, 0.0971f, // G
0.1430f, 0.0606f, 0.7139f }; // B
DEF_TEST(ColorSpace_sRGB, r) {
const float srgb_r[] = { 0.4358f, 0.2224f, 0.0139f };
const float srgb_g[] = { 0.3853f, 0.7170f, 0.0971f };
const float srgb_b[] = { 0.1430f, 0.0606f, 0.7139f };
const float srgb_gamma[] = { 2.2f, 2.2f, 2.2f };
test_space(r, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).get(),
srgb_r, srgb_g, srgb_b, srgb_gamma);
g_sRGB_XYZ, &g_sRGB_XYZ[3], &g_sRGB_XYZ[6], srgb_gamma);
}
@ -100,3 +101,21 @@ DEF_TEST(ColorSpaceParseJpegICCProfile, r) {
const float gamma[] = { 2.2f, 2.2f, 2.2f };
test_space(r, colorSpace, red, green, blue, gamma);
}
DEF_TEST(ColorSpaceSRGBCompare, r) {
// Create an sRGB color space by name
sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
// Create an sRGB color space by value
SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
srgbToxyzD50.set3x3ColMajorf(g_sRGB_XYZ);
sk_sp<SkColorSpace> rgbColorSpace = SkColorSpace::NewRGB(
SkColorSpace::SkGammas(2.2f, 2.2f, 2.2f), srgbToxyzD50);
REPORTER_ASSERT(r, namedColorSpace == namedColorSpace);
// Change a single value from the sRGB matrix
srgbToxyzD50.set(2, 2, 0.5f);
sk_sp<SkColorSpace> strangeColorSpace = SkColorSpace::NewRGB(
SkColorSpace::SkGammas(2.2f, 2.2f, 2.2f), srgbToxyzD50);
REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
}