130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni/*
230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Copyright (C) 2011 The Android Open Source Project
330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Licensed under the Apache License, Version 2.0 (the "License");
530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * you may not use this file except in compliance with the License.
630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * You may obtain a copy of the License at
730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *      http://www.apache.org/licenses/LICENSE-2.0
930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
1030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Unless required by applicable law or agreed to in writing, software
1130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * distributed under the License is distributed on an "AS IS" BASIS,
1230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * See the License for the specific language governing permissions and
1430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * limitations under the License.
1530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */
1630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronipackage android.filterpacks.imageproc;
1930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Filter;
21692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Rennimport android.filterfw.core.FilterContext;
2230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Frame;
2330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FrameFormat;
2421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.core.GenerateFieldPort;
2530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.GLFrame;
2630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.NativeProgram;
2730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.NativeFrame;
2830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Program;
2930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.ShaderProgram;
3030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.geometry.Quad;
31c0017fd82acec5d0427306ea5f536c3d78854f95Marius Rennimport android.filterfw.format.ImageFormat;
3221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.format.ObjectFormat;
3321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn
3430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.opengl.GLES20;
3530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
36a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala/**
37a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala * @hide
38a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala */
3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronipublic class DrawRectFilter extends Filter {
4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "colorRed",  hasDefault = true)
4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private float mColorRed = 0.8f;
4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "colorGreen", hasDefault = true)
4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private float mColorGreen = 0.8f;
4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    @GenerateFieldPort(name = "colorBlue", hasDefault = true)
4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private float mColorBlue = 0.0f;
4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final String mVertexShader =
5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "attribute vec4 aPosition;\n" +
5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "void main() {\n" +
5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "  gl_Position = aPosition;\n" +
5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "}\n";
5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final String mFixedColorFragmentShader =
5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "precision mediump float;\n" +
5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "uniform vec4 color;\n" +
5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "void main() {\n" +
6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "  gl_FragColor = color;\n" +
6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "}\n";
6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    private ShaderProgram mProgram;
6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public DrawRectFilter(String name) {
6721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        super(name);
6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
7033d107bf315c9cc01a02a7a4a2c10a01f62e8c85Wei Hua    @Override
7121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void setupPorts() {
7221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        addMaskedInputPort("image", ImageFormat.create(ImageFormat.COLORSPACE_RGBA,
7321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn                                                       FrameFormat.TARGET_GPU));
74bf4aaebc555cfb1e49ee411e3477203749fe6a11Marius Renn        addMaskedInputPort("box", ObjectFormat.fromClass(Quad.class, FrameFormat.TARGET_SIMPLE));
7521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        addOutputBasedOnInput("image", "image");
7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
7833d107bf315c9cc01a02a7a4a2c10a01f62e8c85Wei Hua    @Override
7921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) {
8021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        return inputFormat;
8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
8333d107bf315c9cc01a02a7a4a2c10a01f62e8c85Wei Hua    @Override
84511360e61650864ea22a171159efe073c80d0cdbMarius Renn    public void prepare(FilterContext context) {
85511360e61650864ea22a171159efe073c80d0cdbMarius Renn        mProgram = new ShaderProgram(context, mVertexShader, mFixedColorFragmentShader);
8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
8833d107bf315c9cc01a02a7a4a2c10a01f62e8c85Wei Hua    @Override
8921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn    public void process(FilterContext env) {
9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Get input frame
9121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        Frame imageFrame = pullInput("image");
9221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        Frame boxFrame = pullInput("box");
9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Get the box
9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        Quad box = (Quad)boxFrame.getObjectValue();
9630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        box = box.scaled(2.0f).translated(-1.0f, -1.0f);
9730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
9830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Create output frame with copy of input
99f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn        GLFrame output = (GLFrame)env.getFrameManager().duplicateFrame(imageFrame);
10030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Draw onto output
10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        output.focus();
10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        renderBox(box);
10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
10530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Push output
10621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn        pushOutput("image", output);
10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Release pushed frame
10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        output.release();
11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private void renderBox(Quad box) {
11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        final int FLOAT_SIZE = 4;
11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Get current values
11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        float[] color = {mColorRed, mColorGreen, mColorBlue, 1f};
11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        float[] vertexValues = { box.p0.x, box.p0.y,
11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                 box.p1.x, box.p1.y,
11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                 box.p3.x, box.p3.y,
12030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                 box.p2.x, box.p2.y };
12130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
12230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Set the program variables
12330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mProgram.setHostValue("color", color);
12430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mProgram.setAttributeValues("aPosition", vertexValues, 2);
12530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mProgram.setVertexCount(4);
12630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
12730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Draw
12830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mProgram.beginDrawing();
12930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        GLES20.glLineWidth(1.0f);
13030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, 4);
13130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
13230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
133