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 
     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