Home | History | Annotate | Download | only in imageproc
      1 /*
      2  * Copyright (C) 2011 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 
     18 package android.filterpacks.imageproc;
     19 
     20 import android.filterfw.core.Filter;
     21 import android.filterfw.core.FilterContext;
     22 import android.filterfw.core.Frame;
     23 import android.filterfw.core.FrameFormat;
     24 import android.filterfw.core.GenerateFieldPort;
     25 import android.filterfw.core.MutableFrameFormat;
     26 import android.filterfw.core.Program;
     27 import android.filterfw.core.ShaderProgram;
     28 import android.filterfw.format.ImageFormat;
     29 
     30 import java.lang.Math;
     31 /**
     32  * @hide
     33  */
     34 public class ToPackedGrayFilter extends Filter {
     35 
     36     @GenerateFieldPort(name = "owidth", hasDefault = true)
     37     private int mOWidth = FrameFormat.SIZE_UNSPECIFIED;
     38     @GenerateFieldPort(name = "oheight", hasDefault = true)
     39     private int mOHeight = FrameFormat.SIZE_UNSPECIFIED;
     40     @GenerateFieldPort(name = "keepAspectRatio", hasDefault = true)
     41     private boolean mKeepAspectRatio = false;
     42 
     43     private Program mProgram;
     44 
     45     private final String mColorToPackedGrayShader =
     46         "precision mediump float;\n" +
     47         "const vec4 coeff_y = vec4(0.299, 0.587, 0.114, 0);\n" +
     48         "uniform sampler2D tex_sampler_0;\n" +
     49         "uniform float pix_stride;\n" +
     50         "varying vec2 v_texcoord;\n" +
     51         "void main() {\n" +
     52         "  for (int i = 0; i < 4; ++i) {\n" +
     53         "    vec4 p = texture2D(tex_sampler_0,\n" +
     54         "                       v_texcoord + vec2(pix_stride * float(i), 0.0));\n" +
     55         "    gl_FragColor[i] = dot(p, coeff_y);\n" +
     56         "  }\n" +
     57         "}\n";
     58 
     59     public ToPackedGrayFilter(String name) {
     60         super(name);
     61     }
     62 
     63     @Override
     64     public void setupPorts() {
     65         addMaskedInputPort("image", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
     66                                                        FrameFormat.TARGET_GPU));
     67         addOutputBasedOnInput("image", "image");
     68     }
     69 
     70     @Override
     71     public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) {
     72         return convertInputFormat(inputFormat);
     73     }
     74 
     75     private void checkOutputDimensions(int outputWidth, int outputHeight) {
     76         if (outputWidth <= 0 || outputHeight <= 0) {
     77             throw new RuntimeException("Invalid output dimensions: " +
     78                                        outputWidth + " " + outputHeight);
     79         }
     80     }
     81 
     82     private FrameFormat convertInputFormat(FrameFormat inputFormat) {
     83         int ow = mOWidth;
     84         int oh = mOHeight;
     85         int w = inputFormat.getWidth();
     86         int h = inputFormat.getHeight();
     87         if (mOWidth == FrameFormat.SIZE_UNSPECIFIED) {
     88             ow = w;
     89         }
     90         if (mOHeight == FrameFormat.SIZE_UNSPECIFIED) {
     91             oh = h;
     92         }
     93         if (mKeepAspectRatio) {
     94             // if keep aspect ratio, use the bigger dimension to determine the
     95             // final output size
     96             if (w > h) {
     97                 ow = Math.max(ow, oh);
     98                 oh = ow * h / w;
     99             } else {
    100                 oh = Math.max(ow, oh);
    101                 ow = oh * w / h;
    102             }
    103         }
    104         ow = (ow > 0 && ow < 4) ? 4 : (ow / 4) * 4; // ensure width is multiple of 4
    105         return ImageFormat.create(ow, oh,
    106                                   ImageFormat.COLORSPACE_GRAY,
    107                                   FrameFormat.TARGET_NATIVE);
    108     }
    109 
    110     @Override
    111     public void prepare(FilterContext context) {
    112         mProgram = new ShaderProgram(context, mColorToPackedGrayShader);
    113     }
    114 
    115     @Override
    116     public void process(FilterContext context) {
    117         Frame input = pullInput("image");
    118         FrameFormat inputFormat = input.getFormat();
    119         FrameFormat outputFormat = convertInputFormat(inputFormat);
    120         int ow = outputFormat.getWidth();
    121         int oh = outputFormat.getHeight();
    122         checkOutputDimensions(ow, oh);
    123         mProgram.setHostValue("pix_stride", 1.0f / ow);
    124 
    125         // Do the RGBA to luminance conversion.
    126         MutableFrameFormat tempFrameFormat = inputFormat.mutableCopy();
    127         tempFrameFormat.setDimensions(ow / 4, oh);
    128         Frame temp = context.getFrameManager().newFrame(tempFrameFormat);
    129         mProgram.process(input, temp);
    130 
    131         // Read frame from GPU to CPU.
    132         Frame output = context.getFrameManager().newFrame(outputFormat);
    133         output.setDataFromFrame(temp);
    134         temp.release();
    135 
    136         // Push output and yield ownership.
    137         pushOutput("image", output);
    138         output.release();
    139     }
    140 
    141 }
    142