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