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