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.KeyValueMap; 26 import android.filterfw.core.MutableFrameFormat; 27 import android.filterfw.core.NativeProgram; 28 import android.filterfw.core.NativeFrame; 29 import android.filterfw.core.Program; 30 import android.filterfw.core.ShaderProgram; 31 import android.filterfw.format.ImageFormat; 32 import android.filterfw.geometry.Quad; 33 import android.filterfw.geometry.Point; 34 import android.util.Log; 35 36 /** 37 * @hide 38 */ 39 public class RotateFilter extends Filter { 40 41 @GenerateFieldPort(name = "angle") 42 private int mAngle; 43 44 @GenerateFieldPort(name = "tile_size", hasDefault = true) 45 private int mTileSize = 640; 46 47 private Program mProgram; 48 49 private int mWidth = 0; 50 private int mHeight = 0; 51 private int mTarget = FrameFormat.TARGET_UNSPECIFIED; 52 53 private int mOutputWidth; 54 private int mOutputHeight; 55 56 public RotateFilter(String name) { 57 super(name); 58 } 59 60 @Override 61 public void setupPorts() { 62 addMaskedInputPort("image", ImageFormat.create(ImageFormat.COLORSPACE_RGBA)); 63 addOutputBasedOnInput("image", "image"); 64 } 65 66 public void initProgram(FilterContext context, int target) { 67 switch (target) { 68 case FrameFormat.TARGET_GPU: 69 ShaderProgram shaderProgram = ShaderProgram.createIdentity(context); 70 shaderProgram.setMaximumTileSize(mTileSize); 71 shaderProgram.setClearsOutput(true); 72 mProgram = shaderProgram; 73 break; 74 75 default: 76 throw new RuntimeException("Filter Sharpen does not support frames of " + 77 "target " + target + "!"); 78 } 79 mTarget = target; 80 } 81 82 @Override 83 public void fieldPortValueUpdated(String name, FilterContext context) { 84 if (mProgram != null) { 85 updateParameters(); 86 } 87 } 88 89 @Override 90 public void process(FilterContext context) { 91 // Get input frame 92 Frame input = pullInput("image"); 93 FrameFormat inputFormat = input.getFormat(); 94 95 // Create program if not created already 96 if (mProgram == null || inputFormat.getTarget() != mTarget) { 97 initProgram(context, inputFormat.getTarget()); 98 } 99 100 if (inputFormat.getWidth() != mWidth || inputFormat.getHeight() != mHeight) { 101 mWidth = inputFormat.getWidth(); 102 mHeight = inputFormat.getHeight(); 103 mOutputWidth = mWidth; 104 mOutputHeight = mHeight; 105 106 updateParameters(); 107 } 108 109 // Create output frame 110 FrameFormat outputFormat = ImageFormat.create(mOutputWidth, mOutputHeight, 111 ImageFormat.COLORSPACE_RGBA, 112 FrameFormat.TARGET_GPU); 113 114 Frame output = context.getFrameManager().newFrame(outputFormat); 115 116 // Process 117 mProgram.process(input, output); 118 119 // Push output 120 pushOutput("image", output); 121 122 // Release pushed frame 123 output.release(); 124 } 125 126 private void updateParameters() { 127 float sinTheta; 128 float cosTheta; 129 130 if (mAngle % 90 == 0) { 131 if (mAngle % 180 == 0) { 132 sinTheta = 0f; 133 cosTheta = (mAngle % 360 == 0) ? 1f:-1f; 134 } else { 135 cosTheta = 0f; 136 sinTheta = ((mAngle + 90) % 360 == 0) ? -1f:1f; 137 138 mOutputWidth = mHeight; 139 mOutputHeight = mWidth; 140 } 141 } else { 142 throw new RuntimeException("degree has to be multiply of 90."); 143 } 144 145 Point x0 = new Point(0.5f * (-cosTheta + sinTheta + 1f), 146 0.5f * (-sinTheta - cosTheta + 1f)); 147 Point x1 = new Point(0.5f * (cosTheta + sinTheta + 1f), 148 0.5f * (sinTheta - cosTheta + 1f)); 149 Point x2 = new Point(0.5f * (-cosTheta - sinTheta + 1f), 150 0.5f * (-sinTheta + cosTheta + 1f)); 151 Point x3 = new Point(0.5f * (cosTheta - sinTheta + 1f), 152 0.5f * (sinTheta + cosTheta + 1f)); 153 Quad quad = new Quad(x0, x1, x2, x3); 154 ((ShaderProgram) mProgram).setTargetRegion(quad); 155 } 156 } 157