1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright 2013 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Takes in an array, returns the size of the array
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw.samples.simplecamera;
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.Rect;
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.hardware.Camera;
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.hardware.Camera.Face;
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log;
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Filter;
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Frame;
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameImage2D;
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameType;
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.FrameValues;
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.MffContext;
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.OutputPort;
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.Signature;
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer;
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class FaceSquareFilter extends Filter {
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final String TAG = "FaceSquareFilter";
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static boolean mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int FACE_X_RANGE = 2000;
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int WIDTH_OFFSET = 1000;
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static int HEIGHT_OFFSET = 1000;
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public FaceSquareFilter(MffContext context, String name) {
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        super(context, name);
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Signature getSignature() {
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameType imageType = FrameType.buffer2D(FrameType.ELEMENT_RGBA8888);
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameType facesType = FrameType.array(Camera.Face.class);
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return new Signature()
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                .addInputPort("image", Signature.PORT_REQUIRED, imageType)
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                .addInputPort("faces", Signature.PORT_REQUIRED, facesType)
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                .addOutputPort("image", Signature.PORT_REQUIRED, imageType)
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                .disallowOtherPorts();
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see androidx.media.filterfw.Filter#onProcess()
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    protected void onProcess() {
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // Get inputs
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameImage2D imageFrame = getConnectedInputPort("image").pullFrame().asFrameImage2D();
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameValues facesFrame = getConnectedInputPort("faces").pullFrame().asFrameValues();
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Face[] faces = (Face[]) facesFrame.getValues();
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] dims = imageFrame.getDimensions();
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ByteBuffer buffer = imageFrame.lockBytes(Frame.MODE_WRITE);
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        byte[] pixels = buffer.array();
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // For every face in faces, draw a white rect around the
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // face following the rect member of the Face
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        drawBoxes(pixels, faces, dims);
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        imageFrame.unlock();
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        OutputPort outPort = getConnectedOutputPort("image");
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        outPort.pushFrame(imageFrame);
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void drawBoxes(byte[] pixels, Face[] faces, int[] dims) {
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for(int i = 0; i < faces.length; i++) {
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Rect tempRect = faces[i].rect;
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int top = (tempRect.top+HEIGHT_OFFSET)*dims[1]/FACE_X_RANGE;
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int bottom = (tempRect.bottom+HEIGHT_OFFSET)*dims[1]/FACE_X_RANGE;
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int left = (tempRect.left+WIDTH_OFFSET)*dims[0]/FACE_X_RANGE;
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int right = (tempRect.right+WIDTH_OFFSET)*dims[0]/FACE_X_RANGE;
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (top < 0) {
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                top = 0;
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (top > dims[1]) {
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                top = dims[1];
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (left < 0) {
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                left = 0;
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (left > dims[0]) {
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                left = dims[0];
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (bottom > dims[1]) {
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                bottom = dims[1];
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (bottom < 0) {
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                bottom = 0;
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (right > dims[0]) {
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                right = dims[0];
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (right < 0) {
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                right = 0;
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (int j = 0; j < (bottom - top); j++) {
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Left edge
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (left > 0 && top > 0) {
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * (top + j) + left) +
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * (top + j) + left) +
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * (top + j) + left) +
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Right edge
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (right > 0 && top > 0) {
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * (top + j) + right) +
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * (top + j) + right) +
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * (top + j) + right) +
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (int k = 0; k < (right - left); k++) {
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Top edge
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (top < dims[1]) {
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * top + left + k) +
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * top + left + k) +
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * top + left + k) +
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Bottom edge
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (bottom < dims[1]) {
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * bottom + left + k) +
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * bottom + left + k) +
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    pixels[ImageConstants.PIX_CHANNELS * (dims[0] * bottom + left + k) +
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                           ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
160