1/*
2 * Copyright 2013 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
17package androidx.media.filterfw.samples.simplecamera;
18
19
20import android.content.res.AssetManager;
21import android.graphics.Bitmap;
22import android.graphics.BitmapFactory;
23import android.net.Uri;
24import android.provider.MediaStore;
25
26import androidx.media.filterfw.Filter;
27import androidx.media.filterfw.FrameImage2D;
28import androidx.media.filterfw.FrameType;
29import androidx.media.filterfw.FrameValues;
30import androidx.media.filterfw.MffContext;
31import androidx.media.filterfw.MffFilterTestCase;
32
33import java.io.FileNotFoundException;
34import java.io.IOException;
35import java.util.concurrent.ExecutionException;
36import java.util.concurrent.TimeoutException;
37
38import android.hardware.Camera;
39import android.hardware.Camera.Face;
40import android.graphics.Rect;
41
42
43public class FaceSquareFilterTest extends MffFilterTestCase {
44
45    private AssetManager assetMgr = null;
46    @Override
47    protected Filter createFilter(MffContext mffContext) {
48        assetMgr = mffContext.getApplicationContext().getAssets();
49        return new FaceSquareFilter(mffContext, "faceSquareFilter");
50    }
51
52    public void testFaceSquareFilter() throws Exception{
53        final int INPUT_WIDTH = 1536;
54        final int INPUT_HEIGHT = 2048;
55        FrameImage2D image =
56                createFrame(FrameType.image2D(FrameType.ELEMENT_RGBA8888, FrameType.READ_CPU),
57                        new int[] {INPUT_WIDTH,INPUT_HEIGHT}).asFrameImage2D();
58
59        FrameValues facesFrame = createFrame(FrameType.array(Camera.Face.class), new int[] {1,1}).
60                asFrameValues();
61
62        Bitmap bitmap = BitmapFactory.decodeStream(assetMgr.open("XZZ019.jpg"));
63        image.setBitmap(bitmap);
64        injectInputFrame("image", image);
65
66        Face face = new Face();
67        Rect faceRect = new Rect();
68        // These are the values for image 141 with 1 face
69        faceRect.set(-533, -453, 369, 224);
70        face.rect = faceRect;
71        Face[] faces = new Face[1];
72        faces[0] = face;
73        facesFrame.setValue(faces);
74        injectInputFrame("faces", facesFrame);
75        process();
76
77        // ensure the output image has the rectangle in the right place
78        FrameImage2D outputImage = getOutputFrame("image").asFrameImage2D();
79        int[] pixels = new int[bitmap.getByteCount()];
80        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),
81                bitmap.getHeight());
82
83        final int FACE_X_RANGE = 2000;
84        final int WIDTH_OFFSET = 1000;
85        final int HEIGHT_OFFSET = 1000;
86
87        int top = (faceRect.top+HEIGHT_OFFSET)*bitmap.getHeight()/FACE_X_RANGE;
88        int bottom = (faceRect.bottom+HEIGHT_OFFSET)*bitmap.getHeight()/FACE_X_RANGE;
89        int left = (faceRect.left+WIDTH_OFFSET)*bitmap.getWidth()/FACE_X_RANGE;
90        int right = (faceRect.right+WIDTH_OFFSET)*bitmap.getWidth()/FACE_X_RANGE;
91
92        if (top < 0) {
93            top = 0;
94        } else if (top > bitmap.getHeight()) {
95            top = bitmap.getHeight();
96        }
97        if (left < 0) {
98            left = 0;
99        } else if (left > bitmap.getWidth()) {
100            left = bitmap.getWidth();
101        }
102        if (bottom > bitmap.getHeight()) {
103            bottom = bitmap.getHeight();
104        } else if (bottom < 0) {
105            bottom = 0;
106        }
107        if (right > bitmap.getWidth()) {
108            right = bitmap.getWidth();
109        } else if (right < 0) {
110            right = 0;
111        }
112
113        for (int j = 0; j < (bottom - top); j++) {
114            // Left edge
115            if (left > 0 && top > 0) {
116                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * (top + j) + left) +
117                       ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
118                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * (top + j) + left) +
119                       ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
120                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * (top + j) + left) +
121                       ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
122            }
123
124            // Right edge
125            if (right > 0 && top > 0) {
126                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * (top + j) + right) +
127                       ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
128                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * (top + j) + right) +
129                       ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
130                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * (top + j) + right) +
131                       ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
132            }
133
134        }
135        for (int k = 0; k < (right - left); k++) {
136            // Top edge
137            if (top < bitmap.getHeight()) {
138                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * top + left + k) +
139                       ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
140                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * top + left + k) +
141                       ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
142                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * top + left + k) +
143                       ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
144
145            }
146            // Bottom edge
147            if (bottom < bitmap.getHeight()) {
148                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * bottom + left + k) +
149                       ImageConstants.RED_OFFSET] = (byte) ImageConstants.MAX_BYTE;
150                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * bottom + left + k) +
151                       ImageConstants.GREEN_OFFSET] = (byte) ImageConstants.MAX_BYTE;
152                pixels[ImageConstants.PIX_CHANNELS * (bitmap.getWidth() * bottom + left + k) +
153                       ImageConstants.BLUE_OFFSET] = (byte) ImageConstants.MAX_BYTE;
154            }
155        }
156
157        Bitmap outputBitmap = outputImage.toBitmap();
158        int[] outputPixels = new int[outputBitmap.getByteCount()];
159        outputBitmap.getPixels(outputPixels, 0, outputBitmap.getWidth(), 0, 0,
160                outputBitmap.getWidth(), outputBitmap.getHeight());
161        int equalCount = 0;
162        for ( int i = 0; i < outputBitmap.getByteCount(); i++) {
163            if (pixels[i] == outputPixels[i])
164                equalCount++;
165        }
166
167        if (equalCount + (0.05f*outputBitmap.getByteCount()) < outputBitmap.getByteCount()) {
168            // Assertion will fail if condition is true
169            assertEquals(equalCount, outputBitmap.getByteCount());
170        }
171    }
172}