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