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 package android.filterpacks.imageproc;
     18 
     19 import android.filterfw.core.Filter;
     20 import android.filterfw.core.FilterContext;
     21 import android.filterfw.core.Frame;
     22 import android.filterfw.core.FrameFormat;
     23 import android.filterfw.core.GenerateFieldPort;
     24 import android.filterfw.core.KeyValueMap;
     25 import android.filterfw.core.NativeProgram;
     26 import android.filterfw.core.NativeFrame;
     27 import android.filterfw.core.Program;
     28 import android.filterfw.core.ShaderProgram;
     29 import android.filterfw.format.ImageFormat;
     30 
     31 import java.util.Set;
     32 
     33 public class SharpenFilter extends Filter {
     34 
     35     @GenerateFieldPort(name = "scale", hasDefault = true)
     36     private float mScale = 0f;
     37 
     38     @GenerateFieldPort(name = "tile_size", hasDefault = true)
     39     private int mTileSize = 640;
     40 
     41     private Program mProgram;
     42 
     43     private int mWidth = 0;
     44     private int mHeight = 0;
     45     private int mTarget = FrameFormat.TARGET_UNSPECIFIED;
     46 
     47     private final String mSharpenShader =
     48             "precision mediump float;\n" +
     49             "uniform sampler2D tex_sampler_0;\n" +
     50             "uniform float scale;\n" +
     51             "uniform float stepsizeX;\n" +
     52             "uniform float stepsizeY;\n" +
     53             "varying vec2 v_texcoord;\n" +
     54             "void main() {\n" +
     55             "  vec3 nbr_color = vec3(0.0, 0.0, 0.0);\n" +
     56             "  vec2 coord;\n" +
     57             "  vec4 color = texture2D(tex_sampler_0, v_texcoord);\n" +
     58             "  coord.x = v_texcoord.x - 0.5 * stepsizeX;\n" +
     59             "  coord.y = v_texcoord.y - stepsizeY;\n" +
     60             "  nbr_color += texture2D(tex_sampler_0, coord).rgb - color.rgb;\n" +
     61             "  coord.x = v_texcoord.x - stepsizeX;\n" +
     62             "  coord.y = v_texcoord.y + 0.5 * stepsizeY;\n" +
     63             "  nbr_color += texture2D(tex_sampler_0, coord).rgb - color.rgb;\n" +
     64             "  coord.x = v_texcoord.x + stepsizeX;\n" +
     65             "  coord.y = v_texcoord.y - 0.5 * stepsizeY;\n" +
     66             "  nbr_color += texture2D(tex_sampler_0, coord).rgb - color.rgb;\n" +
     67             "  coord.x = v_texcoord.x + stepsizeX;\n" +
     68             "  coord.y = v_texcoord.y + 0.5 * stepsizeY;\n" +
     69             "  nbr_color += texture2D(tex_sampler_0, coord).rgb - color.rgb;\n" +
     70             "  gl_FragColor = vec4(color.rgb - 2.0 * scale * nbr_color, color.a);\n" +
     71             "}\n";
     72 
     73     public SharpenFilter(String name) {
     74         super(name);
     75     }
     76 
     77     @Override
     78     public void setupPorts() {
     79         addMaskedInputPort("image", ImageFormat.create(ImageFormat.COLORSPACE_RGBA));
     80         addOutputBasedOnInput("image", "image");
     81     }
     82 
     83     @Override
     84     public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) {
     85         return inputFormat;
     86     }
     87 
     88     public void initProgram(FilterContext context, int target) {
     89         switch (target) {
     90             case FrameFormat.TARGET_GPU:
     91                 ShaderProgram shaderProgram = new ShaderProgram(context, mSharpenShader);
     92                 shaderProgram.setMaximumTileSize(mTileSize);
     93                 mProgram = shaderProgram;
     94                 break;
     95 
     96             default:
     97                 throw new RuntimeException("Filter Sharpen does not support frames of " +
     98                     "target " + target + "!");
     99         }
    100         mTarget = target;
    101     }
    102 
    103     @Override
    104     public void process(FilterContext context) {
    105         // Get input frame
    106         Frame input = pullInput("image");
    107         FrameFormat inputFormat = input.getFormat();
    108 
    109         // Create output frame
    110         Frame output = context.getFrameManager().newFrame(inputFormat);
    111 
    112         // Create program if not created already
    113         if (mProgram == null || inputFormat.getTarget() != mTarget) {
    114             initProgram(context, inputFormat.getTarget());
    115         }
    116 
    117         // Check if the frame size has changed
    118         if (inputFormat.getWidth() != mWidth || inputFormat.getHeight() != mHeight) {
    119             updateFrameSize(inputFormat.getWidth(), inputFormat.getHeight());
    120         }
    121 
    122         // Process
    123         mProgram.process(input, output);
    124 
    125         // Push output
    126         pushOutput("image", output);
    127 
    128         // Release pushed frame
    129         output.release();
    130     }
    131 
    132     private void updateFrameSize(int width, int height) {
    133         mWidth = width;
    134         mHeight = height;
    135 
    136         if (mProgram != null) {
    137             mProgram.setHostValue("stepsizeX", 1.0f / mWidth);
    138             mProgram.setHostValue("stepsizeY", 1.0f / mHeight);
    139             updateParameters();
    140         }
    141     }
    142 
    143     private void updateParameters() {
    144         mProgram.setHostValue("scale", mScale);
    145     }
    146 
    147     @Override
    148     public void fieldPortValueUpdated(String name, FilterContext context) {
    149         if (mProgram != null) {
    150             updateParameters();
    151         }
    152     }
    153 }
    154