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 17package android.renderscript; 18 19import android.content.Context; 20import android.content.res.Resources; 21import android.util.Log; 22 23/** 24 * Intrinsic Histogram filter. 25 * 26 * 27 **/ 28public final class ScriptIntrinsicHistogram extends ScriptIntrinsic { 29 private Allocation mOut; 30 31 private ScriptIntrinsicHistogram(int 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 */ 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("Unsuported element type."); 54 } 55 int id = rs.nScriptIntrinsicCreate(9, e.getID(rs)); 56 ScriptIntrinsicHistogram sib = new ScriptIntrinsicHistogram(id, rs); 57 return sib; 58 } 59 60 /** 61 * Process an input buffer and place the histogram into the 62 * output allocation. The output allocation may be a narrower 63 * vector size than the input. In this case the vector size of 64 * the output is used to determine how many of the input 65 * channels are used in the computation. This is useful if you 66 * have an RGBA input buffer but only want the histogram for 67 * RGB. 68 * 69 * 1D and 2D input allocations are supported. 70 * 71 * @param ain The input image 72 */ 73 public void forEach(Allocation ain) { 74 if (ain.getType().getElement().getVectorSize() < 75 mOut.getType().getElement().getVectorSize()) { 76 77 throw new RSIllegalArgumentException( 78 "Input vector size must be >= output vector size."); 79 } 80 if (ain.getType().getElement().isCompatible(Element.U8(mRS)) && 81 ain.getType().getElement().isCompatible(Element.U8_4(mRS))) { 82 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 83 } 84 85 forEach(0, ain, null, null); 86 } 87 88 /** 89 * Set the coefficients used for the RGBA to Luminocity 90 * calculation. The default is {0.299f, 0.587f, 0.114f, 0.f}. 91 * 92 * Coefficients must be >= 0 and sum to 1.0 or less. 93 * 94 * @param r Red coefficient 95 * @param g Green coefficient 96 * @param b Blue coefficient 97 * @param a Alpha coefficient 98 */ 99 public void setDotCoefficients(float r, float g, float b, float a) { 100 if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) { 101 throw new RSIllegalArgumentException("Coefficient may not be negative."); 102 } 103 if ((r + g + b + a) > 1.f) { 104 throw new RSIllegalArgumentException("Sum of coefficients must be 1.0 or less."); 105 } 106 107 FieldPacker fp = new FieldPacker(16); 108 fp.addF32(r); 109 fp.addF32(g); 110 fp.addF32(b); 111 fp.addF32(a); 112 setVar(0, fp); 113 } 114 115 /** 116 * Set the output of the histogram. 32 bit integer types are 117 * supported. 118 * 119 * @param aout The output allocation 120 */ 121 public void setOutput(Allocation aout) { 122 mOut = aout; 123 if (mOut.getType().getElement() != Element.U32(mRS) && 124 mOut.getType().getElement() != Element.U32_2(mRS) && 125 mOut.getType().getElement() != Element.U32_3(mRS) && 126 mOut.getType().getElement() != Element.U32_4(mRS) && 127 mOut.getType().getElement() != Element.I32(mRS) && 128 mOut.getType().getElement() != Element.I32_2(mRS) && 129 mOut.getType().getElement() != Element.I32_3(mRS) && 130 mOut.getType().getElement() != Element.I32_4(mRS)) { 131 132 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 133 } 134 if ((mOut.getType().getX() != 256) || 135 (mOut.getType().getY() != 0) || 136 mOut.getType().hasMipmaps() || 137 (mOut.getType().getYuv() != 0)) { 138 139 throw new RSIllegalArgumentException("Output must be 1D, 256 elements."); 140 } 141 setVar(1, aout); 142 } 143 144 /** 145 * Process an input buffer and place the histogram into the 146 * output allocation. The dot product of the input channel and 147 * the coefficients from 'setDotCoefficients' are used to 148 * calculate the output values. 149 * 150 * 1D and 2D input allocations are supported. 151 * 152 * @param ain The input image 153 */ 154 public void forEach_Dot(Allocation ain) { 155 if (mOut.getType().getElement().getVectorSize() != 1) { 156 throw new RSIllegalArgumentException("Output vector size must be one."); 157 } 158 if (ain.getType().getElement().isCompatible(Element.U8(mRS)) && 159 ain.getType().getElement().isCompatible(Element.U8_4(mRS))) { 160 throw new RSIllegalArgumentException("Output type must be U32 or I32."); 161 } 162 163 forEach(1, ain, null, null); 164 } 165 166 167 168 /** 169 * Get a KernelID for this intrinsic kernel. 170 * 171 * @return Script.KernelID The KernelID object. 172 */ 173 public Script.KernelID getKernelID_Separate() { 174 return createKernelID(0, 3, null, null); 175 } 176 177 /** 178 * Get a FieldID for the input field of this intrinsic. 179 * 180 * @return Script.FieldID The FieldID object. 181 */ 182 public Script.FieldID getFieldID_Input() { 183 return createFieldID(1, null); 184 } 185} 186 187