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 18package android.filterpacks.imageproc; 19 20import android.filterfw.core.Filter; 21import android.filterfw.core.FilterContext; 22import android.filterfw.core.Frame; 23import android.filterfw.core.FrameFormat; 24import android.filterfw.core.GenerateFieldPort; 25import android.filterfw.core.MutableFrameFormat; 26import android.filterfw.core.Program; 27import android.filterfw.core.ShaderProgram; 28import android.filterfw.geometry.Quad; 29import android.filterfw.format.ImageFormat; 30import android.filterfw.format.ObjectFormat; 31 32/** 33 * @hide 34 */ 35public class CropFilter extends Filter { 36 37 private Program mProgram; 38 private FrameFormat mLastFormat = null; 39 40 @GenerateFieldPort(name = "owidth") 41 private int mOutputWidth = -1; 42 43 @GenerateFieldPort(name = "oheight") 44 private int mOutputHeight = -1; 45 46 @GenerateFieldPort(name = "fillblack") 47 private boolean mFillBlack = false; 48 49 public CropFilter(String name) { 50 super(name); 51 } 52 53 private final String mFragShader = 54 "precision mediump float;\n" + 55 "uniform sampler2D tex_sampler_0;\n" + 56 "varying vec2 v_texcoord;\n" + 57 "void main() {\n" + 58 " const vec2 lo = vec2(0.0, 0.0);\n" + 59 " const vec2 hi = vec2(1.0, 1.0);\n" + 60 " const vec4 black = vec4(0.0, 0.0, 0.0, 1.0);\n" + 61 " bool out_of_bounds =\n" + 62 " any(lessThan(v_texcoord, lo)) ||\n" + 63 " any(greaterThan(v_texcoord, hi));\n" + 64 " if (out_of_bounds) {\n" + 65 " gl_FragColor = black;\n" + 66 " } else {\n" + 67 " gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" + 68 " }\n" + 69 "}\n"; 70 71 @Override 72 public void setupPorts() { 73 addMaskedInputPort("image", ImageFormat.create(ImageFormat.COLORSPACE_RGBA)); 74 addMaskedInputPort("box", ObjectFormat.fromClass(Quad.class, FrameFormat.TARGET_SIMPLE)); 75 addOutputBasedOnInput("image", "image"); 76 } 77 78 @Override 79 public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) { 80 // Make sure output size is set to unspecified, as we do not know what we will be resizing 81 // to. 82 MutableFrameFormat outputFormat = inputFormat.mutableCopy(); 83 outputFormat.setDimensions(FrameFormat.SIZE_UNSPECIFIED, FrameFormat.SIZE_UNSPECIFIED); 84 return outputFormat; 85 } 86 87 protected void createProgram(FilterContext context, FrameFormat format) { 88 // TODO: Add CPU version 89 if (mLastFormat != null && mLastFormat.getTarget() == format.getTarget()) return; 90 mLastFormat = format; 91 mProgram = null; 92 switch (format.getTarget()) { 93 case FrameFormat.TARGET_GPU: 94 if(mFillBlack) 95 mProgram = new ShaderProgram(context, mFragShader); 96 else 97 mProgram = ShaderProgram.createIdentity(context); 98 99 break; 100 } 101 if (mProgram == null) { 102 throw new RuntimeException("Could not create a program for crop filter " + this + "!"); 103 } 104 } 105 106 @Override 107 public void process(FilterContext env) { 108 // Get input frame 109 Frame imageFrame = pullInput("image"); 110 Frame boxFrame = pullInput("box"); 111 112 createProgram(env, imageFrame.getFormat()); 113 114 // Get the box 115 Quad box = (Quad)boxFrame.getObjectValue(); 116 117 // Create output format 118 MutableFrameFormat outputFormat = imageFrame.getFormat().mutableCopy(); 119 outputFormat.setDimensions(mOutputWidth == -1 ? outputFormat.getWidth() : mOutputWidth, 120 mOutputHeight == -1 ? outputFormat.getHeight() : mOutputHeight); 121 122 // Create output frame 123 Frame output = env.getFrameManager().newFrame(outputFormat); 124 125 // Set the program parameters 126 if (mProgram instanceof ShaderProgram) { 127 ShaderProgram shaderProgram = (ShaderProgram)mProgram; 128 shaderProgram.setSourceRegion(box); 129 } 130 131 mProgram.process(imageFrame, output); 132 133 // Push output 134 pushOutput("image", output); 135 136 // Release pushed frame 137 output.release(); 138 } 139 140 141} 142