1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkM44.h"
9cb93a386Sopenharmony_ci#include "src/core/SkYUVMath.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci// in SkColorMatrix order (row-major)
12cb93a386Sopenharmony_ci// Created by running SkColorMatrix_DumpYUVMatrixTables()
13cb93a386Sopenharmony_ciconst float JPEG_full_rgb_to_yuv[] = {
14cb93a386Sopenharmony_ci      0.299000f,  0.587000f,  0.114000f,  0.000000f,  0.000000f,
15cb93a386Sopenharmony_ci     -0.168736f, -0.331264f,  0.500000f,  0.000000f,  0.501961f,
16cb93a386Sopenharmony_ci      0.500000f, -0.418688f, -0.081312f,  0.000000f,  0.501961f,
17cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
18cb93a386Sopenharmony_ci};
19cb93a386Sopenharmony_ciconst float JPEG_full_yuv_to_rgb[] = {
20cb93a386Sopenharmony_ci      1.000000f, -0.000000f,  1.402000f,  0.000000f, -0.703749f,
21cb93a386Sopenharmony_ci      1.000000f, -0.344136f, -0.714136f,  0.000000f,  0.531211f,
22cb93a386Sopenharmony_ci      1.000000f,  1.772000f,  0.000000f,  0.000000f, -0.889475f,
23cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
24cb93a386Sopenharmony_ci};
25cb93a386Sopenharmony_ciconst float Rec601_limited_rgb_to_yuv[] = {
26cb93a386Sopenharmony_ci      0.256788f,  0.504129f,  0.097906f,  0.000000f,  0.062745f,
27cb93a386Sopenharmony_ci     -0.148223f, -0.290993f,  0.439216f,  0.000000f,  0.501961f,
28cb93a386Sopenharmony_ci      0.439216f, -0.367788f, -0.071427f,  0.000000f,  0.501961f,
29cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
30cb93a386Sopenharmony_ci};
31cb93a386Sopenharmony_ciconst float Rec601_limited_yuv_to_rgb[] = {
32cb93a386Sopenharmony_ci      1.164384f, -0.000000f,  1.596027f,  0.000000f, -0.874202f,
33cb93a386Sopenharmony_ci      1.164384f, -0.391762f, -0.812968f,  0.000000f,  0.531668f,
34cb93a386Sopenharmony_ci      1.164384f,  2.017232f,  0.000000f,  0.000000f, -1.085631f,
35cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
36cb93a386Sopenharmony_ci};
37cb93a386Sopenharmony_ciconst float Rec709_full_rgb_to_yuv[] = {
38cb93a386Sopenharmony_ci      0.212600f,  0.715200f,  0.072200f,  0.000000f,  0.000000f,
39cb93a386Sopenharmony_ci     -0.114572f, -0.385428f,  0.500000f,  0.000000f,  0.501961f,
40cb93a386Sopenharmony_ci      0.500000f, -0.454153f, -0.045847f,  0.000000f,  0.501961f,
41cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
42cb93a386Sopenharmony_ci};
43cb93a386Sopenharmony_ciconst float Rec709_full_yuv_to_rgb[] = {
44cb93a386Sopenharmony_ci      1.000000f, -0.000000f,  1.574800f,  0.000000f, -0.790488f,
45cb93a386Sopenharmony_ci      1.000000f, -0.187324f, -0.468124f,  0.000000f,  0.329010f,
46cb93a386Sopenharmony_ci      1.000000f,  1.855600f, -0.000000f,  0.000000f, -0.931439f,
47cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
48cb93a386Sopenharmony_ci};
49cb93a386Sopenharmony_ciconst float Rec709_limited_rgb_to_yuv[] = {
50cb93a386Sopenharmony_ci      0.182586f,  0.614231f,  0.062007f,  0.000000f,  0.062745f,
51cb93a386Sopenharmony_ci     -0.100644f, -0.338572f,  0.439216f,  0.000000f,  0.501961f,
52cb93a386Sopenharmony_ci      0.439216f, -0.398942f, -0.040274f,  0.000000f,  0.501961f,
53cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
54cb93a386Sopenharmony_ci};
55cb93a386Sopenharmony_ciconst float Rec709_limited_yuv_to_rgb[] = {
56cb93a386Sopenharmony_ci      1.164384f, -0.000000f,  1.792741f,  0.000000f, -0.972945f,
57cb93a386Sopenharmony_ci      1.164384f, -0.213249f, -0.532909f,  0.000000f,  0.301483f,
58cb93a386Sopenharmony_ci      1.164384f,  2.112402f, -0.000000f,  0.000000f, -1.133402f,
59cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
60cb93a386Sopenharmony_ci};
61cb93a386Sopenharmony_ciconst float BT2020_8bit_full_rgb_to_yuv[] = {
62cb93a386Sopenharmony_ci      0.262700f,  0.678000f,  0.059300f,  0.000000f,  0.000000f,
63cb93a386Sopenharmony_ci     -0.139630f, -0.360370f,  0.500000f,  0.000000f,  0.501961f,
64cb93a386Sopenharmony_ci      0.500000f, -0.459786f, -0.040214f,  0.000000f,  0.501961f,
65cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
66cb93a386Sopenharmony_ci};
67cb93a386Sopenharmony_ciconst float BT2020_8bit_full_yuv_to_rgb[] = {
68cb93a386Sopenharmony_ci      1.000000f, -0.000000f,  1.474600f,  0.000000f, -0.740191f,
69cb93a386Sopenharmony_ci      1.000000f, -0.164553f, -0.571353f,  0.000000f,  0.369396f,
70cb93a386Sopenharmony_ci      1.000000f,  1.881400f, -0.000000f,  0.000000f, -0.944389f,
71cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
72cb93a386Sopenharmony_ci};
73cb93a386Sopenharmony_ciconst float BT2020_8bit_limited_rgb_to_yuv[] = {
74cb93a386Sopenharmony_ci      0.225613f,  0.582282f,  0.050928f,  0.000000f,  0.062745f,
75cb93a386Sopenharmony_ci     -0.122655f, -0.316560f,  0.439216f,  0.000000f,  0.501961f,
76cb93a386Sopenharmony_ci      0.439216f, -0.403890f, -0.035326f,  0.000000f,  0.501961f,
77cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
78cb93a386Sopenharmony_ci};
79cb93a386Sopenharmony_ciconst float BT2020_8bit_limited_yuv_to_rgb[] = {
80cb93a386Sopenharmony_ci      1.164384f, -0.000000f,  1.678674f,  0.000000f, -0.915688f,
81cb93a386Sopenharmony_ci      1.164384f, -0.187326f, -0.650424f,  0.000000f,  0.347458f,
82cb93a386Sopenharmony_ci      1.164384f,  2.141772f, -0.000000f,  0.000000f, -1.148145f,
83cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
84cb93a386Sopenharmony_ci};
85cb93a386Sopenharmony_ciconst float BT2020_10bit_full_rgb_to_yuv[] = {
86cb93a386Sopenharmony_ci      0.262700f,  0.678000f,  0.059300f,  0.000000f,  0.000000f,
87cb93a386Sopenharmony_ci     -0.139630f, -0.360370f,  0.500000f,  0.000000f,  0.500489f,
88cb93a386Sopenharmony_ci      0.500000f, -0.459786f, -0.040214f,  0.000000f,  0.500489f,
89cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
90cb93a386Sopenharmony_ci};
91cb93a386Sopenharmony_ciconst float BT2020_10bit_full_yuv_to_rgb[] = {
92cb93a386Sopenharmony_ci      1.000000f, -0.000000f,  1.474600f,  0.000000f, -0.738021f,
93cb93a386Sopenharmony_ci      1.000000f, -0.164553f, -0.571353f,  0.000000f,  0.368313f,
94cb93a386Sopenharmony_ci      1.000000f,  1.881400f, -0.000000f,  0.000000f, -0.941620f,
95cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
96cb93a386Sopenharmony_ci};
97cb93a386Sopenharmony_ciconst float BT2020_10bit_limited_rgb_to_yuv[] = {
98cb93a386Sopenharmony_ci      0.224951f,  0.580575f,  0.050779f,  0.000000f,  0.062561f,
99cb93a386Sopenharmony_ci     -0.122296f, -0.315632f,  0.437928f,  0.000000f,  0.500489f,
100cb93a386Sopenharmony_ci      0.437928f, -0.402706f, -0.035222f,  0.000000f,  0.500489f,
101cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
102cb93a386Sopenharmony_ci};
103cb93a386Sopenharmony_ciconst float BT2020_10bit_limited_yuv_to_rgb[] = {
104cb93a386Sopenharmony_ci      1.167808f, -0.000000f,  1.683611f,  0.000000f, -0.915688f,
105cb93a386Sopenharmony_ci      1.167808f, -0.187877f, -0.652337f,  0.000000f,  0.347458f,
106cb93a386Sopenharmony_ci      1.167808f,  2.148072f, -0.000000f,  0.000000f, -1.148145f,
107cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
108cb93a386Sopenharmony_ci};
109cb93a386Sopenharmony_ciconst float BT2020_12bit_full_rgb_to_yuv[] = {
110cb93a386Sopenharmony_ci      0.262700f,  0.678000f,  0.059300f,  0.000000f,  0.000000f,
111cb93a386Sopenharmony_ci     -0.139630f, -0.360370f,  0.500000f,  0.000000f,  0.500122f,
112cb93a386Sopenharmony_ci      0.500000f, -0.459786f, -0.040214f,  0.000000f,  0.500122f,
113cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
114cb93a386Sopenharmony_ci};
115cb93a386Sopenharmony_ciconst float BT2020_12bit_full_yuv_to_rgb[] = {
116cb93a386Sopenharmony_ci      1.000000f, -0.000000f,  1.474600f,  0.000000f, -0.737480f,
117cb93a386Sopenharmony_ci      1.000000f, -0.164553f, -0.571353f,  0.000000f,  0.368043f,
118cb93a386Sopenharmony_ci      1.000000f,  1.881400f, -0.000000f,  0.000000f, -0.940930f,
119cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
120cb93a386Sopenharmony_ci};
121cb93a386Sopenharmony_ciconst float BT2020_12bit_limited_rgb_to_yuv[] = {
122cb93a386Sopenharmony_ci      0.224787f,  0.580149f,  0.050742f,  0.000000f,  0.062515f,
123cb93a386Sopenharmony_ci     -0.122206f, -0.315401f,  0.437607f,  0.000000f,  0.500122f,
124cb93a386Sopenharmony_ci      0.437607f, -0.402411f, -0.035196f,  0.000000f,  0.500122f,
125cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
126cb93a386Sopenharmony_ci};
127cb93a386Sopenharmony_ciconst float BT2020_12bit_limited_yuv_to_rgb[] = {
128cb93a386Sopenharmony_ci      1.168664f, -0.000000f,  1.684846f,  0.000000f, -0.915688f,
129cb93a386Sopenharmony_ci      1.168664f, -0.188015f, -0.652816f,  0.000000f,  0.347458f,
130cb93a386Sopenharmony_ci      1.168664f,  2.149647f, -0.000000f,  0.000000f, -1.148145f,
131cb93a386Sopenharmony_ci      0.000000f,  0.000000f,  0.000000f,  1.000000f,  0.000000f,
132cb93a386Sopenharmony_ci};
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_cistatic_assert(kJPEG_Full_SkYUVColorSpace            == 0, "");
135cb93a386Sopenharmony_cistatic_assert(kRec601_Limited_SkYUVColorSpace       == 1, "");
136cb93a386Sopenharmony_cistatic_assert(kRec709_Full_SkYUVColorSpace          == 2, "");
137cb93a386Sopenharmony_cistatic_assert(kRec709_Limited_SkYUVColorSpace       == 3, "");
138cb93a386Sopenharmony_cistatic_assert(kBT2020_8bit_Full_SkYUVColorSpace     == 4, "");
139cb93a386Sopenharmony_cistatic_assert(kBT2020_8bit_Limited_SkYUVColorSpace  == 5, "");
140cb93a386Sopenharmony_cistatic_assert(kBT2020_10bit_Full_SkYUVColorSpace    == 6, "");
141cb93a386Sopenharmony_cistatic_assert(kBT2020_10bit_Limited_SkYUVColorSpace == 7, "");
142cb93a386Sopenharmony_cistatic_assert(kBT2020_12bit_Full_SkYUVColorSpace    == 8, "");
143cb93a386Sopenharmony_cistatic_assert(kBT2020_12bit_Limited_SkYUVColorSpace == 9, "");
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_ciconst float* yuv_to_rgb_array[] = {
146cb93a386Sopenharmony_ci    JPEG_full_yuv_to_rgb,
147cb93a386Sopenharmony_ci    Rec601_limited_yuv_to_rgb,
148cb93a386Sopenharmony_ci    Rec709_full_yuv_to_rgb,
149cb93a386Sopenharmony_ci    Rec709_limited_yuv_to_rgb,
150cb93a386Sopenharmony_ci    BT2020_8bit_full_yuv_to_rgb,
151cb93a386Sopenharmony_ci    BT2020_8bit_limited_yuv_to_rgb,
152cb93a386Sopenharmony_ci    BT2020_10bit_full_yuv_to_rgb,
153cb93a386Sopenharmony_ci    BT2020_10bit_limited_yuv_to_rgb,
154cb93a386Sopenharmony_ci    BT2020_12bit_full_yuv_to_rgb,
155cb93a386Sopenharmony_ci    BT2020_12bit_limited_yuv_to_rgb,
156cb93a386Sopenharmony_ci};
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ciconst float* rgb_to_yuv_array[] = {
159cb93a386Sopenharmony_ci    JPEG_full_rgb_to_yuv,
160cb93a386Sopenharmony_ci    Rec601_limited_rgb_to_yuv,
161cb93a386Sopenharmony_ci    Rec709_full_rgb_to_yuv,
162cb93a386Sopenharmony_ci    Rec709_limited_rgb_to_yuv,
163cb93a386Sopenharmony_ci    BT2020_8bit_full_rgb_to_yuv,
164cb93a386Sopenharmony_ci    BT2020_8bit_limited_rgb_to_yuv,
165cb93a386Sopenharmony_ci    BT2020_10bit_full_rgb_to_yuv,
166cb93a386Sopenharmony_ci    BT2020_10bit_limited_rgb_to_yuv,
167cb93a386Sopenharmony_ci    BT2020_12bit_full_rgb_to_yuv,
168cb93a386Sopenharmony_ci    BT2020_12bit_limited_rgb_to_yuv,
169cb93a386Sopenharmony_ci};
170cb93a386Sopenharmony_ci
171cb93a386Sopenharmony_ciconstexpr size_t kSizeOfColorMatrix = 20 * sizeof(float);
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_civoid SkColorMatrix_RGB2YUV(SkYUVColorSpace cs, float m[20]) {
174cb93a386Sopenharmony_ci    if ((unsigned)cs < (unsigned)kIdentity_SkYUVColorSpace) {
175cb93a386Sopenharmony_ci        memcpy(m, rgb_to_yuv_array[(unsigned)cs], kSizeOfColorMatrix);
176cb93a386Sopenharmony_ci    } else {
177cb93a386Sopenharmony_ci        memset(m, 0, kSizeOfColorMatrix);
178cb93a386Sopenharmony_ci        m[0] = m[6] = m[12] = m[18] = 1;
179cb93a386Sopenharmony_ci    }
180cb93a386Sopenharmony_ci}
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_civoid SkColorMatrix_YUV2RGB(SkYUVColorSpace cs, float m[20]) {
183cb93a386Sopenharmony_ci    if ((unsigned)cs < (unsigned)kIdentity_SkYUVColorSpace) {
184cb93a386Sopenharmony_ci        memcpy(m, yuv_to_rgb_array[(unsigned)cs], kSizeOfColorMatrix);
185cb93a386Sopenharmony_ci    } else {
186cb93a386Sopenharmony_ci        memset(m, 0, kSizeOfColorMatrix);
187cb93a386Sopenharmony_ci        m[0] = m[6] = m[12] = m[18] = 1;
188cb93a386Sopenharmony_ci    }
189cb93a386Sopenharmony_ci}
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci// we just drop the alpha rol/col from the colormatrix
194cb93a386Sopenharmony_ci// output is |        tr |
195cb93a386Sopenharmony_ci//           |  3x3   tg |
196cb93a386Sopenharmony_ci//           |        tb |
197cb93a386Sopenharmony_ci//           | 0 0 0  1  |
198cb93a386Sopenharmony_cistatic void colormatrix_to_matrix44(const float src[20], SkM44* dst) {
199cb93a386Sopenharmony_ci    *dst = SkM44(src[ 0], src[ 1], src[ 2], src[ 4],
200cb93a386Sopenharmony_ci                 src[ 5], src[ 6], src[ 7], src[ 9],
201cb93a386Sopenharmony_ci                 src[10], src[11], src[12], src[14],
202cb93a386Sopenharmony_ci                       0,       0,       0,       1);
203cb93a386Sopenharmony_ci}
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_ci// input: ignore the bottom row
206cb93a386Sopenharmony_ci// output: inject identity row/column for alpha
207cb93a386Sopenharmony_cistatic void matrix44_to_colormatrix(const SkM44& src, float dst[20]) {
208cb93a386Sopenharmony_ci    dst[0] = src.rc(0,0);
209cb93a386Sopenharmony_ci    dst[1] = src.rc(0,1);
210cb93a386Sopenharmony_ci    dst[2] = src.rc(0,2);
211cb93a386Sopenharmony_ci    dst[3] = 0;
212cb93a386Sopenharmony_ci    dst[4] = src.rc(0,3);    // tx
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci    dst[5] = src.rc(1,0);
215cb93a386Sopenharmony_ci    dst[6] = src.rc(1,1);
216cb93a386Sopenharmony_ci    dst[7] = src.rc(1,2);
217cb93a386Sopenharmony_ci    dst[8] = 0;
218cb93a386Sopenharmony_ci    dst[9] = src.rc(1,3);    // ty
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci    dst[10] = src.rc(2,0);
221cb93a386Sopenharmony_ci    dst[11] = src.rc(2,1);
222cb93a386Sopenharmony_ci    dst[12] = src.rc(2,2);
223cb93a386Sopenharmony_ci    dst[13] = 0;
224cb93a386Sopenharmony_ci    dst[14] = src.rc(2,3);   // tz
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci    dst[15] = dst[16] = dst[17] = dst[19] = 0;
227cb93a386Sopenharmony_ci    dst[18] = 1;
228cb93a386Sopenharmony_ci}
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_cistatic void scale3(float m[], float s) {
231cb93a386Sopenharmony_ci    for (int i = 0; i < 3; ++i) {
232cb93a386Sopenharmony_ci        m[i] *= s;
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci}
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_cinamespace {
237cb93a386Sopenharmony_cienum Range { kFull, kLimited };
238cb93a386Sopenharmony_cistruct YUVCoeff {
239cb93a386Sopenharmony_ci    float   Kr, Kb;
240cb93a386Sopenharmony_ci    int     bits;
241cb93a386Sopenharmony_ci    Range   range;
242cb93a386Sopenharmony_ci};
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ciconst YUVCoeff gCoeff[] = {
245cb93a386Sopenharmony_ci    { 0.2990f, 0.1140f,  8, kFull    }, // kJPEG_Full_SkYUVColorSpace
246cb93a386Sopenharmony_ci    { 0.2990f, 0.1140f,  8, kLimited }, // kRec601_Limited_SkYUVColorSpace
247cb93a386Sopenharmony_ci    { 0.2126f, 0.0722f,  8, kFull    }, // kRec709_Full_SkYUVColorSpace
248cb93a386Sopenharmony_ci    { 0.2126f, 0.0722f,  8, kLimited }, // kRec709_Limited_SkYUVColorSpace
249cb93a386Sopenharmony_ci    { 0.2627f, 0.0593f,  8, kFull    }, // kBT2020_8bit_Full_SkYUVColorSpace
250cb93a386Sopenharmony_ci    { 0.2627f, 0.0593f,  8, kLimited }, // kBT2020_8bit_Limited_SkYUVColorSpace
251cb93a386Sopenharmony_ci    { 0.2627f, 0.0593f, 10, kFull    }, // kBT2020_10bit_Full_SkYUVColorSpace
252cb93a386Sopenharmony_ci    { 0.2627f, 0.0593f, 10, kLimited }, // kBT2020_10bit_Limited_SkYUVColorSpace
253cb93a386Sopenharmony_ci    { 0.2627f, 0.0593f, 12, kFull    }, // kBT2020_12bit_Full_SkYUVColorSpace
254cb93a386Sopenharmony_ci    { 0.2627f, 0.0593f, 12, kLimited }, // kBT2020_12bit_Limited_SkYUVColorSpace
255cb93a386Sopenharmony_ci};
256cb93a386Sopenharmony_ci}  // namespace
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_cistatic void make_rgb_to_yuv_matrix(float mx[20], const YUVCoeff& c) {
259cb93a386Sopenharmony_ci    SkASSERT(c.bits >= 8);
260cb93a386Sopenharmony_ci    const float Kr = c.Kr;
261cb93a386Sopenharmony_ci    const float Kb = c.Kb;
262cb93a386Sopenharmony_ci    const float Kg = 1.0f - Kr - Kb;
263cb93a386Sopenharmony_ci    const float Cr = 0.5f / (1.0f - Kb);
264cb93a386Sopenharmony_ci    const float Cb = 0.5f / (1.0f - Kr);
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ci    const int shift = c.bits - 8;
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_ci    const float denom = static_cast<float>((1 << c.bits) - 1);
269cb93a386Sopenharmony_ci    float scaleY  = 1.0f,
270cb93a386Sopenharmony_ci          addY    = 0.0f,
271cb93a386Sopenharmony_ci          scaleUV = 1.0f,
272cb93a386Sopenharmony_ci          addUV   = (128 << shift) / denom;
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci    if (c.range == kLimited) {
275cb93a386Sopenharmony_ci        scaleY  = (219 << shift) / denom;
276cb93a386Sopenharmony_ci        addY    = ( 16 << shift) / denom;
277cb93a386Sopenharmony_ci        scaleUV = (224 << shift) / denom;
278cb93a386Sopenharmony_ci    }
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci    float m[20] = {
281cb93a386Sopenharmony_ci          Kr,  Kg,   Kb,  0,  addY,
282cb93a386Sopenharmony_ci         -Kr, -Kg, 1-Kb,  0, addUV,
283cb93a386Sopenharmony_ci        1-Kr, -Kg,  -Kb,  0, addUV,
284cb93a386Sopenharmony_ci           0,   0,    0,  1,     0,
285cb93a386Sopenharmony_ci    };
286cb93a386Sopenharmony_ci    memcpy(mx, m, sizeof(m));
287cb93a386Sopenharmony_ci    scale3(mx +  0,      scaleY );
288cb93a386Sopenharmony_ci    scale3(mx +  5, Cr * scaleUV);
289cb93a386Sopenharmony_ci    scale3(mx + 10, Cb * scaleUV);
290cb93a386Sopenharmony_ci}
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_cistatic void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv) {
293cb93a386Sopenharmony_ci    const char* names[] = {
294cb93a386Sopenharmony_ci        "JPEG_full",
295cb93a386Sopenharmony_ci        "Rec601_limited",
296cb93a386Sopenharmony_ci        "Rec709_full",
297cb93a386Sopenharmony_ci        "Rec709_limited",
298cb93a386Sopenharmony_ci        "BT2020_8bit_full",
299cb93a386Sopenharmony_ci        "BT2020_8bit_limited",
300cb93a386Sopenharmony_ci        "BT2020_10bit_full",
301cb93a386Sopenharmony_ci        "BT2020_10bit_limited",
302cb93a386Sopenharmony_ci        "BT2020_12bit_full",
303cb93a386Sopenharmony_ci        "BT2020_12bit_limited",
304cb93a386Sopenharmony_ci    };
305cb93a386Sopenharmony_ci    const char* dirnames[] = {
306cb93a386Sopenharmony_ci        "yuv_to_rgb", "rgb_to_yuv",
307cb93a386Sopenharmony_ci    };
308cb93a386Sopenharmony_ci    SkDebugf("const float %s_%s[] = {\n", names[cs], dirnames[rgb2yuv]);
309cb93a386Sopenharmony_ci    for (int i = 0; i < 4; ++i) {
310cb93a386Sopenharmony_ci        SkDebugf("    ");
311cb93a386Sopenharmony_ci        for (int j = 0; j < 5; ++j) {
312cb93a386Sopenharmony_ci            SkDebugf(" %9.6ff,", m[i * 5 + j]);
313cb93a386Sopenharmony_ci        }
314cb93a386Sopenharmony_ci        SkDebugf("\n");
315cb93a386Sopenharmony_ci    }
316cb93a386Sopenharmony_ci    SkDebugf("};\n");
317cb93a386Sopenharmony_ci}
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci// Used to create the prebuilt tables for each colorspace.
320cb93a386Sopenharmony_ci// Don't remove this function, in case we want to recompute those tables in the future.
321cb93a386Sopenharmony_civoid SkColorMatrix_DumpYUVMatrixTables() {
322cb93a386Sopenharmony_ci    for (int i = 0; i < kLastEnum_SkYUVColorSpace; ++i) {
323cb93a386Sopenharmony_ci        SkYUVColorSpace cs = static_cast<SkYUVColorSpace>(i);
324cb93a386Sopenharmony_ci        float m[20];
325cb93a386Sopenharmony_ci        make_rgb_to_yuv_matrix(m, gCoeff[(unsigned)cs]);
326cb93a386Sopenharmony_ci        dump(m, cs, true);
327cb93a386Sopenharmony_ci        SkM44 m44, im44;
328cb93a386Sopenharmony_ci        colormatrix_to_matrix44(m, &m44);
329cb93a386Sopenharmony_ci        float im[20];
330cb93a386Sopenharmony_ci#ifdef SK_DEBUG
331cb93a386Sopenharmony_ci        // be sure our coversion between matrix44 and colormatrix is perfect
332cb93a386Sopenharmony_ci        matrix44_to_colormatrix(m44, im);
333cb93a386Sopenharmony_ci        SkASSERT(memcmp(m, im, sizeof(im)) == 0);
334cb93a386Sopenharmony_ci#endif
335cb93a386Sopenharmony_ci        SkAssertResult(m44.invert(&im44));
336cb93a386Sopenharmony_ci        matrix44_to_colormatrix(im44, im);
337cb93a386Sopenharmony_ci        dump(im, cs, false);
338cb93a386Sopenharmony_ci    }
339cb93a386Sopenharmony_ci}
340