Home | History | Annotate | Download | only in renderscript
      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 
     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("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