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_2(mRS)) && 96 !ain.getType().getElement().isCompatible(Element.U8_3(mRS)) && 97 !ain.getType().getElement().isCompatible(Element.U8_4(mRS))) { 98 throw new RSIllegalArgumentException("Input type must be U8, U8_1, U8_2 or U8_4."); 99 } 100 101 forEach(0, ain, null, null, opt); 102 } 103 104 105 106 /** 107 * Set the coefficients used for the RGBA to Luminocity 108 * calculation. The default is {0.299f, 0.587f, 0.114f, 0.f}. 109 * 110 * Coefficients must be >= 0 and sum to 1.0 or less. 111 * 112 * @param r Red coefficient 113 * @param g Green coefficient 114 * @param b Blue coefficient 115 * @param a Alpha coefficient 116 */ setDotCoefficients(float r, float g, float b, float a)117 public void setDotCoefficients(float r, float g, float b, float a) { 118 if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) { 119 throw new RSIllegalArgumentException("Coefficient may not be negative."); 120 } 121 if ((r + g + b + a) > 1.f) { 122 throw new RSIllegalArgumentException("Sum of coefficients must be 1.0 or less."); 123 } 124 125 FieldPacker fp = new FieldPacker(16); 126 fp.addF32(r); 127 fp.addF32(g); 128 fp.addF32(b); 129 fp.addF32(a); 130 setVar(0, fp); 131 } 132 133 /** 134 * Set the output of the histogram. 32 bit integer types are 135 * supported. 136 * 137 * @param aout The output allocation 138 */ setOutput(Allocation aout)139 public void setOutput(Allocation aout) { 140 mOut = aout; 141 if (mOut.getType().getElement() != Element.U32(mRS) && 142 mOut.getType().getElement() != Element.U32_2(mRS) && 143 mOut.getType().getElement() != Element.U32_3(mRS) && 144 mOut.getType().getElement() != Element.U32_4(mRS) && 145 mOut.getType().getElement() != Element.I32(mRS) && 146 mOut.getType().getElement() != Element.I32_2(mRS) && 147 mOut.getType().getElement() != Element.I32_3(mRS) && 148 mOut.getType().getElement() != Element.I32_4(mRS)) { 149 150 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 151 } 152 if ((mOut.getType().getX() != 256) || 153 (mOut.getType().getY() != 0) || 154 mOut.getType().hasMipmaps() || 155 (mOut.getType().getYuv() != 0)) { 156 157 throw new RSIllegalArgumentException("Output must be 1D, 256 elements."); 158 } 159 setVar(1, aout); 160 } 161 162 163 /** 164 * Process an input buffer and place the histogram into the 165 * output allocation. The dot product of the input channel and 166 * the coefficients from 'setDotCoefficients' are used to 167 * calculate the output values. 168 * 169 * 1D and 2D input allocations are supported. 170 * 171 * @param ain The input image 172 */ forEach_Dot(Allocation ain)173 public void forEach_Dot(Allocation ain) { 174 forEach_Dot(ain, null); 175 } 176 177 /** 178 * Process an input buffer and place the histogram into the 179 * output allocation. The dot product of the input channel and 180 * the coefficients from 'setDotCoefficients' are used to 181 * calculate the output values. 182 * 183 * 1D and 2D input allocations are supported. 184 * 185 * @param ain The input image 186 * @param opt LaunchOptions for clipping 187 */ forEach_Dot(Allocation ain, Script.LaunchOptions opt)188 public void forEach_Dot(Allocation ain, Script.LaunchOptions opt) { 189 if (mOut.getType().getElement().getVectorSize() != 1) { 190 throw new RSIllegalArgumentException("Output vector size must be one."); 191 } 192 if (!ain.getType().getElement().isCompatible(Element.U8(mRS)) && 193 !ain.getType().getElement().isCompatible(Element.U8_2(mRS)) && 194 !ain.getType().getElement().isCompatible(Element.U8_3(mRS)) && 195 !ain.getType().getElement().isCompatible(Element.U8_4(mRS))) { 196 throw new RSIllegalArgumentException("Input type must be U8, U8_1, U8_2 or U8_4."); 197 } 198 199 forEach(1, ain, null, null, opt); 200 } 201 202 203 204 /** 205 * Get a KernelID for this intrinsic kernel. 206 * 207 * @return Script.KernelID The KernelID object. 208 */ getKernelID_Separate()209 public Script.KernelID getKernelID_Separate() { 210 return createKernelID(0, 3, null, null); 211 } 212 213 /** 214 * Get a FieldID for the input field of this intrinsic. 215 * 216 * @return Script.FieldID The FieldID object. 217 */ getFieldID_Input()218 public Script.FieldID getFieldID_Input() { 219 return createFieldID(1, null); 220 } 221 } 222 223