ScriptIntrinsicHistogram.java revision 6f5555db1af436bb5aad430e6e00aa5b69d5ca6c
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
17package android.support.v8.renderscript;
18
19import android.util.Log;
20
21/**
22 * Intrinsic Histogram filter.
23 *
24 *
25 **/
26public class ScriptIntrinsicHistogram extends ScriptIntrinsic {
27    private Allocation mOut;
28    // API level for the intrinsic
29    private static final int INTRINSIC_API_LEVEL = 19;
30
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     */
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        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 (mOut.getType().getElement().getVectorSize() == 3) {
105            throw new RSIllegalArgumentException(
106                "Output vector size should not be 3 for Input vector size 4.");
107        }
108        if (!ain.getType().getElement().isCompatible(Element.U8(mRS)) &&
109            !ain.getType().getElement().isCompatible(Element.U8_4(mRS))) {
110            throw new RSIllegalArgumentException("Output type must be U8 or U8_4.");
111        }
112
113        forEach(0, ain, null, null, opt);
114    }
115
116
117
118    /**
119     * Set the coefficients used for the RGBA to Luminocity
120     * calculation. The default is {0.299f, 0.587f, 0.114f, 0.f}.
121     *
122     * Coefficients must be >= 0 and sum to 1.0 or less.
123     *
124     * @param r Red coefficient
125     * @param g Green coefficient
126     * @param b Blue coefficient
127     * @param a Alpha coefficient
128     */
129    public void setDotCoefficients(float r, float g, float b, float a) {
130        if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) {
131            throw new RSIllegalArgumentException("Coefficient may not be negative.");
132        }
133        if ((r + g + b + a) > 1.f) {
134            throw new RSIllegalArgumentException("Sum of coefficients must be 1.0 or less.");
135        }
136
137        FieldPacker fp = new FieldPacker(16);
138        fp.addF32(r);
139        fp.addF32(g);
140        fp.addF32(b);
141        fp.addF32(a);
142        setVar(0, fp);
143    }
144
145    /**
146     * Set the output of the histogram.  32 bit integer types are
147     * supported.
148     *
149     * @param aout The output allocation
150     */
151    public void setOutput(Allocation aout) {
152        mOut = aout;
153        if (mOut.getType().getElement() != Element.U32(mRS) &&
154            mOut.getType().getElement() != Element.U32_2(mRS) &&
155            mOut.getType().getElement() != Element.U32_3(mRS) &&
156            mOut.getType().getElement() != Element.U32_4(mRS) &&
157            mOut.getType().getElement() != Element.I32(mRS) &&
158            mOut.getType().getElement() != Element.I32_2(mRS) &&
159            mOut.getType().getElement() != Element.I32_3(mRS) &&
160            mOut.getType().getElement() != Element.I32_4(mRS)) {
161
162            throw new RSIllegalArgumentException("Output type must be U32 or I32.");
163        }
164        if ((mOut.getType().getX() != 256) ||
165            (mOut.getType().getY() != 0) ||
166            mOut.getType().hasMipmaps() ||
167            (mOut.getType().getYuv() != 0)) {
168
169            throw new RSIllegalArgumentException("Output must be 1D, 256 elements.");
170        }
171        setVar(1, aout);
172    }
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     */
185    public void forEach_Dot(Allocation ain) {
186        forEach_Dot(ain, null);
187    }
188
189    /**
190     * Process an input buffer and place the histogram into the
191     * output allocation. The dot product of the input channel and
192     * the coefficients from 'setDotCoefficients' are used to
193     * calculate the output values.
194     *
195     * 1D and 2D input allocations are supported.
196     *
197     * @param ain The input image
198     * @param opt LaunchOptions for clipping
199     */
200    public void forEach_Dot(Allocation ain, Script.LaunchOptions opt) {
201        if (mOut.getType().getElement().getVectorSize() != 1) {
202            throw new RSIllegalArgumentException("Output vector size must be one.");
203        }
204        if (!ain.getType().getElement().isCompatible(Element.U8(mRS)) &&
205            !ain.getType().getElement().isCompatible(Element.U8_4(mRS))) {
206            throw new RSIllegalArgumentException("Output type must be U8 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