1 /*
2 * Copyright 2020 Google LLC
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 "src/ports/SkNDKConversions.h"
9
10 namespace {
11 static const struct {
12 SkColorType colorType;
13 AndroidBitmapFormat format;
14 } gColorTypeTable[] = {
15 { kRGBA_8888_SkColorType, ANDROID_BITMAP_FORMAT_RGBA_8888 },
16 { kRGBA_F16_SkColorType, ANDROID_BITMAP_FORMAT_RGBA_F16 },
17 { kRGB_565_SkColorType, ANDROID_BITMAP_FORMAT_RGB_565 },
18 // Android allows using its alpha 8 format to get 8 bit gray pixels.
19 { kGray_8_SkColorType, ANDROID_BITMAP_FORMAT_A_8 },
20 };
21
22 } // anonymous namespace
23
24 namespace SkNDKConversions {
toAndroidBitmapFormat(SkColorType colorType)25 AndroidBitmapFormat toAndroidBitmapFormat(SkColorType colorType) {
26 for (const auto& entry : gColorTypeTable) {
27 if (entry.colorType == colorType) {
28 return entry.format;
29 }
30 }
31 return ANDROID_BITMAP_FORMAT_NONE;
32 }
33
toColorType(AndroidBitmapFormat format)34 SkColorType toColorType(AndroidBitmapFormat format) {
35 for (const auto& entry : gColorTypeTable) {
36 if (entry.format == format) {
37 return entry.colorType;
38 }
39 }
40 return kUnknown_SkColorType;
41 }
42
43 } // SkNDKConversions
44
45 static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
46
47 static constexpr skcms_Matrix3x3 kDCIP3 = {{
48 {0.486143, 0.323835, 0.154234},
49 {0.226676, 0.710327, 0.0629966},
50 {0.000800549, 0.0432385, 0.78275},
51 }};
52
53 namespace {
54 static const struct {
55 ADataSpace dataSpace;
56 skcms_TransferFunction transferFunction;
57 skcms_Matrix3x3 gamut;
58 } gColorSpaceTable[] = {
59 { ADATASPACE_SRGB, SkNamedTransferFn::kSRGB, SkNamedGamut::kSRGB },
60 { ADATASPACE_SCRGB, SkNamedTransferFn::kSRGB, SkNamedGamut::kSRGB },
61 { ADATASPACE_SCRGB_LINEAR, SkNamedTransferFn::kLinear, SkNamedGamut::kSRGB },
62 { ADATASPACE_SRGB_LINEAR, SkNamedTransferFn::kLinear, SkNamedGamut::kSRGB },
63 { ADATASPACE_ADOBE_RGB, SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB },
64 { ADATASPACE_DISPLAY_P3, SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3 },
65 { ADATASPACE_BT2020, SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020 },
66 { ADATASPACE_BT709, SkNamedTransferFn::kRec2020, SkNamedGamut::kSRGB },
67 { ADATASPACE_DCI_P3, k2Dot6, kDCIP3 },
68 };
69
70 } // anonymous namespace
71
nearly_equal(float a,float b)72 static bool nearly_equal(float a, float b) {
73 return fabs(a - b) < .002f;
74 }
75
nearly_equal(const skcms_TransferFunction & x,const skcms_TransferFunction & y)76 static bool nearly_equal(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
77 return nearly_equal(x.g, y.g)
78 && nearly_equal(x.a, y.a)
79 && nearly_equal(x.b, y.b)
80 && nearly_equal(x.c, y.c)
81 && nearly_equal(x.d, y.d)
82 && nearly_equal(x.e, y.e)
83 && nearly_equal(x.f, y.f);
84 }
85
nearly_equal(const skcms_Matrix3x3 & a,const skcms_Matrix3x3 & b)86 static bool nearly_equal(const skcms_Matrix3x3& a, const skcms_Matrix3x3& b) {
87 for (int i = 0; i < 3; i++)
88 for (int j = 0; j < 3; j++) {
89 if (!nearly_equal(a.vals[i][j], b.vals[i][j])) return false;
90 }
91 return true;
92 }
93
94 namespace SkNDKConversions {
toDataSpace(SkColorSpace * cs)95 ADataSpace toDataSpace(SkColorSpace* cs) {
96 if (!cs) return ADATASPACE_SRGB;
97
98 skcms_TransferFunction fn;
99 skcms_Matrix3x3 gamut;
100 if (cs->isNumericalTransferFn(&fn) && cs->toXYZD50(&gamut)) {
101 for (const auto& entry : gColorSpaceTable) {
102 if (nearly_equal(gamut, entry.gamut) && nearly_equal(fn, entry.transferFunction)) {
103 return entry.dataSpace;
104 }
105 }
106 }
107 return ADATASPACE_UNKNOWN;
108 }
109
toColorSpace(ADataSpace dataSpace)110 sk_sp<SkColorSpace> toColorSpace(ADataSpace dataSpace) {
111 for (const auto& entry : gColorSpaceTable) {
112 if (entry.dataSpace == dataSpace) {
113 return SkColorSpace::MakeRGB(entry.transferFunction, entry.gamut);
114 }
115 }
116 return nullptr;
117 }
118 }
119
120