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