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