1 /* 2 * Copyright (C) 2013 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.renderscript; 18 19 /** 20 * Intrinsic Histogram filter. 21 * 22 * 23 **/ 24 public final class ScriptIntrinsicHistogram extends ScriptIntrinsic { 25 private Allocation mOut; 26 ScriptIntrinsicHistogram(long id, RenderScript rs)27 private ScriptIntrinsicHistogram(long id, RenderScript rs) { 28 super(id, rs); 29 } 30 31 /** 32 * Create an intrinsic for calculating the histogram of an uchar 33 * or uchar4 image. 34 * 35 * Supported elements types are 36 * {@link Element#U8_4}, {@link Element#U8_3}, 37 * {@link Element#U8_2}, {@link Element#U8} 38 * 39 * @param rs The RenderScript context 40 * @param e Element type for inputs 41 * 42 * @return ScriptIntrinsicHistogram 43 */ create(RenderScript rs, Element e)44 public static ScriptIntrinsicHistogram create(RenderScript rs, Element e) { 45 if ((!e.isCompatible(Element.U8_4(rs))) && 46 (!e.isCompatible(Element.U8_3(rs))) && 47 (!e.isCompatible(Element.U8_2(rs))) && 48 (!e.isCompatible(Element.U8(rs)))) { 49 throw new RSIllegalArgumentException("Unsuported element type."); 50 } 51 long id = rs.nScriptIntrinsicCreate(9, e.getID(rs)); 52 ScriptIntrinsicHistogram sib = new ScriptIntrinsicHistogram(id, rs); 53 return sib; 54 } 55 56 /** 57 * Process an input buffer and place the histogram into the 58 * output allocation. The output allocation may be a narrower 59 * vector size than the input. In this case the vector size of 60 * the output is used to determine how many of the input 61 * channels are used in the computation. This is useful if you 62 * have an RGBA input buffer but only want the histogram for 63 * RGB. 64 * 65 * 1D and 2D input allocations are supported. 66 * 67 * @param ain The input image 68 */ forEach(Allocation ain)69 public void forEach(Allocation ain) { 70 forEach(ain, null); 71 } 72 73 /** 74 * Process an input buffer and place the histogram into the 75 * output allocation. The output allocation may be a narrower 76 * vector size than the input. In this case the vector size of 77 * the output is used to determine how many of the input 78 * channels are used in the computation. This is useful if you 79 * have an RGBA input buffer but only want the histogram for 80 * RGB. 81 * 82 * 1D and 2D input allocations are supported. 83 * 84 * @param ain The input image 85 * @param opt LaunchOptions for clipping 86 */ forEach(Allocation ain, Script.LaunchOptions opt)87 public void forEach(Allocation ain, Script.LaunchOptions opt) { 88 if (ain.getType().getElement().getVectorSize() < 89 mOut.getType().getElement().getVectorSize()) { 90 91 throw new RSIllegalArgumentException( 92 "Input vector size must be >= output vector size."); 93 } 94 if (ain.getType().getElement().isCompatible(Element.U8(mRS)) && 95 ain.getType().getElement().isCompatible(Element.U8_4(mRS))) { 96 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 97 } 98 99 forEach(0, ain, null, null, opt); 100 } 101 102 103 104 /** 105 * Set the coefficients used for the RGBA to Luminocity 106 * calculation. The default is {0.299f, 0.587f, 0.114f, 0.f}. 107 * 108 * Coefficients must be >= 0 and sum to 1.0 or less. 109 * 110 * @param r Red coefficient 111 * @param g Green coefficient 112 * @param b Blue coefficient 113 * @param a Alpha coefficient 114 */ setDotCoefficients(float r, float g, float b, float a)115 public void setDotCoefficients(float r, float g, float b, float a) { 116 if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) { 117 throw new RSIllegalArgumentException("Coefficient may not be negative."); 118 } 119 if ((r + g + b + a) > 1.f) { 120 throw new RSIllegalArgumentException("Sum of coefficients must be 1.0 or less."); 121 } 122 123 FieldPacker fp = new FieldPacker(16); 124 fp.addF32(r); 125 fp.addF32(g); 126 fp.addF32(b); 127 fp.addF32(a); 128 setVar(0, fp); 129 } 130 131 /** 132 * Set the output of the histogram. 32 bit integer types are 133 * supported. 134 * 135 * @param aout The output allocation 136 */ setOutput(Allocation aout)137 public void setOutput(Allocation aout) { 138 mOut = aout; 139 if (mOut.getType().getElement() != Element.U32(mRS) && 140 mOut.getType().getElement() != Element.U32_2(mRS) && 141 mOut.getType().getElement() != Element.U32_3(mRS) && 142 mOut.getType().getElement() != Element.U32_4(mRS) && 143 mOut.getType().getElement() != Element.I32(mRS) && 144 mOut.getType().getElement() != Element.I32_2(mRS) && 145 mOut.getType().getElement() != Element.I32_3(mRS) && 146 mOut.getType().getElement() != Element.I32_4(mRS)) { 147 148 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 149 } 150 if ((mOut.getType().getX() != 256) || 151 (mOut.getType().getY() != 0) || 152 mOut.getType().hasMipmaps() || 153 (mOut.getType().getYuv() != 0)) { 154 155 throw new RSIllegalArgumentException("Output must be 1D, 256 elements."); 156 } 157 setVar(1, aout); 158 } 159 160 161 /** 162 * Process an input buffer and place the histogram into the 163 * output allocation. The dot product of the input channel and 164 * the coefficients from 'setDotCoefficients' are used to 165 * calculate the output values. 166 * 167 * 1D and 2D input allocations are supported. 168 * 169 * @param ain The input image 170 */ forEach_Dot(Allocation ain)171 public void forEach_Dot(Allocation ain) { 172 forEach_Dot(ain, null); 173 } 174 175 /** 176 * Process an input buffer and place the histogram into the 177 * output allocation. The dot product of the input channel and 178 * the coefficients from 'setDotCoefficients' are used to 179 * calculate the output values. 180 * 181 * 1D and 2D input allocations are supported. 182 * 183 * @param ain The input image 184 * @param opt LaunchOptions for clipping 185 */ forEach_Dot(Allocation ain, Script.LaunchOptions opt)186 public void forEach_Dot(Allocation ain, Script.LaunchOptions opt) { 187 if (mOut.getType().getElement().getVectorSize() != 1) { 188 throw new RSIllegalArgumentException("Output vector size must be one."); 189 } 190 if (ain.getType().getElement().isCompatible(Element.U8(mRS)) && 191 ain.getType().getElement().isCompatible(Element.U8_4(mRS))) { 192 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 193 } 194 195 forEach(1, ain, null, null, opt); 196 } 197 198 199 200 /** 201 * Get a KernelID for this intrinsic kernel. 202 * 203 * @return Script.KernelID The KernelID object. 204 */ getKernelID_Separate()205 public Script.KernelID getKernelID_Separate() { 206 return createKernelID(0, 3, null, null); 207 } 208 209 /** 210 * Get a FieldID for the input field of this intrinsic. 211 * 212 * @return Script.FieldID The FieldID object. 213 */ getFieldID_Input()214 public Script.FieldID getFieldID_Input() { 215 return createFieldID(1, null); 216 } 217 } 218 219