• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SkColorMatrix.h"
9 
10 #define kRScale     0
11 #define kGScale     6
12 #define kBScale     12
13 #define kAScale     18
14 
setIdentity()15 void SkColorMatrix::setIdentity() {
16     memset(fMat, 0, sizeof(fMat));
17     fMat[kRScale] = fMat[kGScale] = fMat[kBScale] = fMat[kAScale] = SK_Scalar1;
18 }
19 
setScale(SkScalar rScale,SkScalar gScale,SkScalar bScale,SkScalar aScale)20 void SkColorMatrix::setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
21                              SkScalar aScale) {
22     memset(fMat, 0, sizeof(fMat));
23     fMat[kRScale] = rScale;
24     fMat[kGScale] = gScale;
25     fMat[kBScale] = bScale;
26     fMat[kAScale] = aScale;
27 }
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 
setRotate(Axis axis,SkScalar degrees)31 void SkColorMatrix::setRotate(Axis axis, SkScalar degrees) {
32     SkScalar S, C;
33 
34     S = SkScalarSinCos(SkDegreesToRadians(degrees), &C);
35 
36     this->setSinCos(axis, S, C);
37 }
38 
setSinCos(Axis axis,SkScalar sine,SkScalar cosine)39 void SkColorMatrix::setSinCos(Axis axis, SkScalar sine, SkScalar cosine) {
40     SkASSERT((unsigned)axis < 3);
41 
42     static const uint8_t gRotateIndex[] = {
43         6, 7, 11, 12,
44         0, 10, 2, 12,
45         0, 1,  5,  6,
46     };
47     const uint8_t* index = gRotateIndex + axis * 4;
48 
49     this->setIdentity();
50     fMat[index[0]] = cosine;
51     fMat[index[1]] = sine;
52     fMat[index[2]] = -sine;
53     fMat[index[3]] = cosine;
54 }
55 
preRotate(Axis axis,SkScalar degrees)56 void SkColorMatrix::preRotate(Axis axis, SkScalar degrees) {
57     SkColorMatrix tmp;
58     tmp.setRotate(axis, degrees);
59     this->preConcat(tmp);
60 }
61 
postRotate(Axis axis,SkScalar degrees)62 void SkColorMatrix::postRotate(Axis axis, SkScalar degrees) {
63     SkColorMatrix tmp;
64     tmp.setRotate(axis, degrees);
65     this->postConcat(tmp);
66 }
67 
68 ///////////////////////////////////////////////////////////////////////////////
69 
setConcat(const SkColorMatrix & matA,const SkColorMatrix & matB)70 void SkColorMatrix::setConcat(const SkColorMatrix& matA,
71                               const SkColorMatrix& matB) {
72     SkScalar    tmp[20];
73     SkScalar*   result = fMat;
74 
75     if (&matA == this || &matB == this) {
76         result = tmp;
77     }
78 
79     const SkScalar* a = matA.fMat;
80     const SkScalar* b = matB.fMat;
81 
82     int index = 0;
83     for (int j = 0; j < 20; j += 5) {
84         for (int i = 0; i < 4; i++) {
85             result[index++] =   SkScalarMul(a[j + 0], b[i + 0]) +
86                                 SkScalarMul(a[j + 1], b[i + 5]) +
87                                 SkScalarMul(a[j + 2], b[i + 10]) +
88                                 SkScalarMul(a[j + 3], b[i + 15]);
89         }
90         result[index++] =   SkScalarMul(a[j + 0], b[4]) +
91                             SkScalarMul(a[j + 1], b[9]) +
92                             SkScalarMul(a[j + 2], b[14]) +
93                             SkScalarMul(a[j + 3], b[19]) +
94                             a[j + 4];
95     }
96 
97     if (fMat != result) {
98         memcpy(fMat, result, sizeof(fMat));
99     }
100 }
101 
102 ///////////////////////////////////////////////////////////////////////////////
103 
setrow(SkScalar row[],SkScalar r,SkScalar g,SkScalar b)104 static void setrow(SkScalar row[], SkScalar r, SkScalar g, SkScalar b) {
105     row[0] = r;
106     row[1] = g;
107     row[2] = b;
108 }
109 
110 static const SkScalar kHueR = SkFloatToScalar(0.213f);
111 static const SkScalar kHueG = SkFloatToScalar(0.715f);
112 static const SkScalar kHueB = SkFloatToScalar(0.072f);
113 
setSaturation(SkScalar sat)114 void SkColorMatrix::setSaturation(SkScalar sat) {
115     memset(fMat, 0, sizeof(fMat));
116 
117     const SkScalar R = SkScalarMul(kHueR, SK_Scalar1 - sat);
118     const SkScalar G = SkScalarMul(kHueG, SK_Scalar1 - sat);
119     const SkScalar B = SkScalarMul(kHueB, SK_Scalar1 - sat);
120 
121     setrow(fMat +  0, R + sat, G, B);
122     setrow(fMat +  5, R, G + sat, B);
123     setrow(fMat + 10, R, G, B + sat);
124     fMat[18] = SK_Scalar1;
125 }
126 
127 static const SkScalar kR2Y = SkFloatToScalar(0.299f);
128 static const SkScalar kG2Y = SkFloatToScalar(0.587f);
129 static const SkScalar kB2Y = SkFloatToScalar(0.114f);
130 
131 static const SkScalar kR2U = SkFloatToScalar(-0.16874f);
132 static const SkScalar kG2U = SkFloatToScalar(-0.33126f);
133 static const SkScalar kB2U = SkFloatToScalar(0.5f);
134 
135 static const SkScalar kR2V = SkFloatToScalar(0.5f);
136 static const SkScalar kG2V = SkFloatToScalar(-0.41869f);
137 static const SkScalar kB2V = SkFloatToScalar(-0.08131f);
138 
setRGB2YUV()139 void SkColorMatrix::setRGB2YUV() {
140     memset(fMat, 0, sizeof(fMat));
141 
142     setrow(fMat +  0, kR2Y, kG2Y, kB2Y);
143     setrow(fMat +  5, kR2U, kG2U, kB2U);
144     setrow(fMat + 10, kR2V, kG2V, kB2V);
145     fMat[18] = SK_Scalar1;
146 }
147 
148 static const SkScalar kV2R = SkFloatToScalar(1.402f);
149 static const SkScalar kU2G = SkFloatToScalar(-0.34414f);
150 static const SkScalar kV2G = SkFloatToScalar(-0.71414f);
151 static const SkScalar kU2B = SkFloatToScalar(1.772f);
152 
setYUV2RGB()153 void SkColorMatrix::setYUV2RGB() {
154     memset(fMat, 0, sizeof(fMat));
155 
156     setrow(fMat +  0, SK_Scalar1, 0, kV2R);
157     setrow(fMat +  5, SK_Scalar1, kU2G, kV2G);
158     setrow(fMat + 10, SK_Scalar1, kU2B, 0);
159     fMat[18] = SK_Scalar1;
160 }
161 
162