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 17 package android.uirendering.cts.testclasses; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 25 import android.content.res.Resources; 26 import android.graphics.Bitmap; 27 import android.graphics.BitmapFactory; 28 import android.graphics.BitmapRegionDecoder; 29 import android.graphics.Canvas; 30 import android.graphics.Color; 31 import android.graphics.Matrix; 32 import android.graphics.Paint; 33 import android.graphics.Picture; 34 import android.graphics.Rect; 35 import android.graphics.drawable.Drawable; 36 import android.graphics.drawable.NinePatchDrawable; 37 import android.uirendering.cts.R; 38 import android.uirendering.cts.bitmapcomparers.ExactComparer; 39 import android.uirendering.cts.bitmapcomparers.MSSIMComparer; 40 import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier; 41 import android.uirendering.cts.bitmapverifiers.RectVerifier; 42 import android.uirendering.cts.testinfrastructure.ActivityTestBase; 43 import android.util.DisplayMetrics; 44 45 import androidx.test.filters.MediumTest; 46 import androidx.test.runner.AndroidJUnit4; 47 48 import org.junit.Before; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 52 import java.io.ByteArrayInputStream; 53 import java.io.ByteArrayOutputStream; 54 import java.io.IOException; 55 import java.io.InputStream; 56 57 @MediumTest 58 @RunWith(AndroidJUnit4.class) 59 public class HardwareBitmapTests extends ActivityTestBase { 60 61 private Resources mRes; 62 63 private static final BitmapFactory.Options HARDWARE_OPTIONS = createHardwareOptions(); 64 createHardwareOptions()65 private static BitmapFactory.Options createHardwareOptions() { 66 BitmapFactory.Options options = new BitmapFactory.Options(); 67 options.inPreferredConfig = Bitmap.Config.HARDWARE; 68 return options; 69 } 70 71 @Before setup()72 public void setup() { 73 mRes = getActivity().getResources(); 74 } 75 76 @Test testDecodeResource()77 public void testDecodeResource() { 78 createTest().addCanvasClient((canvas, width, height) -> { 79 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 80 HARDWARE_OPTIONS); 81 canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint()); 82 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 83 R.drawable.golden_robot, new MSSIMComparer(0.95))); 84 } 85 86 @Test testCreateFromPicture()87 public void testCreateFromPicture() { 88 final Rect rect = new Rect(10, 10, 80, 80); 89 Picture picture = new Picture(); 90 { 91 Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT); 92 Paint p = new Paint(); 93 p.setAntiAlias(false); 94 p.setColor(Color.BLUE); 95 canvas.drawRect(rect, p); 96 picture.endRecording(); 97 } 98 Bitmap hardwareBitmap = Bitmap.createBitmap(picture); 99 assertEquals(TEST_WIDTH, hardwareBitmap.getWidth()); 100 assertEquals(TEST_HEIGHT, hardwareBitmap.getHeight()); 101 assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig()); 102 createTest().addCanvasClient((canvas, width, height) -> { 103 canvas.drawBitmap(hardwareBitmap, 0, 0, null); 104 }, true).runWithVerifier(new RectVerifier(Color.WHITE, Color.BLUE, rect)); 105 } 106 107 @Test testReadbackThroughPicture()108 public void testReadbackThroughPicture() { 109 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 110 HARDWARE_OPTIONS); 111 assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig()); 112 Picture picture = new Picture(); 113 { 114 Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT); 115 canvas.drawColor(Color.WHITE); 116 canvas.drawBitmap(hardwareBitmap, 0, 0, null); 117 picture.endRecording(); 118 } 119 assertTrue(picture.requiresHardwareAcceleration()); 120 Bitmap result = Bitmap.createBitmap(picture, picture.getWidth(), picture.getHeight(), 121 Bitmap.Config.ARGB_8888); 122 assertTrue(new GoldenImageVerifier(getActivity(), 123 R.drawable.golden_robot, new MSSIMComparer(0.95)).verify(result)); 124 } 125 126 @Test testReadbackThroughPictureNoEndRecording()127 public void testReadbackThroughPictureNoEndRecording() { 128 // Exact same test as #testReadbackThroughPicture but with an omitted endRecording 129 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 130 HARDWARE_OPTIONS); 131 assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig()); 132 Picture picture = new Picture(); 133 { 134 Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT); 135 canvas.drawColor(Color.WHITE); 136 canvas.drawBitmap(hardwareBitmap, 0, 0, null); 137 } 138 // It will be true, but as endRecording hasn't been called yet it's still in the 139 // "false" state from beginRecording() 140 assertFalse(picture.requiresHardwareAcceleration()); 141 Bitmap result = Bitmap.createBitmap(picture, picture.getWidth(), picture.getHeight(), 142 Bitmap.Config.ARGB_8888); 143 assertTrue(new GoldenImageVerifier(getActivity(), 144 R.drawable.golden_robot, new MSSIMComparer(0.95)).verify(result)); 145 } 146 147 @Test testCreateScaledBitmapFromPicture()148 public void testCreateScaledBitmapFromPicture() { 149 Picture picture = new Picture(); 150 { 151 Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS); 152 Canvas canvas = picture.beginRecording(bitmap.getWidth(), bitmap.getHeight()); 153 Paint paint = new Paint(); 154 paint.setFilterBitmap(true); 155 paint.setAntiAlias(true); 156 canvas.drawBitmap(bitmap, 0, 0, paint); 157 picture.endRecording(); 158 } 159 assertTrue(picture.requiresHardwareAcceleration()); 160 Bitmap scaled = Bitmap.createBitmap(picture, 24, 24, Bitmap.Config.HARDWARE); 161 createTest().addCanvasClient((canvas, width, height) -> { 162 assertEquals(Bitmap.Config.HARDWARE, scaled.getConfig()); 163 canvas.drawBitmap(scaled, 0, 0, null); 164 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 165 R.drawable.golden_hardwaretest_create_scaled, new MSSIMComparer(0.9))); 166 } 167 168 @Test testBitmapRegionDecode()169 public void testBitmapRegionDecode() throws IOException { 170 InputStream inputStream = mRes.openRawResource(R.drawable.robot); 171 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(inputStream, false); 172 createTest().addCanvasClient((canvas, width, height) -> { 173 Bitmap hardwareBitmap = decoder.decodeRegion(new Rect(10, 15, 34, 39), 174 HARDWARE_OPTIONS); 175 canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint()); 176 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 177 R.drawable.golden_headless_robot, new MSSIMComparer(0.95))); 178 } 179 180 @Test testBitmapConfigFromRGB565()181 public void testBitmapConfigFromRGB565() { 182 testBitmapCopy(R.drawable.robot, Bitmap.Config.RGB_565, Bitmap.Config.HARDWARE); 183 } 184 185 @Test testBitmapConfigFromARGB8888()186 public void testBitmapConfigFromARGB8888() { 187 testBitmapCopy(R.drawable.robot, Bitmap.Config.ARGB_8888, Bitmap.Config.HARDWARE); 188 } 189 190 @Test testBitmapConfigFromHardwareToHardware()191 public void testBitmapConfigFromHardwareToHardware() { 192 testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.HARDWARE); 193 } 194 195 @Test testBitmapConfigFromHardwareToARGB8888()196 public void testBitmapConfigFromHardwareToARGB8888() { 197 testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.ARGB_8888); 198 } 199 200 @Test testSetDensity()201 public void testSetDensity() { 202 createTest().addCanvasClient((canvas, width, height) -> { 203 Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot); 204 bitmap.setDensity(DisplayMetrics.DENSITY_LOW); 205 canvas.drawBitmap(bitmap, 0, 0, null); 206 }, true).addCanvasClient((canvas, width, height) -> { 207 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 208 HARDWARE_OPTIONS); 209 hardwareBitmap.setDensity(DisplayMetrics.DENSITY_LOW); 210 canvas.drawBitmap(hardwareBitmap, 0, 0, null); 211 }, true).runWithComparer(new ExactComparer()); 212 } 213 214 @Test testNinePatch()215 public void testNinePatch() { 216 createTest().addCanvasClient((canvas, width, height) -> { 217 InputStream is = mRes.openRawResource(R.drawable.blue_padded_square); 218 NinePatchDrawable ninePatch = (NinePatchDrawable) Drawable.createFromResourceStream( 219 mRes, null, is, null, HARDWARE_OPTIONS); 220 ninePatch.setBounds(0, 0, width, height); 221 ninePatch.setFilterBitmap(false); 222 ninePatch.draw(canvas); 223 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 224 R.drawable.golden_hardwaretest_ninepatch, new MSSIMComparer(0.95))); 225 } 226 227 @Test testCreateIdentityBitmap()228 public void testCreateIdentityBitmap() { 229 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 230 HARDWARE_OPTIONS); 231 Bitmap newBitmap = Bitmap.createBitmap(hardwareBitmap); 232 assertEquals(hardwareBitmap, newBitmap); 233 } 234 235 @Test testCreateScaledBitmap()236 public void testCreateScaledBitmap() { 237 createTest().addCanvasClient((canvas, width, height) -> { 238 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 239 HARDWARE_OPTIONS); 240 Bitmap scaled = Bitmap.createScaledBitmap(hardwareBitmap, 24, 24, true); 241 assertEquals(Bitmap.Config.HARDWARE, scaled.getConfig()); 242 canvas.drawBitmap(scaled, 0, 0, null); 243 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 244 R.drawable.golden_hardwaretest_create_scaled, new MSSIMComparer(0.9))); 245 } 246 247 @Test testCreateSubsetBitmap()248 public void testCreateSubsetBitmap() { 249 createTest().addCanvasClient((canvas, width, height) -> { 250 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 251 HARDWARE_OPTIONS); 252 Matrix matrix = new Matrix(); 253 matrix.setRotate(90); 254 Bitmap cropped = Bitmap.createBitmap(hardwareBitmap, 7, 7, 30, 30); 255 assertEquals(Bitmap.Config.HARDWARE, cropped.getConfig()); 256 canvas.drawBitmap(cropped, 0, 0, null); 257 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 258 R.drawable.golden_hardwaretest_create_subset, new MSSIMComparer(0.9))); 259 } 260 261 @Test testCreateTransformedBitmap()262 public void testCreateTransformedBitmap() { 263 createTest().addCanvasClient((canvas, width, height) -> { 264 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 265 HARDWARE_OPTIONS); 266 Matrix matrix = new Matrix(); 267 matrix.setRotate(90); 268 Bitmap transformed = Bitmap.createBitmap(hardwareBitmap, 7, 7, 30, 30, matrix, false); 269 assertEquals(Bitmap.Config.HARDWARE, transformed.getConfig()); 270 canvas.drawBitmap(transformed, 0, 0, null); 271 }, true).runWithVerifier(new GoldenImageVerifier(getActivity(), 272 R.drawable.golden_hardwaretest_create_transformed, new MSSIMComparer(0.9))); 273 } 274 275 @Test testCompressHardware()276 public void testCompressHardware() { 277 Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, 278 HARDWARE_OPTIONS); 279 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 280 assertTrue(hardwareBitmap.compress(Bitmap.CompressFormat.PNG, 50, stream)); 281 Bitmap decoded = BitmapFactory.decodeStream( 282 new ByteArrayInputStream(stream.toByteArray())); 283 createTest().addCanvasClient((canvas, width, height) -> { 284 canvas.drawColor(Color.CYAN); 285 canvas.drawBitmap(hardwareBitmap, 0, 0, null); 286 }, true).addCanvasClient((canvas, width, height) -> { 287 canvas.drawColor(Color.CYAN); 288 canvas.drawBitmap(decoded, 0, 0, null); 289 }, true).runWithComparer(new MSSIMComparer(0.99)); 290 291 } 292 293 @Test testHardwareExtractAlpha()294 public void testHardwareExtractAlpha() { 295 Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888); 296 bitmap.eraseColor(Color.argb(127, 250, 0, 0)); 297 bitmap.setPixel(25, 25, Color.BLUE); 298 299 Bitmap hwBitmap = bitmap.copy(Bitmap.Config.HARDWARE, false); 300 Bitmap alphaBitmap = hwBitmap.extractAlpha(); 301 assertEquals(Bitmap.Config.ALPHA_8, alphaBitmap.getConfig()); 302 assertTrue(Color.alpha(alphaBitmap.getPixel(25, 25)) >= 254); 303 assertEquals(127, Color.alpha(alphaBitmap.getPixel(40, 40))); 304 } 305 testBitmapCopy(int id, Bitmap.Config from, Bitmap.Config to)306 private void testBitmapCopy(int id, Bitmap.Config from, Bitmap.Config to) { 307 BitmapFactory.Options options = new BitmapFactory.Options(); 308 options.inScaled = false; 309 options.inPreferredConfig = from; 310 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), id, options); 311 assertEquals(from, bitmap.getConfig()); 312 313 createTest().addCanvasClient((canvas, width, height) -> { 314 canvas.drawColor(Color.CYAN); 315 canvas.drawBitmap(bitmap, 0, 0, null); 316 }, true).addCanvasClient((canvas, width, height) -> { 317 canvas.drawColor(Color.CYAN); 318 Bitmap copy = bitmap.copy(to, false); 319 assertNotNull(copy); 320 assertEquals(to, copy.getConfig()); 321 canvas.drawBitmap(copy, 0, 0, null); 322 }, true).runWithComparer(new MSSIMComparer(0.99)); 323 } 324 } 325