Home | History | Annotate | Download | only in effects
      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