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