1/* 2 * Copyright (C) 2012 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.renderscript; 18 19import android.util.Log; 20 21/** 22 * Intrinsic for applying a color matrix to allocations. 23 * 24 * If the element type is {@link Element.DataType#UNSIGNED_8}, 25 * it is converted to {@link Element.DataType#FLOAT_32} and 26 * normalized from (0-255) to (0-1). If the incoming vector size 27 * is less than four, a {@link Element#F32_4} is created by 28 * filling the missing vector channels with zero. This value is 29 * then multiplied by the 4x4 color matrix as performed by 30 * rsMatrixMultiply(), adding a {@link Element#F32_4}, and then 31 * writing it to the output {@link Allocation}. 32 * 33 * If the ouptut type is unsigned, the value is normalized from 34 * (0-1) to (0-255) and converted. If the output vector size is 35 * less than four, the unused channels are discarded. 36 * 37 * Supported elements types are {@link Element#U8}, {@link 38 * Element#U8_2}, {@link Element#U8_3}, {@link Element#U8_4}, 39 * {@link Element#F32}, {@link Element#F32_2}, {@link 40 * Element#F32_3}, and {@link Element#F32_4}. 41 **/ 42public final class ScriptIntrinsicColorMatrix extends ScriptIntrinsic { 43 private final Matrix4f mMatrix = new Matrix4f(); 44 private final Float4 mAdd = new Float4(); 45 46 private ScriptIntrinsicColorMatrix(int id, RenderScript rs) { 47 super(id, rs); 48 } 49 50 /** 51 * Create an intrinsic for applying a color matrix to an 52 * allocation. 53 * 54 * @param rs The RenderScript context 55 * @param e Element type for inputs and outputs, As of API 19, 56 * this parameter is ignored. The Element type check is 57 * performed in the kernel launch. 58 * 59 * @deprecated Use the single argument version as Element is now 60 * ignored. 61 * 62 * @return ScriptIntrinsicColorMatrix 63 */ 64 @Deprecated 65 public static ScriptIntrinsicColorMatrix create(RenderScript rs, Element e) { 66 return create(rs); 67 } 68 69 /** 70 * Create an intrinsic for applying a color matrix to an 71 * allocation. 72 * 73 * @param rs The RenderScript context 74 * 75 * @return ScriptIntrinsicColorMatrix 76 */ 77 public static ScriptIntrinsicColorMatrix create(RenderScript rs) { 78 int id = rs.nScriptIntrinsicCreate(2, 0); 79 return new ScriptIntrinsicColorMatrix(id, rs); 80 81 } 82 83 private void setMatrix() { 84 FieldPacker fp = new FieldPacker(16*4); 85 fp.addMatrix(mMatrix); 86 setVar(0, fp); 87 } 88 89 /** 90 * Set the color matrix which will be applied to each cell of 91 * the image. 92 * 93 * @param m The 4x4 matrix to set. 94 */ 95 public void setColorMatrix(Matrix4f m) { 96 mMatrix.load(m); 97 setMatrix(); 98 } 99 100 /** 101 * Set the color matrix which will be applied to each cell of the image. 102 * This will set the alpha channel to be a copy. 103 * 104 * @param m The 3x3 matrix to set. 105 */ 106 public void setColorMatrix(Matrix3f m) { 107 mMatrix.load(m); 108 setMatrix(); 109 } 110 111 /** 112 * Set the value to be added after the color matrix has been 113 * applied. The default value is {0, 0, 0, 0} 114 * 115 * @param f The float4 value to be added. 116 */ 117 public void setAdd(Float4 f) { 118 mAdd.x = f.x; 119 mAdd.y = f.y; 120 mAdd.z = f.z; 121 mAdd.w = f.w; 122 123 FieldPacker fp = new FieldPacker(4*4); 124 fp.addF32(f.x); 125 fp.addF32(f.y); 126 fp.addF32(f.z); 127 fp.addF32(f.w); 128 setVar(1, fp); 129 } 130 131 /** 132 * Set the value to be added after the color matrix has been 133 * applied. The default value is {0, 0, 0, 0} 134 * 135 * @param r The red add value. 136 * @param g The green add value. 137 * @param b The blue add value. 138 * @param a The alpha add value. 139 */ 140 public void setAdd(float r, float g, float b, float a) { 141 mAdd.x = r; 142 mAdd.y = g; 143 mAdd.z = b; 144 mAdd.w = a; 145 146 FieldPacker fp = new FieldPacker(4*4); 147 fp.addF32(mAdd.x); 148 fp.addF32(mAdd.y); 149 fp.addF32(mAdd.z); 150 fp.addF32(mAdd.w); 151 setVar(1, fp); 152 } 153 154 /** 155 * Set a color matrix to convert from RGB to luminance. The alpha channel 156 * will be a copy. 157 * 158 */ 159 public void setGreyscale() { 160 mMatrix.loadIdentity(); 161 mMatrix.set(0, 0, 0.299f); 162 mMatrix.set(1, 0, 0.587f); 163 mMatrix.set(2, 0, 0.114f); 164 mMatrix.set(0, 1, 0.299f); 165 mMatrix.set(1, 1, 0.587f); 166 mMatrix.set(2, 1, 0.114f); 167 mMatrix.set(0, 2, 0.299f); 168 mMatrix.set(1, 2, 0.587f); 169 mMatrix.set(2, 2, 0.114f); 170 setMatrix(); 171 } 172 173 /** 174 * Set the matrix to convert from YUV to RGB with a direct copy of the 4th 175 * channel. 176 * 177 */ 178 public void setYUVtoRGB() { 179 mMatrix.loadIdentity(); 180 mMatrix.set(0, 0, 1.f); 181 mMatrix.set(1, 0, 0.f); 182 mMatrix.set(2, 0, 1.13983f); 183 mMatrix.set(0, 1, 1.f); 184 mMatrix.set(1, 1, -0.39465f); 185 mMatrix.set(2, 1, -0.5806f); 186 mMatrix.set(0, 2, 1.f); 187 mMatrix.set(1, 2, 2.03211f); 188 mMatrix.set(2, 2, 0.f); 189 setMatrix(); 190 } 191 192 /** 193 * Set the matrix to convert from RGB to YUV with a direct copy of the 4th 194 * channel. 195 * 196 */ 197 public void setRGBtoYUV() { 198 mMatrix.loadIdentity(); 199 mMatrix.set(0, 0, 0.299f); 200 mMatrix.set(1, 0, 0.587f); 201 mMatrix.set(2, 0, 0.114f); 202 mMatrix.set(0, 1, -0.14713f); 203 mMatrix.set(1, 1, -0.28886f); 204 mMatrix.set(2, 1, 0.436f); 205 mMatrix.set(0, 2, 0.615f); 206 mMatrix.set(1, 2, -0.51499f); 207 mMatrix.set(2, 2, -0.10001f); 208 setMatrix(); 209 } 210 211 212 /** 213 * Invoke the kernel and apply the matrix to each cell of input 214 * {@link Allocation} and copy to the output {@link Allocation}. 215 * 216 * If the vector size of the input is less than four, the 217 * remaining components are treated as zero for the matrix 218 * multiply. 219 * 220 * If the output vector size is less than four, the unused 221 * vector components are discarded. 222 * 223 * 224 * @param ain Input allocation 225 * @param aout Output allocation 226 */ 227 public void forEach(Allocation ain, Allocation aout) { 228 if (!ain.getElement().isCompatible(Element.U8(mRS)) && 229 !ain.getElement().isCompatible(Element.U8_2(mRS)) && 230 !ain.getElement().isCompatible(Element.U8_3(mRS)) && 231 !ain.getElement().isCompatible(Element.U8_4(mRS)) && 232 !ain.getElement().isCompatible(Element.F32(mRS)) && 233 !ain.getElement().isCompatible(Element.F32_2(mRS)) && 234 !ain.getElement().isCompatible(Element.F32_3(mRS)) && 235 !ain.getElement().isCompatible(Element.F32_4(mRS))) { 236 237 throw new RSIllegalArgumentException("Unsuported element type."); 238 } 239 240 if (!aout.getElement().isCompatible(Element.U8(mRS)) && 241 !aout.getElement().isCompatible(Element.U8_2(mRS)) && 242 !aout.getElement().isCompatible(Element.U8_3(mRS)) && 243 !aout.getElement().isCompatible(Element.U8_4(mRS)) && 244 !aout.getElement().isCompatible(Element.F32(mRS)) && 245 !aout.getElement().isCompatible(Element.F32_2(mRS)) && 246 !aout.getElement().isCompatible(Element.F32_3(mRS)) && 247 !aout.getElement().isCompatible(Element.F32_4(mRS))) { 248 249 throw new RSIllegalArgumentException("Unsuported element type."); 250 } 251 252 forEach(0, ain, aout, null); 253 } 254 255 /** 256 * Get a KernelID for this intrinsic kernel. 257 * 258 * @return Script.KernelID The KernelID object. 259 */ 260 public Script.KernelID getKernelID() { 261 return createKernelID(0, 3, null, null); 262 } 263 264} 265 266