1 /*
2 * Copyright 2011 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/effects/SkColorMatrix.h"
9 #include "src/core/SkYUVMath.h"
10
RGBtoYUV(SkYUVColorSpace cs)11 SkColorMatrix SkColorMatrix::RGBtoYUV(SkYUVColorSpace cs) {
12 SkColorMatrix m;
13 SkColorMatrix_RGB2YUV(cs, m.fMat.data());
14 return m;
15 }
16
YUVtoRGB(SkYUVColorSpace cs)17 SkColorMatrix SkColorMatrix::YUVtoRGB(SkYUVColorSpace cs) {
18 SkColorMatrix m;
19 SkColorMatrix_YUV2RGB(cs, m.fMat.data());
20 return m;
21 }
22
23 enum {
24 kR_Scale = 0,
25 kG_Scale = 6,
26 kB_Scale = 12,
27 kA_Scale = 18,
28
29 kR_Trans = 4,
30 kG_Trans = 9,
31 kB_Trans = 14,
32 kA_Trans = 19,
33 };
34
set_concat(float result[20],const float outer[20],const float inner[20])35 static void set_concat(float result[20], const float outer[20], const float inner[20]) {
36 float tmp[20];
37 float* target;
38
39 if (outer == result || inner == result) {
40 target = tmp; // will memcpy answer when we're done into result
41 } else {
42 target = result;
43 }
44
45 int index = 0;
46 for (int j = 0; j < 20; j += 5) {
47 for (int i = 0; i < 4; i++) {
48 target[index++] = outer[j + 0] * inner[i + 0] +
49 outer[j + 1] * inner[i + 5] +
50 outer[j + 2] * inner[i + 10] +
51 outer[j + 3] * inner[i + 15];
52 }
53 target[index++] = outer[j + 0] * inner[4] +
54 outer[j + 1] * inner[9] +
55 outer[j + 2] * inner[14] +
56 outer[j + 3] * inner[19] +
57 outer[j + 4];
58 }
59
60 if (target != result) {
61 std::copy_n(target, 20, result);
62 }
63 }
64
setIdentity()65 void SkColorMatrix::setIdentity() {
66 fMat.fill(0.0f);
67 fMat[kR_Scale] = fMat[kG_Scale] = fMat[kB_Scale] = fMat[kA_Scale] = 1;
68 }
69
setScale(float rScale,float gScale,float bScale,float aScale)70 void SkColorMatrix::setScale(float rScale, float gScale, float bScale, float aScale) {
71 fMat.fill(0.0f);
72 fMat[kR_Scale] = rScale;
73 fMat[kG_Scale] = gScale;
74 fMat[kB_Scale] = bScale;
75 fMat[kA_Scale] = aScale;
76 }
77
postTranslate(float dr,float dg,float db,float da)78 void SkColorMatrix::postTranslate(float dr, float dg, float db, float da) {
79 fMat[kR_Trans] += dr;
80 fMat[kG_Trans] += dg;
81 fMat[kB_Trans] += db;
82 fMat[kA_Trans] += da;
83 }
84
85 ///////////////////////////////////////////////////////////////////////////////
86
setConcat(const SkColorMatrix & matA,const SkColorMatrix & matB)87 void SkColorMatrix::setConcat(const SkColorMatrix& matA, const SkColorMatrix& matB) {
88 set_concat(fMat.data(), matA.fMat.data(), matB.fMat.data());
89 }
90
91 ///////////////////////////////////////////////////////////////////////////////
92
setrow(float row[],float r,float g,float b)93 static void setrow(float row[], float r, float g, float b) {
94 row[0] = r;
95 row[1] = g;
96 row[2] = b;
97 }
98
99 static const float kHueR = 0.213f;
100 static const float kHueG = 0.715f;
101 static const float kHueB = 0.072f;
102
setSaturation(float sat)103 void SkColorMatrix::setSaturation(float sat) {
104 fMat.fill(0.0f);
105
106 const float R = kHueR * (1 - sat);
107 const float G = kHueG * (1 - sat);
108 const float B = kHueB * (1 - sat);
109
110 setrow(fMat.data() + 0, R + sat, G, B);
111 setrow(fMat.data() + 5, R, G + sat, B);
112 setrow(fMat.data() + 10, R, G, B + sat);
113 fMat[kA_Scale] = 1;
114 }
115