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