• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "include/core/SkColorSpace.h"
9 #include "include/core/SkData.h"
10 #include "include/core/SkICC.h"
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkTypes.h"
13 #include "modules/skcms/skcms.h"
14 #include "tests/Test.h"
15 #include "tools/Resources.h"
16 
17 #include <cmath>
18 #include <cstdint>
19 #include <cstdlib>
20 
DEF_TEST(AdobeRGB,r)21 DEF_TEST(AdobeRGB, r) {
22     if (sk_sp<SkData> profile = GetResourceAsData("icc_profiles/AdobeRGB1998.icc")) {
23         skcms_ICCProfile parsed;
24         REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed));
25         REPORTER_ASSERT(r, !parsed.has_CICP);
26 
27         auto got  = SkColorSpace::Make(parsed);
28         auto want = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
29         REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), want.get()));
30     }
31 }
32 
DEF_TEST(HDR_ICC,r)33 DEF_TEST(HDR_ICC, r) {
34     constexpr size_t kTestCount = 3;
35     SK_API sk_sp<SkData> profile[kTestCount] = {
36             SkWriteICCProfile(SkNamedTransferFn::kPQ, SkNamedGamut::kRec2020),
37             SkWriteICCProfile(SkNamedTransferFn::kHLG, SkNamedGamut::kDisplayP3),
38             SkWriteICCProfile(SkNamedTransferFn::kSRGB, SkNamedGamut::kSRGB),
39     };
40 
41     SK_API sk_sp<SkData> dst_profile[kTestCount] = {
42             SkWriteICCProfile(SkNamedTransferFn::kLinear, SkNamedGamut::kRec2020),
43             SkWriteICCProfile(SkNamedTransferFn::kLinear, SkNamedGamut::kDisplayP3),
44             SkWriteICCProfile(SkNamedTransferFn::kLinear, SkNamedGamut::kSRGB),
45     };
46 
47     constexpr size_t kPixelCount = 6;
48 
49     // clang-format off
50     float pixels[kPixelCount][3] = {
51             { 0.0f, 0.0f, 0.0f, },
52             { 0.5f, 0.5f, 0.5f, },
53             { 0.5f, 0.0f, 0.0f, },
54             { 0.0f, 0.5f, 0.0f, },
55             { 0.0f, 0.0f, 0.5f, },
56             { 1.0f, 1.0f, 1.0f, },
57     };
58     float dst_pixels_expected[kTestCount][kPixelCount][3] = {
59             {
60                     { 0.f,     0.f,     0.f,     },
61                     { 0.3126f, 0.3125f, 0.3125f, },
62                     { 0.4061f, 0.f,     0.f,     },
63                     { 0.f,     0.3475f, 0.f,     },
64                     { 0.f,     0.f,     0.4426f, },
65                     { 1.f,     1.f,     1.f,     },
66             },
67             {
68                     { 0.f,     0.f,     0.f,     },
69                     { 0.1044f, 0.1044f, 0.1044f, },
70                     { 0.1044f, 0.f,     0.f,     },
71                     { 0.f,     0.1044f, 0.f,     },
72                     { 0.f,     0.f,     0.1044f, },
73                     { 1.f,     1.f,     1.f,     },
74             },
75             {
76                     { 0.f,     0.0f,    0.0f,    },
77                     { 0.2140f, 0.2140f, 0.2140f, },
78                     { 0.2140f, 0.0f,    0.0f,    },
79                     { 0.0f,    0.2140f, 0.0f,    },
80                     { 0.0f,    0.0f,    0.2140f, },
81                     { 1.0f,    1.0f,    1.0f,    },
82             },
83     };
84     // clang-format on
85     bool cicp_expected[kTestCount] = {true, true, false};
86     bool a2b_expected[kTestCount] = {true, false, false};
87     uint32_t cicp_primaries_expected[kTestCount] = {9, 12, 0};
88     uint32_t cicp_trfn_expected[kTestCount] = {16, 18, 0};
89 
90     for (size_t test = 0; test < kTestCount; ++test) {
91         skcms_ICCProfile parsed;
92         REPORTER_ASSERT(r, skcms_Parse(profile[test]->data(), profile[test]->size(), &parsed));
93 
94         REPORTER_ASSERT(r, parsed.has_A2B == a2b_expected[test]);
95         REPORTER_ASSERT(r, parsed.has_CICP == cicp_expected[test]);
96         if (cicp_expected[test]) {
97             REPORTER_ASSERT(r, parsed.CICP.color_primaries == cicp_primaries_expected[test]);
98             REPORTER_ASSERT(r, parsed.CICP.transfer_characteristics == cicp_trfn_expected[test]);
99             REPORTER_ASSERT(r, parsed.CICP.matrix_coefficients == 0);
100             REPORTER_ASSERT(r, parsed.CICP.video_full_range_flag == 1);
101         }
102 
103         skcms_ICCProfile dst_parsed;
104         REPORTER_ASSERT(
105                 r, skcms_Parse(dst_profile[test]->data(), dst_profile[test]->size(), &dst_parsed));
106 
107         for (size_t pixel = 0; pixel < kPixelCount; ++pixel) {
108             float dst_pixel_actual[3]{0.f, 0.f, 0.f};
109             bool xform_result = skcms_Transform(pixels[pixel],
110                                                 skcms_PixelFormat_RGB_fff,
111                                                 skcms_AlphaFormat_Opaque,
112                                                 &parsed,
113                                                 dst_pixel_actual,
114                                                 skcms_PixelFormat_RGB_fff,
115                                                 skcms_AlphaFormat_Opaque,
116                                                 &dst_parsed,
117                                                 1);
118             REPORTER_ASSERT(r, xform_result);
119 
120             auto approx_equal = [=](float x, float y) { return std::abs(x - y) < 1e-3f; };
121             for (size_t i = 0; i < 3; ++i) {
122                 REPORTER_ASSERT(
123                         r, approx_equal(dst_pixel_actual[i], dst_pixels_expected[test][pixel][i]));
124             }
125         }
126     }
127 }
128