blob: 7091946bbb75d3325737a9f0485e049e87440156 [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:
mtkleinb4359632016-07-18 11:16:14 -070018 static std::unique_ptr<SkColorSpaceXform> CreateIdentityXform(const sk_sp<SkGammas>& gammas) {
19 // Logically we can pass any matrix here. For simplicty, pass I(), i.e. D50 XYZ gamut.
20 sk_sp<SkColorSpace> space(new SkColorSpace_Base(nullptr, gammas, SkMatrix::I(), nullptr));
21 return SkColorSpaceXform::New(space, space);
msarettdc27a642016-06-06 12:02:31 -070022 }
23};
24
msarettb3906762016-06-22 14:07:48 -070025static bool almost_equal(int x, int y) {
26 return SkTAbs(x - y) <= 1;
27}
28
mtkleinb4359632016-07-18 11:16:14 -070029static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas) {
msarettdc27a642016-06-06 12:02:31 -070030 // Arbitrary set of 10 pixels
31 constexpr int width = 10;
32 constexpr uint32_t srcPixels[width] = {
33 0xFFABCDEF, 0xFF146829, 0xFF382759, 0xFF184968, 0xFFDE8271,
msarettb3906762016-06-22 14:07:48 -070034 0xFF32AB52, 0xFF0383BC, 0xFF000102, 0xFFFFFFFF, 0xFFDDEEFF, };
msarettdc27a642016-06-06 12:02:31 -070035 uint32_t dstPixels[width];
36
mtkleinb4359632016-07-18 11:16:14 -070037 // Create and perform an identity xform.
38 std::unique_ptr<SkColorSpaceXform> xform = ColorSpaceXformTest::CreateIdentityXform(gammas);
msarett9ce3a542016-07-15 13:54:38 -070039 xform->applyTo8888(dstPixels, srcPixels, width);
msarettdc27a642016-06-06 12:02:31 -070040
mtkleinb4359632016-07-18 11:16:14 -070041 // Since the src->dst matrix is the identity, and the gamma curves match,
42 // the pixels should be unchanged.
msarettdc27a642016-06-06 12:02:31 -070043 for (int i = 0; i < width; i++) {
msarettb3906762016-06-22 14:07:48 -070044 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 0) & 0xFF),
45 SkGetPackedR32(dstPixels[i])));
46 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 8) & 0xFF),
47 SkGetPackedG32(dstPixels[i])));
48 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 16) & 0xFF),
49 SkGetPackedB32(dstPixels[i])));
50 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF),
51 SkGetPackedA32(dstPixels[i])));
msarettdc27a642016-06-06 12:02:31 -070052 }
53}
54
55DEF_TEST(ColorSpaceXform_TableGamma, r) {
56 // Lookup-table based gamma curves
57 SkGammaCurve red, green, blue;
58 constexpr size_t tableSize = 10;
59 red.fTable = std::unique_ptr<float[]>(new float[tableSize]);
60 green.fTable = std::unique_ptr<float[]>(new float[tableSize]);
61 blue.fTable = std::unique_ptr<float[]>(new float[tableSize]);
62 red.fTableSize = green.fTableSize = blue.fTableSize = 10;
63 red.fTable[0] = green.fTable[0] = blue.fTable[0] = 0.00f;
64 red.fTable[1] = green.fTable[1] = blue.fTable[1] = 0.05f;
65 red.fTable[2] = green.fTable[2] = blue.fTable[2] = 0.10f;
66 red.fTable[3] = green.fTable[3] = blue.fTable[3] = 0.15f;
67 red.fTable[4] = green.fTable[4] = blue.fTable[4] = 0.25f;
68 red.fTable[5] = green.fTable[5] = blue.fTable[5] = 0.35f;
69 red.fTable[6] = green.fTable[6] = blue.fTable[6] = 0.45f;
70 red.fTable[7] = green.fTable[7] = blue.fTable[7] = 0.60f;
71 red.fTable[8] = green.fTable[8] = blue.fTable[8] = 0.75f;
72 red.fTable[9] = green.fTable[9] = blue.fTable[9] = 1.00f;
73 sk_sp<SkGammas> gammas =
74 sk_make_sp<SkGammas>(std::move(red), std::move(green), std::move(blue));
mtkleinb4359632016-07-18 11:16:14 -070075 test_identity_xform(r, gammas);
msarettdc27a642016-06-06 12:02:31 -070076}
77
78DEF_TEST(ColorSpaceXform_ParametricGamma, r) {
79 // Parametric gamma curves
80 SkGammaCurve red, green, blue;
81
msarettb3906762016-06-22 14:07:48 -070082 // Interval, switch xforms at 0.0031308f
83 red.fD = green.fD = blue.fD = 0.04045f;
msarettdc27a642016-06-06 12:02:31 -070084
msarettb3906762016-06-22 14:07:48 -070085 // First equation:
86 red.fE = green.fE = blue.fE = 1.0f / 12.92f;
msarettdc27a642016-06-06 12:02:31 -070087
msarettb3906762016-06-22 14:07:48 -070088 // Second equation:
89 // Note that the function is continuous (it's actually sRGB).
90 red.fA = green.fA = blue.fA = 1.0f / 1.055f;
91 red.fB = green.fB = blue.fB = 0.055f / 1.055f;
92 red.fC = green.fC = blue.fC = 0.0f;
93 red.fG = green.fG = blue.fG = 2.4f;
94 sk_sp<SkGammas> gammas =
95 sk_make_sp<SkGammas>(std::move(red), std::move(green), std::move(blue));
mtkleinb4359632016-07-18 11:16:14 -070096 test_identity_xform(r, gammas);
msarettdc27a642016-06-06 12:02:31 -070097}
98
99DEF_TEST(ColorSpaceXform_ExponentialGamma, r) {
100 // Exponential gamma curves
101 SkGammaCurve red, green, blue;
msarettb3906762016-06-22 14:07:48 -0700102 red.fValue = green.fValue = blue.fValue = 1.4f;
msarettdc27a642016-06-06 12:02:31 -0700103 sk_sp<SkGammas> gammas =
104 sk_make_sp<SkGammas>(std::move(red), std::move(green), std::move(blue));
mtkleinb4359632016-07-18 11:16:14 -0700105 test_identity_xform(r, gammas);
msarettdc27a642016-06-06 12:02:31 -0700106}