1/*
2 * Copyright (C) 2016 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 android.uirendering.cts.testclasses;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertNotNull;
21import static org.junit.Assert.assertNull;
22import static org.junit.Assert.assertTrue;
23
24import android.content.res.Resources;
25import android.graphics.BitmapRegionDecoder;
26import android.graphics.Color;
27import android.graphics.Matrix;
28import android.graphics.Paint;
29import android.graphics.Rect;
30import android.graphics.drawable.Drawable;
31import android.graphics.drawable.NinePatchDrawable;
32import android.support.test.runner.AndroidJUnit4;
33import android.uirendering.cts.R;
34
35import android.graphics.Bitmap;
36import android.graphics.BitmapFactory;
37import android.support.test.filters.MediumTest;
38import android.uirendering.cts.bitmapcomparers.ExactComparer;
39import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
40import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
41import android.uirendering.cts.testinfrastructure.ActivityTestBase;
42import android.util.DisplayMetrics;
43
44import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
47
48import java.io.ByteArrayInputStream;
49import java.io.ByteArrayOutputStream;
50import java.io.IOException;
51import java.io.InputStream;
52
53@MediumTest
54@RunWith(AndroidJUnit4.class)
55public class HardwareBitmapTests extends ActivityTestBase {
56
57    private Resources mRes;
58
59    private static final BitmapFactory.Options HARDWARE_OPTIONS = createHardwareOptions();
60
61    private static BitmapFactory.Options createHardwareOptions() {
62        BitmapFactory.Options options = new BitmapFactory.Options();
63        options.inPreferredConfig = Bitmap.Config.HARDWARE;
64        return options;
65    }
66
67    @Before
68    public void setup() {
69        mRes = getActivity().getResources();
70    }
71
72    @Test
73    public void testDecodeResource() {
74        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
75            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
76                    HARDWARE_OPTIONS);
77            canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
78        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
79                R.drawable.golden_robot, new MSSIMComparer(0.95)));
80    }
81
82    @Test
83    public void testBitmapRegionDecode() throws IOException {
84        InputStream inputStream = mRes.openRawResource(R.drawable.robot);
85        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(inputStream, false);
86        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
87            Bitmap hardwareBitmap = decoder.decodeRegion(new Rect(10, 15, 34, 39),
88                    HARDWARE_OPTIONS);
89            canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
90        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
91                R.drawable.golden_headless_robot, new MSSIMComparer(0.95)));
92    }
93
94    @Test
95    public void testBitmapConfigFromRGB565() {
96        testBitmapCopy(R.drawable.robot, Bitmap.Config.RGB_565, Bitmap.Config.HARDWARE);
97    }
98
99    @Test
100    public void testBitmapConfigFromARGB8888() {
101        testBitmapCopy(R.drawable.robot, Bitmap.Config.ARGB_8888, Bitmap.Config.HARDWARE);
102    }
103
104    @Test
105    public void testBitmapConfigFromA8() {
106        Bitmap b = Bitmap.createBitmap(32, 32, Bitmap.Config.ALPHA_8);
107        // we do not support conversion from A8
108        assertNull(b.copy(Bitmap.Config.HARDWARE, false));
109    }
110
111    @Test
112    public void testBitmapConfigFromIndex8() {
113        testBitmapCopy(R.drawable.index_8, null, Bitmap.Config.HARDWARE);
114    }
115
116    @Test
117    public void testBitmapConfigFromHardwareToHardware() {
118        testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.HARDWARE);
119    }
120
121    @Test
122    public void testBitmapConfigFromHardwareToARGB8888() {
123        testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.ARGB_8888);
124    }
125
126    @Test
127    public void testSetDensity() {
128        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
129            Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot);
130            bitmap.setDensity(DisplayMetrics.DENSITY_LOW);
131            canvas.drawBitmap(bitmap, 0, 0, null);
132        }, true).addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
133            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
134                    HARDWARE_OPTIONS);
135            hardwareBitmap.setDensity(DisplayMetrics.DENSITY_LOW);
136            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
137        }, true).runWithComparer(new ExactComparer());
138    }
139
140    @Test
141    public void testNinePatch() {
142        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
143            InputStream is = mRes.openRawResource(R.drawable.blue_padded_square);
144            NinePatchDrawable ninePatch = (NinePatchDrawable) Drawable.createFromResourceStream(
145                    mRes, null, is, null, HARDWARE_OPTIONS);
146            ninePatch.setBounds(0, 0, width, height);
147            ninePatch.draw(canvas);
148        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
149                R.drawable.golden_hardwaretest_ninepatch, new MSSIMComparer(0.95)));
150    }
151
152    @Test
153    public void testCreateIdentityBitmap() {
154        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
155                HARDWARE_OPTIONS);
156        Bitmap newBitmap = Bitmap.createBitmap(hardwareBitmap);
157        assertEquals(hardwareBitmap, newBitmap);
158    }
159
160    @Test
161    public void testCreateScaledBitmap() {
162        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
163            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
164                    HARDWARE_OPTIONS);
165            Bitmap scaled = Bitmap.createScaledBitmap(hardwareBitmap, 24, 24, false);
166            assertEquals(Bitmap.Config.HARDWARE, scaled.getConfig());
167            canvas.drawBitmap(scaled, 0, 0, null);
168        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
169                R.drawable.golden_hardwaretest_create_scaled, new MSSIMComparer(0.9)));
170    }
171
172    @Test
173    public void testCreateSubsetBitmap() {
174        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
175            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
176                    HARDWARE_OPTIONS);
177            Matrix matrix = new Matrix();
178            matrix.setRotate(90);
179            Bitmap cropped = Bitmap.createBitmap(hardwareBitmap, 7, 7, 30, 30);
180            assertEquals(Bitmap.Config.HARDWARE, cropped.getConfig());
181            canvas.drawBitmap(cropped, 0, 0, null);
182        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
183                R.drawable.golden_hardwaretest_create_subset, new MSSIMComparer(0.9)));
184    }
185
186    @Test
187    public void testCreateTransformedBitmap() {
188        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
189            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
190                    HARDWARE_OPTIONS);
191            Matrix matrix = new Matrix();
192            matrix.setRotate(90);
193            Bitmap transformed = Bitmap.createBitmap(hardwareBitmap, 7, 7, 30, 30, matrix, false);
194            assertEquals(Bitmap.Config.HARDWARE, transformed.getConfig());
195            canvas.drawBitmap(transformed, 0, 0, null);
196        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
197                R.drawable.golden_hardwaretest_create_transformed, new MSSIMComparer(0.9)));
198    }
199
200
201    @Test
202    public void testCompressHardware() {
203        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
204                HARDWARE_OPTIONS);
205        ByteArrayOutputStream stream = new ByteArrayOutputStream();
206        assertTrue(hardwareBitmap.compress(Bitmap.CompressFormat.PNG, 50, stream));
207        Bitmap decoded = BitmapFactory.decodeStream(
208                new ByteArrayInputStream(stream.toByteArray()));
209        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
210            canvas.drawColor(Color.CYAN);
211            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
212        }, true).addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
213            canvas.drawColor(Color.CYAN);
214            canvas.drawBitmap(decoded, 0, 0, null);
215        }, true).runWithComparer(new MSSIMComparer(0.99));
216
217    }
218
219    @Test
220    public void testHardwareExtractAlpha() {
221        Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
222        bitmap.eraseColor(Color.argb(127, 250, 0, 0));
223        bitmap.setPixel(25, 25, Color.BLUE);
224
225        Bitmap hwBitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
226        Bitmap alphaBitmap = hwBitmap.extractAlpha();
227        assertEquals(Bitmap.Config.ALPHA_8, alphaBitmap.getConfig());
228        assertTrue(Color.alpha(alphaBitmap.getPixel(25, 25)) >= 254);
229        assertEquals(127, Color.alpha(alphaBitmap.getPixel(40, 40)));
230    }
231
232    private void testBitmapCopy(int id, Bitmap.Config from, Bitmap.Config to) {
233        BitmapFactory.Options options = new BitmapFactory.Options();
234        options.inScaled = false;
235        options.inPreferredConfig = from;
236        Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), id, options);
237        assertEquals(from, bitmap.getConfig());
238
239        createTest().addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
240            canvas.drawColor(Color.CYAN);
241            canvas.drawBitmap(bitmap, 0, 0, null);
242        }, true).addCanvasClientWithoutUsingPicture((canvas, width, height) -> {
243            canvas.drawColor(Color.CYAN);
244            Bitmap copy = bitmap.copy(to, false);
245            assertNotNull(copy);
246            assertEquals(to, copy.getConfig());
247            canvas.drawBitmap(copy, 0, 0, null);
248        }, true).runWithComparer(new MSSIMComparer(0.99));
249    }
250}