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