Index: tests/ColorSpaceXformTest.cpp |
diff --git a/tests/ColorSpaceXformTest.cpp b/tests/ColorSpaceXformTest.cpp |
index 477e61acdda9d4956afdb6eea2537bed421e18c9..0e67fe497d5afd81c74e9096487c3ab7a600beb3 100644 |
--- a/tests/ColorSpaceXformTest.cpp |
+++ b/tests/ColorSpaceXformTest.cpp |
@@ -10,6 +10,7 @@ |
#include "SkCodecPriv.h" |
#include "SkColorPriv.h" |
#include "SkColorSpace.h" |
+#include "SkColorSpace_A2B.h" |
#include "SkColorSpace_Base.h" |
#include "SkColorSpace_XYZ.h" |
#include "SkColorSpaceXform_Base.h" |
@@ -25,10 +26,42 @@ public: |
// Use special testing entry point, so we don't skip the xform, even though src == dst. |
return SlowIdentityXform(static_cast<SkColorSpace_XYZ*>(space.get())); |
} |
+ |
+ static std::unique_ptr<SkColorSpaceXform> CreateIdentityXform_A2B( |
+ SkGammaNamed gammaNamed, const sk_sp<SkGammas>& gammas) { |
+ std::vector<SkColorSpace_A2B::Element> srcElements; |
+ // sRGB |
+ const float values[16] = { |
+ 0.4358f, 0.3853f, 0.1430f, 0.0f, |
+ 0.2224f, 0.7170f, 0.0606f, 0.0f, |
+ 0.0139f, 0.0971f, 0.7139f, 0.0f, |
+ 0.0000f, 0.0000f, 0.0000f, 1.0f |
+ }; |
+ SkMatrix44 arbitraryMatrix{SkMatrix44::kUninitialized_Constructor}; |
+ arbitraryMatrix.setRowMajorf(values); |
+ if (kNonStandard_SkGammaNamed == gammaNamed) { |
+ srcElements.push_back(SkColorSpace_A2B::Element(gammas)); |
+ } else { |
+ srcElements.push_back(SkColorSpace_A2B::Element(gammaNamed)); |
+ } |
+ srcElements.push_back(SkColorSpace_A2B::Element(arbitraryMatrix)); |
+ auto srcSpace = ColorSpaceXformTest::CreateA2BSpace(SkColorSpace_A2B::PCS::kXYZ, |
+ std::move(srcElements)); |
+ sk_sp<SkColorSpace> dstSpace(new SkColorSpace_XYZ(gammaNamed, gammas, arbitraryMatrix, |
+ nullptr)); |
+ |
+ return SkColorSpaceXform::New(static_cast<SkColorSpace_A2B*>(srcSpace.get()), |
+ static_cast<SkColorSpace_XYZ*>(dstSpace.get())); |
+ } |
+ |
+ static sk_sp<SkColorSpace> CreateA2BSpace(SkColorSpace_A2B::PCS pcs, |
+ std::vector<SkColorSpace_A2B::Element> elements) { |
+ return sk_sp<SkColorSpace>(new SkColorSpace_A2B(pcs, nullptr, std::move(elements))); |
+ } |
}; |
static bool almost_equal(int x, int y) { |
- return SkTAbs(x - y) <= 1; |
+ return SkTAbs(x - y) <= 1 ; |
} |
static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas, |
@@ -67,6 +100,42 @@ static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& ga |
} |
} |
+static void test_identity_xform_A2B(skiatest::Reporter* r, SkGammaNamed gammaNamed, |
+ const sk_sp<SkGammas>& gammas, bool repeat) { |
+ // Arbitrary set of 10 pixels |
+ constexpr int width = 10; |
+ constexpr uint32_t srcPixels[width] = { |
+ 0xFFABCDEF, 0xFF146829, 0xFF382759, 0xFF184968, 0xFFDE8271, |
+ 0xFF32AB52, 0xFF0383BC, 0xFF000102, 0xFFFFFFFF, 0xFFDDEEFF, }; |
+ uint32_t dstPixels[width]; |
+ |
+ // Create and perform an identity xform. |
+ auto xform = ColorSpaceXformTest::CreateIdentityXform_A2B(gammaNamed, gammas); |
+ bool result = xform->apply(select_xform_format(kN32_SkColorType), dstPixels, |
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, srcPixels, width, |
+ kOpaque_SkAlphaType); |
+ REPORTER_ASSERT(r, result); |
+ |
+ // Since the src->dst matrix is the identity, and the gamma curves match, |
+ // the pixels should be unchanged. |
+ for (int i = 0; i < width; i++) { |
+ REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 0) & 0xFF), |
+ SkGetPackedB32(dstPixels[i]))); |
+ REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 8) & 0xFF), |
+ SkGetPackedG32(dstPixels[i]))); |
+ REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 16) & 0xFF), |
+ SkGetPackedR32(dstPixels[i]))); |
+ REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF), |
+ SkGetPackedA32(dstPixels[i]))); |
+ } |
+ |
+ if (repeat) { |
+ // We should cache part of the transform after the run. So it is interesting |
+ // to make sure it still runs correctly the second time. |
+ test_identity_xform_A2B(r, gammaNamed, gammas, false); |
+ } |
+} |
+ |
DEF_TEST(ColorSpaceXform_TableGamma, r) { |
// Lookup-table based gamma curves |
constexpr size_t tableSize = 10; |
@@ -90,6 +159,7 @@ DEF_TEST(ColorSpaceXform_TableGamma, r) { |
table[8] = 0.75f; |
table[9] = 1.00f; |
test_identity_xform(r, gammas, true); |
+ test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, true); |
} |
DEF_TEST(ColorSpaceXform_ParametricGamma, r) { |
@@ -116,6 +186,7 @@ DEF_TEST(ColorSpaceXform_ParametricGamma, r) { |
params->fC = 0.0f; |
params->fG = 2.4f; |
test_identity_xform(r, gammas, true); |
+ test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, true); |
} |
DEF_TEST(ColorSpaceXform_ExponentialGamma, r) { |
@@ -124,6 +195,7 @@ DEF_TEST(ColorSpaceXform_ExponentialGamma, r) { |
gammas->fRedType = gammas->fGreenType = gammas->fBlueType = SkGammas::Type::kValue_Type; |
gammas->fRedData.fValue = gammas->fGreenData.fValue = gammas->fBlueData.fValue = 1.4f; |
test_identity_xform(r, gammas, true); |
+ test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, true); |
} |
DEF_TEST(ColorSpaceXform_NamedGamma, r) { |
@@ -133,6 +205,10 @@ DEF_TEST(ColorSpaceXform_NamedGamma, r) { |
gammas->fGreenData.fNamed = k2Dot2Curve_SkGammaNamed; |
gammas->fBlueData.fNamed = kLinear_SkGammaNamed; |
test_identity_xform(r, gammas, true); |
+ test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, true); |
+ test_identity_xform_A2B(r, kSRGB_SkGammaNamed, nullptr, true); |
+ test_identity_xform_A2B(r, k2Dot2Curve_SkGammaNamed, nullptr, true); |
+ test_identity_xform_A2B(r, kLinear_SkGammaNamed, nullptr, true); |
} |
DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) { |
@@ -174,5 +250,68 @@ DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) { |
gammas->fBlueData.fParamOffset = sizeof(float) * tableSize; |
test_identity_xform(r, gammas, true); |
+ test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, true); |
+} |
+ |
+DEF_TEST(ColorSpaceXform_A2BCLUT, r) { |
+ constexpr int inputChannels = 3; |
+ constexpr int gp = 4; // # grid points |
+ |
+ constexpr int numEntries = gp*gp*gp*3; |
+ uint8_t gridPoints[3] = {gp, gp, gp}; |
+ void* memory = sk_malloc_throw(sizeof(SkColorLookUpTable) + sizeof(float) * numEntries); |
+ sk_sp<SkColorLookUpTable> colorLUT(new (memory) SkColorLookUpTable(inputChannels, gridPoints)); |
+ // make a CLUT that rotates R, G, and B ie R->G, G->B, B->R |
+ float* table = SkTAddOffset<float>(memory, sizeof(SkColorLookUpTable)); |
+ for (int r = 0; r < gp; ++r) { |
+ for (int g = 0; g < gp; ++g) { |
+ for (int b = 0; b < gp; ++b) { |
+ table[3*(gp*gp*r + gp*g + b) + 0] = g * (1.f / (gp - 1.f)); |
+ table[3*(gp*gp*r + gp*g + b) + 1] = b * (1.f / (gp - 1.f)); |
+ table[3*(gp*gp*r + gp*g + b) + 2] = r * (1.f / (gp - 1.f)); |
+ } |
+ } |
+ } |
+ |
+ // build an even distribution of pixels every (7 / 255) steps |
+ // to test the xform on |
+ constexpr int pixelgp = 7; |
+ constexpr int numPixels = pixelgp*pixelgp*pixelgp; |
+ SkAutoTMalloc<uint32_t> srcPixels(numPixels); |
+ int srcIndex = 0; |
+ for (int r = 0; r < pixelgp; ++r) { |
+ for (int g = 0; g < pixelgp; ++g) { |
+ for (int b = 0; b < pixelgp; ++b) { |
+ const int red = (int) (r * (255.f / (pixelgp - 1.f))); |
+ const int green = (int) (g * (255.f / (pixelgp - 1.f))); |
+ const int blue = (int) (b * (255.f / (pixelgp - 1.f))); |
+ srcPixels[srcIndex] = SkColorSetRGB(red, green, blue); |
+ ++srcIndex; |
+ } |
+ } |
+ } |
+ SkAutoTMalloc<uint32_t> dstPixels(numPixels); |
+ |
+ // src space is identity besides CLUT |
+ std::vector<SkColorSpace_A2B::Element> srcElements; |
+ srcElements.push_back(SkColorSpace_A2B::Element(std::move(colorLUT))); |
+ auto srcSpace = ColorSpaceXformTest::CreateA2BSpace(SkColorSpace_A2B::PCS::kXYZ, |
+ std::move(srcElements)); |
+ // dst space is entirely identity |
+ auto dstSpace = SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkMatrix44::I()); |
+ auto xform = SkColorSpaceXform::New(srcSpace.get(), dstSpace.get()); |
+ bool result = xform->apply(SkColorSpaceXform::kRGBA_8888_ColorFormat, dstPixels.get(), |
+ SkColorSpaceXform::kRGBA_8888_ColorFormat, srcPixels.get(), |
+ numPixels, kOpaque_SkAlphaType); |
+ REPORTER_ASSERT(r, result); |
+ |
+ for (int i = 0; i < numPixels; ++i) { |
+ REPORTER_ASSERT(r, almost_equal(SkColorGetR(srcPixels[i]), |
+ SkColorGetG(dstPixels[i]))); |
+ REPORTER_ASSERT(r, almost_equal(SkColorGetG(srcPixels[i]), |
+ SkColorGetB(dstPixels[i]))); |
+ REPORTER_ASSERT(r, almost_equal(SkColorGetB(srcPixels[i]), |
+ SkColorGetR(dstPixels[i]))); |
+ } |
} |