blob: b5df1e1e7200751a9c2ca3bd8ad81ab8fae2e0e9 [file] [log] [blame]
msarettdc27a642016-06-06 12:02:31 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Resources.h"
9#include "SkCodec.h"
10#include "SkColorPriv.h"
11#include "SkColorSpace.h"
12#include "SkColorSpace_Base.h"
13#include "SkColorSpaceXform.h"
14#include "Test.h"
15
16class ColorSpaceXformTest {
17public:
msarettb3906762016-06-22 14:07:48 -070018 static std::unique_ptr<SkColorSpaceXform> CreateDefaultXform(const sk_sp<SkGammas>& srcGamma,
msarettdc27a642016-06-06 12:02:31 -070019 const SkMatrix44& srcToDst, const sk_sp<SkGammas>& dstGamma) {
msarettb3906762016-06-22 14:07:48 -070020
21 sk_sp<SkColorSpace> srcSpace(
22 new SkColorSpace_Base(nullptr, srcGamma, SkMatrix::I(), nullptr));
23 sk_sp<SkColorSpace> dstSpace(
24 new SkColorSpace_Base(nullptr, dstGamma, SkMatrix::I(), nullptr));
25
26 return SkColorSpaceXform::New(srcSpace, dstSpace);
msarettdc27a642016-06-06 12:02:31 -070027 }
28};
29
msarettb3906762016-06-22 14:07:48 -070030static bool almost_equal(int x, int y) {
31 return SkTAbs(x - y) <= 1;
32}
33
msarettdc27a642016-06-06 12:02:31 -070034static void test_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas) {
35 // Arbitrary set of 10 pixels
36 constexpr int width = 10;
37 constexpr uint32_t srcPixels[width] = {
38 0xFFABCDEF, 0xFF146829, 0xFF382759, 0xFF184968, 0xFFDE8271,
msarettb3906762016-06-22 14:07:48 -070039 0xFF32AB52, 0xFF0383BC, 0xFF000102, 0xFFFFFFFF, 0xFFDDEEFF, };
msarettdc27a642016-06-06 12:02:31 -070040 uint32_t dstPixels[width];
41
42 // Identity matrix
43 SkMatrix44 srcToDst = SkMatrix44::I();
44
45 // Create and perform xform
msarettb3906762016-06-22 14:07:48 -070046 std::unique_ptr<SkColorSpaceXform> xform =
47 ColorSpaceXformTest::CreateDefaultXform(gammas, srcToDst, gammas);
msarettdea03402016-06-16 10:50:55 -070048 xform->xform_RGB1_8888(dstPixels, srcPixels, width);
msarettdc27a642016-06-06 12:02:31 -070049
50 // Since the matrix is the identity, and the gamma curves match, the pixels
51 // should be unchanged.
52 for (int i = 0; i < width; i++) {
msarettb3906762016-06-22 14:07:48 -070053 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 0) & 0xFF),
54 SkGetPackedR32(dstPixels[i])));
55 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 8) & 0xFF),
56 SkGetPackedG32(dstPixels[i])));
57 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 16) & 0xFF),
58 SkGetPackedB32(dstPixels[i])));
59 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF),
60 SkGetPackedA32(dstPixels[i])));
msarettdc27a642016-06-06 12:02:31 -070061 }
62}
63
64DEF_TEST(ColorSpaceXform_TableGamma, r) {
65 // Lookup-table based gamma curves
66 SkGammaCurve red, green, blue;
67 constexpr size_t tableSize = 10;
68 red.fTable = std::unique_ptr<float[]>(new float[tableSize]);
69 green.fTable = std::unique_ptr<float[]>(new float[tableSize]);
70 blue.fTable = std::unique_ptr<float[]>(new float[tableSize]);
71 red.fTableSize = green.fTableSize = blue.fTableSize = 10;
72 red.fTable[0] = green.fTable[0] = blue.fTable[0] = 0.00f;
73 red.fTable[1] = green.fTable[1] = blue.fTable[1] = 0.05f;
74 red.fTable[2] = green.fTable[2] = blue.fTable[2] = 0.10f;
75 red.fTable[3] = green.fTable[3] = blue.fTable[3] = 0.15f;
76 red.fTable[4] = green.fTable[4] = blue.fTable[4] = 0.25f;
77 red.fTable[5] = green.fTable[5] = blue.fTable[5] = 0.35f;
78 red.fTable[6] = green.fTable[6] = blue.fTable[6] = 0.45f;
79 red.fTable[7] = green.fTable[7] = blue.fTable[7] = 0.60f;
80 red.fTable[8] = green.fTable[8] = blue.fTable[8] = 0.75f;
81 red.fTable[9] = green.fTable[9] = blue.fTable[9] = 1.00f;
82 sk_sp<SkGammas> gammas =
83 sk_make_sp<SkGammas>(std::move(red), std::move(green), std::move(blue));
84 test_xform(r, gammas);
85}
86
87DEF_TEST(ColorSpaceXform_ParametricGamma, r) {
88 // Parametric gamma curves
89 SkGammaCurve red, green, blue;
90
msarettb3906762016-06-22 14:07:48 -070091 // Interval, switch xforms at 0.0031308f
92 red.fD = green.fD = blue.fD = 0.04045f;
msarettdc27a642016-06-06 12:02:31 -070093
msarettb3906762016-06-22 14:07:48 -070094 // First equation:
95 red.fE = green.fE = blue.fE = 1.0f / 12.92f;
msarettdc27a642016-06-06 12:02:31 -070096
msarettb3906762016-06-22 14:07:48 -070097 // Second equation:
98 // Note that the function is continuous (it's actually sRGB).
99 red.fA = green.fA = blue.fA = 1.0f / 1.055f;
100 red.fB = green.fB = blue.fB = 0.055f / 1.055f;
101 red.fC = green.fC = blue.fC = 0.0f;
102 red.fG = green.fG = blue.fG = 2.4f;
103 sk_sp<SkGammas> gammas =
104 sk_make_sp<SkGammas>(std::move(red), std::move(green), std::move(blue));
msarettdc27a642016-06-06 12:02:31 -0700105 test_xform(r, gammas);
106}
107
108DEF_TEST(ColorSpaceXform_ExponentialGamma, r) {
109 // Exponential gamma curves
110 SkGammaCurve red, green, blue;
msarettb3906762016-06-22 14:07:48 -0700111 red.fValue = green.fValue = blue.fValue = 1.4f;
msarettdc27a642016-06-06 12:02:31 -0700112 sk_sp<SkGammas> gammas =
113 sk_make_sp<SkGammas>(std::move(red), std::move(green), std::move(blue));
114 test_xform(r, gammas);
115}