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