1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.graphics; 18 19import android.util.FloatMath; 20 21/** 22 * 5x4 matrix for transforming the color+alpha components of a Bitmap. 23 * The matrix is stored in a single array, and its treated as follows: 24 * [ a, b, c, d, e, 25 * f, g, h, i, j, 26 * k, l, m, n, o, 27 * p, q, r, s, t ] 28 * 29 * When applied to a color [r, g, b, a], the resulting color is computed as 30 * (after clamping) 31 * R' = a*R + b*G + c*B + d*A + e; 32 * G' = f*R + g*G + h*B + i*A + j; 33 * B' = k*R + l*G + m*B + n*A + o; 34 * A' = p*R + q*G + r*B + s*A + t; 35 */ 36public class ColorMatrix { 37 38 private final float[] mArray = new float[20]; 39 40 /** 41 * Create a new colormatrix initialized to identity (as if reset() had 42 * been called). 43 */ 44 public ColorMatrix() { 45 reset(); 46 } 47 48 /** 49 * Create a new colormatrix initialized with the specified array of values. 50 */ 51 public ColorMatrix(float[] src) { 52 System.arraycopy(src, 0, mArray, 0, 20); 53 } 54 55 /** 56 * Create a new colormatrix initialized with the specified colormatrix. 57 */ 58 public ColorMatrix(ColorMatrix src) { 59 System.arraycopy(src.mArray, 0, mArray, 0, 20); 60 } 61 62 /** 63 * Return the array of floats representing this colormatrix. 64 */ 65 public final float[] getArray() { return mArray; } 66 67 /** 68 * Set this colormatrix to identity: 69 * [ 1 0 0 0 0 - red vector 70 * 0 1 0 0 0 - green vector 71 * 0 0 1 0 0 - blue vector 72 * 0 0 0 1 0 ] - alpha vector 73 */ 74 public void reset() { 75 final float[] a = mArray; 76 77 for (int i = 19; i > 0; --i) { 78 a[i] = 0; 79 } 80 a[0] = a[6] = a[12] = a[18] = 1; 81 } 82 83 /** 84 * Assign the src colormatrix into this matrix, copying all of its values. 85 */ 86 public void set(ColorMatrix src) { 87 System.arraycopy(src.mArray, 0, mArray, 0, 20); 88 } 89 90 /** 91 * Assign the array of floats into this matrix, copying all of its values. 92 */ 93 public void set(float[] src) { 94 System.arraycopy(src, 0, mArray, 0, 20); 95 } 96 97 /** 98 * Set this colormatrix to scale by the specified values. 99 */ 100 public void setScale(float rScale, float gScale, float bScale, 101 float aScale) { 102 final float[] a = mArray; 103 104 for (int i = 19; i > 0; --i) { 105 a[i] = 0; 106 } 107 a[0] = rScale; 108 a[6] = gScale; 109 a[12] = bScale; 110 a[18] = aScale; 111 } 112 113 /** 114 * Set the rotation on a color axis by the specified values. 115 * axis=0 correspond to a rotation around the RED color 116 * axis=1 correspond to a rotation around the GREEN color 117 * axis=2 correspond to a rotation around the BLUE color 118 */ 119 public void setRotate(int axis, float degrees) { 120 reset(); 121 float radians = degrees * (float)Math.PI / 180; 122 float cosine = FloatMath.cos(radians); 123 float sine = FloatMath.sin(radians); 124 switch (axis) { 125 // Rotation around the red color 126 case 0: 127 mArray[6] = mArray[12] = cosine; 128 mArray[7] = sine; 129 mArray[11] = -sine; 130 break; 131 // Rotation around the green color 132 case 1: 133 mArray[0] = mArray[12] = cosine; 134 mArray[2] = -sine; 135 mArray[10] = sine; 136 break; 137 // Rotation around the blue color 138 case 2: 139 mArray[0] = mArray[6] = cosine; 140 mArray[1] = sine; 141 mArray[5] = -sine; 142 break; 143 default: 144 throw new RuntimeException(); 145 } 146 } 147 148 /** 149 * Set this colormatrix to the concatenation of the two specified 150 * colormatrices, such that the resulting colormatrix has the same effect 151 * as applying matB and then applying matA. It is legal for either matA or 152 * matB to be the same colormatrix as this. 153 */ 154 public void setConcat(ColorMatrix matA, ColorMatrix matB) { 155 float[] tmp = null; 156 157 if (matA == this || matB == this) { 158 tmp = new float[20]; 159 } 160 else { 161 tmp = mArray; 162 } 163 164 final float[] a = matA.mArray; 165 final float[] b = matB.mArray; 166 int index = 0; 167 for (int j = 0; j < 20; j += 5) { 168 for (int i = 0; i < 4; i++) { 169 tmp[index++] = a[j + 0] * b[i + 0] + a[j + 1] * b[i + 5] + 170 a[j + 2] * b[i + 10] + a[j + 3] * b[i + 15]; 171 } 172 tmp[index++] = a[j + 0] * b[4] + a[j + 1] * b[9] + 173 a[j + 2] * b[14] + a[j + 3] * b[19] + 174 a[j + 4]; 175 } 176 177 if (tmp != mArray) { 178 System.arraycopy(tmp, 0, mArray, 0, 20); 179 } 180 } 181 182 /** 183 * Concat this colormatrix with the specified prematrix. This is logically 184 * the same as calling setConcat(this, prematrix); 185 */ 186 public void preConcat(ColorMatrix prematrix) { 187 setConcat(this, prematrix); 188 } 189 190 /** 191 * Concat this colormatrix with the specified postmatrix. This is logically 192 * the same as calling setConcat(postmatrix, this); 193 */ 194 public void postConcat(ColorMatrix postmatrix) { 195 setConcat(postmatrix, this); 196 } 197 198 /////////////////////////////////////////////////////////////////////////// 199 200 /** 201 * Set the matrix to affect the saturation of colors. A value of 0 maps the 202 * color to gray-scale. 1 is identity. 203 */ 204 public void setSaturation(float sat) { 205 reset(); 206 float[] m = mArray; 207 208 final float invSat = 1 - sat; 209 final float R = 0.213f * invSat; 210 final float G = 0.715f * invSat; 211 final float B = 0.072f * invSat; 212 213 m[0] = R + sat; m[1] = G; m[2] = B; 214 m[5] = R; m[6] = G + sat; m[7] = B; 215 m[10] = R; m[11] = G; m[12] = B + sat; 216 } 217 218 /** 219 * Set the matrix to convert RGB to YUV 220 */ 221 public void setRGB2YUV() { 222 reset(); 223 float[] m = mArray; 224 // these coefficients match those in libjpeg 225 m[0] = 0.299f; m[1] = 0.587f; m[2] = 0.114f; 226 m[5] = -0.16874f; m[6] = -0.33126f; m[7] = 0.5f; 227 m[10] = 0.5f; m[11] = -0.41869f; m[12] = -0.08131f; 228 } 229 230 /** 231 * Set the matrix to convert from YUV to RGB 232 */ 233 public void setYUV2RGB() { 234 reset(); 235 float[] m = mArray; 236 // these coefficients match those in libjpeg 237 m[2] = 1.402f; 238 m[5] = 1; m[6] = -0.34414f; m[7] = -0.71414f; 239 m[10] = 1; m[11] = 1.772f; m[12] = 0; 240 } 241} 242 243