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