Home | History | Annotate | Download | only in utils
      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 
     15 void SkColorMatrix::setIdentity() {
     16     memset(fMat, 0, sizeof(fMat));
     17     fMat[kRScale] = fMat[kGScale] = fMat[kBScale] = fMat[kAScale] = SK_Scalar1;
     18 }
     19 
     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 
     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 
     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 
     56 void SkColorMatrix::preRotate(Axis axis, SkScalar degrees) {
     57     SkColorMatrix tmp;
     58     tmp.setRotate(axis, degrees);
     59     this->preConcat(tmp);
     60 }
     61 
     62 void SkColorMatrix::postRotate(Axis axis, SkScalar degrees) {
     63     SkColorMatrix tmp;
     64     tmp.setRotate(axis, degrees);
     65     this->postConcat(tmp);
     66 }
     67 
     68 ///////////////////////////////////////////////////////////////////////////////
     69 
     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 
    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 
    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 
    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 
    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