1 /* 2 * Copyright (C) 2023 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 junit.framework.Assert.assertFalse; 20 21 import static org.testng.Assert.assertEquals; 22 import static org.testng.Assert.assertTrue; 23 24 import android.graphics.Bitmap; 25 import android.graphics.BitmapShader; 26 import android.graphics.Canvas; 27 import android.graphics.Color; 28 import android.graphics.ColorSpace; 29 import android.graphics.Gainmap; 30 import android.graphics.HardwareBufferRenderer; 31 import android.graphics.Matrix; 32 import android.graphics.Paint; 33 import android.graphics.Picture; 34 import android.graphics.RecordingCanvas; 35 import android.graphics.RenderNode; 36 import android.graphics.Shader; 37 import android.hardware.HardwareBuffer; 38 import android.platform.test.annotations.RequiresFlagsEnabled; 39 import android.platform.test.flag.junit.CheckFlagsRule; 40 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 41 import android.uirendering.cts.bitmapverifiers.ColorVerifier; 42 import android.uirendering.cts.util.BitmapAsserter; 43 import android.uirendering.cts.util.BitmapDumper; 44 45 import androidx.annotation.ColorLong; 46 import androidx.test.filters.SmallTest; 47 import androidx.test.runner.AndroidJUnit4; 48 49 import com.android.graphics.hwui.flags.Flags; 50 51 import org.junit.Rule; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 import org.testng.Assert; 55 56 import java.util.concurrent.CountDownLatch; 57 import java.util.concurrent.TimeUnit; 58 import java.util.function.Consumer; 59 60 @SmallTest 61 @RunWith(AndroidJUnit4.class) 62 public class GainmapTests { 63 64 @Rule 65 public final CheckFlagsRule mCheckFlagsRule = 66 DeviceFlagsValueProvider.createCheckFlagsRule(); 67 68 69 private static final ColorSpace BT2020_HLG = ColorSpace.get(ColorSpace.Named.BT2020_HLG); 70 private static final ColorSpace BT2020_PQ = ColorSpace.get(ColorSpace.Named.BT2020_PQ); 71 private static final ColorSpace BT2020 = ColorSpace.get(ColorSpace.Named.BT2020); 72 private static final ColorSpace SRGB = ColorSpace.get(ColorSpace.Named.SRGB); 73 74 // A 10x6 base image with a 5x3 (so 1/2 res) gainmap that boosts the center 3 pixels 75 // by 0x40, 0x80, and 0xff respectively 76 private static final Bitmap sTestImage; 77 static { 78 Bitmap base = Bitmap.createBitmap(10, 6, Bitmap.Config.ARGB_8888); 79 base.eraseColor(Color.WHITE); 80 81 Bitmap gainmapImage = Bitmap.createBitmap(5, 3, Bitmap.Config.ARGB_8888); 82 gainmapImage.eraseColor(0); 83 gainmapImage.setPixel(1, 1, 0xFF404040); 84 gainmapImage.setPixel(2, 1, 0xFF808080); 85 gainmapImage.setPixel(3, 1, 0xFFFFFFFF); 86 87 Gainmap gainmap = new Gainmap(gainmapImage); 88 base.setGainmap(gainmap); 89 sTestImage = base; 90 } 91 92 // A 10x6 HLG base image with a 1x1 gainmap that annihilates the red and blue 93 // components in an sRGB working space. 94 private static final Bitmap sHLGTestImage; 95 static { 96 Bitmap base = Bitmap.createBitmap(10, 6, Bitmap.Config.ARGB_8888); 97 base.eraseColor(Color.WHITE); 98 base.setColorSpace(BT2020_HLG); 99 100 Bitmap gainmapImage = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 101 gainmapImage.setPixel(0, 0, 0xFFFF00FF); 102 Gainmap gainmap = new Gainmap(gainmapImage); 103 if (Flags.isoGainmapApis()) { 104 gainmap.setGainmapDirection(Gainmap.GAINMAP_DIRECTION_HDR_TO_SDR); 105 gainmap.setAlternativeImagePrimaries(SRGB); 106 } 107 gainmap.setRatioMax(100000000f, 100000000f, 100000000f); 108 gainmap.setRatioMin(3.789f, 3.789f, 3.789f); 109 base.setGainmap(gainmap); 110 sHLGTestImage = base; 111 } 112 113 // A 10x6 base image with a 5x3 (so 1/2 res) gainmap that boosts the center 3 pixels 114 // by 0x40, 0x80, and 0xff respectively 115 private static final Bitmap sTestImageA8; 116 static { 117 Bitmap base = Bitmap.createBitmap(10, 6, Bitmap.Config.ARGB_8888); 118 base.eraseColor(Color.WHITE); 119 120 Bitmap gainmapImage = Bitmap.createBitmap(5, 3, Bitmap.Config.ALPHA_8); 121 gainmapImage.eraseColor(0); 122 gainmapImage.setPixel(1, 1, 0x40000000); 123 gainmapImage.setPixel(2, 1, 0x80000000); 124 gainmapImage.setPixel(3, 1, 0xFF000000); 125 126 Gainmap gainmap = new Gainmap(gainmapImage); 127 base.setGainmap(gainmap); 128 sTestImageA8 = base; 129 } 130 131 private static final Picture sTestPicture; 132 static { 133 sTestPicture = new Picture(); 134 Canvas canvas = sTestPicture.beginRecording(sTestImage.getWidth(), sTestImage.getHeight()); canvas.drawBitmap(sTestImage, 0, 0, null)135 canvas.drawBitmap(sTestImage, 0, 0, null); sTestPicture.endRecording()136 sTestPicture.endRecording(); 137 } 138 139 private static final Picture sHLGTestPicture; 140 static { 141 sHLGTestPicture = new Picture(); 142 Canvas canvas = sHLGTestPicture.beginRecording( 143 sHLGTestImage.getWidth(), sHLGTestImage.getHeight()); canvas.drawBitmap(sHLGTestImage, 0, 0, null)144 canvas.drawBitmap(sHLGTestImage, 0, 0, null); sHLGTestPicture.endRecording()145 sHLGTestPicture.endRecording(); 146 } 147 148 private static final Gainmap sNoOpGainmap; 149 static { 150 sNoOpGainmap = new Gainmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8)); 151 sNoOpGainmap.setRatioMin(1f, 1f, 1f); 152 sNoOpGainmap.setRatioMax(1f, 1f, 1f); 153 } 154 assertChannels(Color result, @ColorLong long expected, float delta)155 private static void assertChannels(Color result, @ColorLong long expected, float delta) { 156 ColorSpace.Connector connector = ColorSpace.connect(Color.colorSpace(expected), 157 result.getColorSpace()); 158 float[] mapped = connector.transform(Color.red(expected), Color.green(expected), 159 Color.blue(expected)); 160 Assert.assertEquals(result.red(), mapped[0], delta, "red channel mismatch"); 161 Assert.assertEquals(result.green(), mapped[1], delta, "green channel mismatch"); 162 Assert.assertEquals(result.blue(), mapped[2], delta, "blue channel mismatch"); 163 } 164 165 @ColorLong mapWhiteWithGain(Gainmap gainmap, double gain)166 private static long mapWhiteWithGain(Gainmap gainmap, double gain) { 167 double logRatioMin = Math.log(gainmap.getRatioMin()[0]); 168 double logRatioMax = Math.log(gainmap.getRatioMax()[0]); 169 double epsilonSdr = gainmap.getEpsilonSdr()[0]; 170 double epsilonHdr = gainmap.getEpsilonHdr()[0]; 171 double L = (logRatioMin * (1 - gain)) + (logRatioMax * gain); 172 float D = (float) ((1.0 + epsilonSdr) * Math.exp(L) - epsilonHdr); 173 return Color.pack(D, D, D, 1.f, ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB)); 174 } 175 assertTestImageResult(Bitmap result)176 private void assertTestImageResult(Bitmap result) { 177 assertTestImageResult(result, sTestImage.getGainmap()); 178 } 179 toleranceForResult(Bitmap result)180 private static float toleranceForResult(Bitmap result) { 181 // 8888 precision ain't so great 182 if (result.getConfig() == Bitmap.Config.ARGB_8888) { 183 // PQ math on GLES2.0 is very poor 184 if (result.getColorSpace().getId() == ColorSpace.Named.BT2020_PQ.ordinal() 185 || result.getColorSpace().getId() == ColorSpace.Named.BT2020.ordinal()) { 186 return 0.06f; 187 } 188 return 0.02f; 189 } 190 return 0.004f; 191 } 192 assertTestImageResult(Bitmap result, Gainmap gainmap)193 private void assertTestImageResult(Bitmap result, Gainmap gainmap) { 194 try { 195 // 8888 precision ain't so great 196 final float delta = toleranceForResult(result); 197 assertChannels(result.getColor(0, 0), Color.pack(Color.WHITE), delta); 198 assertChannels(result.getColor(2, 2), 199 mapWhiteWithGain(gainmap, 0x40 / 255.f), delta); 200 assertChannels(result.getColor(4, 2), 201 mapWhiteWithGain(gainmap, 0x80 / 255.f), delta); 202 assertChannels(result.getColor(6, 2), 203 mapWhiteWithGain(gainmap, 0xFF / 255.f), delta); 204 } catch (Throwable t) { 205 BitmapDumper.dumpBitmap(result); 206 throw t; 207 } 208 } 209 assertFullyAppliedHLGTestImageResult(Bitmap result)210 private void assertFullyAppliedHLGTestImageResult(Bitmap result) { 211 try { 212 final float delta = toleranceForResult(result); 213 // Note: maps a BT. 2020 color to an sRGB Green 214 assertChannels(result.getColor(0, 0), Color.pack(Color.GREEN), delta); 215 assertChannels(result.getColor(2, 2), Color.pack(Color.GREEN), delta); 216 assertChannels(result.getColor(4, 2), Color.pack(Color.GREEN), delta); 217 assertChannels(result.getColor(6, 2), Color.pack(Color.GREEN), delta); 218 } catch (Throwable t) { 219 BitmapDumper.dumpBitmap(result); 220 throw t; 221 } 222 } 223 renderTestImageWithHardware(ColorSpace dest)224 private static Bitmap renderTestImageWithHardware(ColorSpace dest) { 225 return renderTestImageWithHardware(dest, false); 226 } 227 renderWithHardware(ColorSpace dest, Consumer<RecordingCanvas> func)228 private static Bitmap renderWithHardware(ColorSpace dest, Consumer<RecordingCanvas> func) { 229 HardwareBuffer buffer = HardwareBuffer.create(sTestImage.getWidth(), sTestImage.getHeight(), 230 HardwareBuffer.RGBA_8888, 231 1, HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE); 232 HardwareBufferRenderer renderer = new HardwareBufferRenderer(buffer); 233 RenderNode content = new RenderNode("gainmap"); 234 content.setPosition(0, 0, sTestImage.getWidth(), sTestImage.getHeight()); 235 RecordingCanvas canvas = content.beginRecording(); 236 func.accept(canvas); 237 content.endRecording(); 238 renderer.setContentRoot(content); 239 CountDownLatch latch = new CountDownLatch(1); 240 renderer.obtainRenderRequest().setColorSpace(dest).draw(Runnable::run, result -> { 241 result.getFence().awaitForever(); 242 latch.countDown(); 243 }); 244 try { 245 Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); 246 } catch (InterruptedException ex) { 247 Assert.fail(ex.getMessage()); 248 } 249 return Bitmap.wrapHardwareBuffer(buffer, dest).copy(Bitmap.Config.ARGB_8888, false); 250 } 251 renderTestImageWithHardware(Bitmap bitmap, ColorSpace dest)252 private static Bitmap renderTestImageWithHardware(Bitmap bitmap, ColorSpace dest) { 253 return renderWithHardware(dest, canvas -> { 254 canvas.drawBitmap(bitmap, 0, 0, null); 255 }); 256 } 257 renderTestPictureWithHardware(Picture picture, ColorSpace dest)258 private static Bitmap renderTestPictureWithHardware(Picture picture, ColorSpace dest) { 259 return renderWithHardware(dest, canvas -> { 260 canvas.drawPicture(picture); 261 }); 262 } 263 264 private static Bitmap renderTestImageWithHardware(ColorSpace dest, boolean usePicture) { 265 if (usePicture) { 266 return renderTestPictureWithHardware(sTestPicture, dest); 267 } else { 268 return renderTestImageWithHardware(sTestImage, dest); 269 } 270 } 271 272 @Test 273 public void gainmapToHlgSoftware() { 274 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 275 Canvas canvas = new Canvas(result); 276 canvas.drawBitmap(sTestImage, 0f, 0f, null); 277 assertTestImageResult(result); 278 canvas.drawBitmap(sTestImageA8, 0f, 0f, null); 279 assertTestImageResult(result); 280 } 281 282 @Test 283 public void gainmapToPqSoftware() { 284 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_PQ); 285 Canvas canvas = new Canvas(result); 286 canvas.drawBitmap(sTestImage, 0f, 0f, null); 287 assertTestImageResult(result); 288 canvas.drawBitmap(sTestImageA8, 0f, 0f, null); 289 assertTestImageResult(result); 290 } 291 292 @Test 293 public void gainmapToSrgbSoftware() { 294 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, SRGB); 295 Canvas canvas = new Canvas(result); 296 canvas.drawBitmap(sTestImage, 0f, 0f, null); 297 assertTestImageResult(result, sNoOpGainmap); 298 } 299 300 @RequiresFlagsEnabled(Flags.FLAG_ISO_GAINMAP_APIS) 301 @Test 302 public void hlgGainmapToBt2020Software() { 303 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020); 304 Canvas canvas = new Canvas(result); 305 canvas.drawBitmap(sHLGTestImage, 0f, 0f, null); 306 assertFullyAppliedHLGTestImageResult(result); 307 } 308 309 @Test 310 public void gainmapToHlgPictureSoftware() { 311 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 312 Canvas canvas = new Canvas(result); 313 canvas.drawPicture(sTestPicture); 314 assertTestImageResult(result); 315 } 316 317 @Test 318 public void gainmapToPqPictureSoftware() { 319 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 320 Canvas canvas = new Canvas(result); 321 canvas.drawPicture(sTestPicture); 322 assertTestImageResult(result); 323 } 324 325 @Test 326 public void gainmapToSrgbPictureSoftware() { 327 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, SRGB); 328 Canvas canvas = new Canvas(result); 329 canvas.drawPicture(sTestPicture); 330 assertTestImageResult(result, sNoOpGainmap); 331 } 332 333 @RequiresFlagsEnabled(Flags.FLAG_ISO_GAINMAP_APIS) 334 @Test 335 public void hlgGainmapToBt2020PictureSoftware() { 336 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020); 337 Canvas canvas = new Canvas(result); 338 canvas.drawPicture(sHLGTestPicture); 339 assertFullyAppliedHLGTestImageResult(result); 340 } 341 342 @Test 343 public void gainmapToHlgHardware() throws Exception { 344 Bitmap result = renderTestImageWithHardware(BT2020_HLG); 345 assertTestImageResult(result); 346 } 347 348 @Test 349 public void gainmapToPqHardware() { 350 Bitmap result = renderTestImageWithHardware(BT2020_PQ); 351 assertTestImageResult(result); 352 } 353 354 @Test 355 public void gainmapToSrgbHardware() { 356 Bitmap result = renderTestImageWithHardware(SRGB); 357 assertTestImageResult(result, sNoOpGainmap); 358 } 359 360 @RequiresFlagsEnabled(Flags.FLAG_ISO_GAINMAP_APIS) 361 @Test 362 public void hlgGainmapToBt2020Hardware() { 363 Bitmap result = renderTestImageWithHardware(sHLGTestImage, BT2020); 364 assertFullyAppliedHLGTestImageResult(result); 365 } 366 367 @Test 368 public void gainmapToHlgPictureHardware() throws Exception { 369 Bitmap result = renderTestImageWithHardware(BT2020_HLG, true); 370 assertTestImageResult(result); 371 } 372 373 @Test 374 public void gainmapToPqPictureHardware() { 375 Bitmap result = renderTestImageWithHardware(BT2020_PQ, true); 376 assertTestImageResult(result); 377 } 378 379 @Test 380 public void gainmapToSrgbPictureHardware() { 381 Bitmap result = renderTestImageWithHardware(SRGB, true); 382 assertTestImageResult(result, sNoOpGainmap); 383 } 384 385 @RequiresFlagsEnabled(Flags.FLAG_ISO_GAINMAP_APIS) 386 @Test 387 public void hlgGainmapToBt2020PictureHardware() { 388 Bitmap result = renderTestPictureWithHardware(sHLGTestPicture, BT2020); 389 assertFullyAppliedHLGTestImageResult(result); 390 } 391 392 @Test 393 public void bitmapShaderSupportHLG() { 394 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 395 Canvas canvas = new Canvas(result); 396 Paint paint = new Paint(); 397 paint.setFlags(0); 398 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 399 Shader.TileMode.CLAMP); 400 paint.setShader(shader); 401 canvas.drawPaint(paint); 402 assertTestImageResult(result); 403 } 404 405 @RequiresFlagsEnabled(Flags.FLAG_ISO_GAINMAP_APIS) 406 @Test 407 public void bitmapShaderSupportHLGGainmaps() { 408 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020); 409 Canvas canvas = new Canvas(result); 410 Paint paint = new Paint(); 411 paint.setFlags(0); 412 BitmapShader shader = new BitmapShader(sHLGTestImage, Shader.TileMode.CLAMP, 413 Shader.TileMode.CLAMP); 414 paint.setShader(shader); 415 canvas.drawPaint(paint); 416 assertFullyAppliedHLGTestImageResult(result); 417 } 418 419 @Test 420 public void bitmapShaderSupportHLGHardware() { 421 Bitmap result = renderWithHardware(BT2020_HLG, canvas -> { 422 Paint paint = new Paint(); 423 paint.setFlags(0); 424 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 425 Shader.TileMode.CLAMP); 426 paint.setShader(shader); 427 canvas.drawPaint(paint); 428 }); 429 assertTestImageResult(result); 430 } 431 432 @Test 433 public void bitmapShaderSupportSrgbHardware() { 434 Bitmap result = renderWithHardware(SRGB, canvas -> { 435 Paint paint = new Paint(); 436 paint.setFlags(0); 437 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 438 Shader.TileMode.CLAMP); 439 paint.setShader(shader); 440 canvas.drawPaint(paint); 441 }); 442 assertTestImageResult(result, sNoOpGainmap); 443 } 444 445 @RequiresFlagsEnabled(Flags.FLAG_ISO_GAINMAP_APIS) 446 @Test 447 public void bitmapShaderSupportHLGGainmapsHardware() { 448 Bitmap result = renderWithHardware(BT2020, canvas -> { 449 Paint paint = new Paint(); 450 paint.setFlags(0); 451 BitmapShader shader = new BitmapShader(sHLGTestImage, Shader.TileMode.CLAMP, 452 Shader.TileMode.CLAMP); 453 paint.setShader(shader); 454 canvas.drawPaint(paint); 455 }); 456 assertFullyAppliedHLGTestImageResult(result); 457 } 458 459 460 @RequiresFlagsEnabled(Flags.FLAG_GAINMAP_ANIMATIONS) 461 @Test 462 public void bitmapShaderOverrideGainmapToNoOpHLG() { 463 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 464 Canvas canvas = new Canvas(result); 465 Paint paint = new Paint(); 466 paint.setFlags(0); 467 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 468 Shader.TileMode.CLAMP); 469 shader.setOverrideGainmap(sNoOpGainmap); 470 paint.setShader(shader); 471 canvas.drawPaint(paint); 472 BitmapAsserter.assertBitmapIsVerified(result, new ColorVerifier(Color.WHITE, 3), 473 ""); 474 } 475 476 @RequiresFlagsEnabled(Flags.FLAG_GAINMAP_ANIMATIONS) 477 @Test 478 public void bitmapShaderOverrideGainmapTo4xHLG() { 479 Gainmap override = new Gainmap(sTestImage.getGainmap().getGainmapContents()); 480 override.setRatioMax(4.0f, 4.0f, 4.0f); 481 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 482 Canvas canvas = new Canvas(result); 483 Paint paint = new Paint(); 484 paint.setFlags(0); 485 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 486 Shader.TileMode.CLAMP); 487 shader.setOverrideGainmap(override); 488 paint.setShader(shader); 489 canvas.drawPaint(paint); 490 assertTestImageResult(result, override); 491 } 492 493 @RequiresFlagsEnabled(Flags.FLAG_GAINMAP_ANIMATIONS) 494 @Test 495 public void bitmapShaderOverrideGainmapModifyAfterSetHLG() { 496 Gainmap override = new Gainmap(sTestImage.getGainmap().getGainmapContents()); 497 override.setRatioMax(4.0f, 4.0f, 4.0f); 498 Gainmap initialOverride = new Gainmap(override, override.getGainmapContents()); 499 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 500 Canvas canvas = new Canvas(result); 501 Paint paint = new Paint(); 502 paint.setFlags(0); 503 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 504 Shader.TileMode.CLAMP); 505 shader.setOverrideGainmap(override); 506 override.setRatioMax(1f, 1f, 1f); 507 paint.setShader(shader); 508 canvas.drawPaint(paint); 509 assertTestImageResult(result, initialOverride); 510 } 511 512 @RequiresFlagsEnabled(Flags.FLAG_GAINMAP_ANIMATIONS) 513 @Test 514 public void bitmapShaderOverrideGainmapPaintObservesUpdatesHLG() { 515 Gainmap override = new Gainmap(sTestImage.getGainmap().getGainmapContents()); 516 Bitmap result = Bitmap.createBitmap(10, 6, Bitmap.Config.RGBA_F16, false, BT2020_HLG); 517 Canvas canvas = new Canvas(result); 518 Paint paint = new Paint(); 519 paint.setFlags(0); 520 BitmapShader shader = new BitmapShader(sTestImage, Shader.TileMode.CLAMP, 521 Shader.TileMode.CLAMP); 522 shader.setOverrideGainmap(override); 523 paint.setShader(shader); 524 canvas.drawPaint(paint); 525 override.setRatioMax(1, 1, 1); 526 shader.setOverrideGainmap(override); 527 canvas.drawPaint(paint); 528 BitmapAsserter.assertBitmapIsVerified(result, new ColorVerifier(Color.WHITE, 3), 529 ""); 530 } 531 532 @Test 533 public void createScaledBitmap() { 534 Bitmap result = Bitmap.createScaledBitmap(sTestImage, 20, 12, false); 535 assertEquals(result.getWidth(), 20); 536 assertEquals(result.getHeight(), 12); 537 assertTrue(result.hasGainmap()); 538 Bitmap gainmapContents = result.getGainmap().getGainmapContents(); 539 assertEquals(gainmapContents.getWidth(), 10); 540 assertEquals(gainmapContents.getHeight(), 6); 541 542 assertChannels(gainmapContents.getColor(0, 0), Color.pack(Color.BLACK), 0f); 543 assertChannels(gainmapContents.getColor(1, 1), Color.pack(Color.BLACK), 0f); 544 545 assertChannels(gainmapContents.getColor(2, 2), Color.pack(0xFF404040), 0f); 546 assertChannels(gainmapContents.getColor(3, 3), Color.pack(0xFF404040), 0f); 547 548 assertChannels(gainmapContents.getColor(4, 2), Color.pack(0xFF808080), 0f); 549 assertChannels(gainmapContents.getColor(5, 3), Color.pack(0xFF808080), 0f); 550 551 assertChannels(gainmapContents.getColor(6, 2), Color.pack(0xFFFFFFFF), 0f); 552 assertChannels(gainmapContents.getColor(7, 3), Color.pack(0xFFFFFFFF), 0f); 553 554 assertChannels(gainmapContents.getColor(8, 4), Color.pack(Color.BLACK), 0f); 555 assertChannels(gainmapContents.getColor(9, 5), Color.pack(Color.BLACK), 0f); 556 } 557 558 @Test 559 public void applyRotation180Matrix() { 560 Matrix m = new Matrix(); 561 m.setRotate(180.0f, 5.f, 3.f); 562 Bitmap result = Bitmap.createBitmap(sTestImage, 0, 0, 10, 6, m, false); 563 assertEquals(result.getWidth(), 10); 564 assertEquals(result.getHeight(), 6); 565 assertTrue(result.hasGainmap()); 566 Bitmap gainmapContents = result.getGainmap().getGainmapContents(); 567 assertEquals(gainmapContents.getWidth(), 5); 568 assertEquals(gainmapContents.getHeight(), 3); 569 assertChannels(gainmapContents.getColor(0, 0), Color.pack(Color.BLACK), 0f); 570 assertChannels(gainmapContents.getColor(0, 1), Color.pack(Color.BLACK), 0f); 571 assertChannels(gainmapContents.getColor(1, 1), Color.pack(0xFFFFFFFF), 0f); 572 assertChannels(gainmapContents.getColor(2, 1), Color.pack(0xFF808080), 0f); 573 assertChannels(gainmapContents.getColor(3, 1), Color.pack(0xFF404040), 0f); 574 assertChannels(gainmapContents.getColor(4, 1), Color.pack(Color.BLACK), 0f); 575 assertChannels(gainmapContents.getColor(4, 2), Color.pack(Color.BLACK), 0f); 576 } 577 578 @Test 579 public void applyRotation90Matrix() { 580 Matrix m = new Matrix(); 581 m.setRotate(90.0f, 5.f, 3.f); 582 Bitmap result = Bitmap.createBitmap(sTestImage, 0, 0, 10, 6, m, false); 583 assertEquals(result.getWidth(), 6); 584 assertEquals(result.getHeight(), 10); 585 assertTrue(result.hasGainmap()); 586 Bitmap gainmapContents = result.getGainmap().getGainmapContents(); 587 assertEquals(gainmapContents.getWidth(), 3); 588 assertEquals(gainmapContents.getHeight(), 5); 589 assertChannels(gainmapContents.getColor(0, 0), Color.pack(Color.BLACK), 0f); 590 assertChannels(gainmapContents.getColor(1, 0), Color.pack(Color.BLACK), 0f); 591 assertChannels(gainmapContents.getColor(1, 1), Color.pack(0xFF404040), 0f); 592 assertChannels(gainmapContents.getColor(1, 2), Color.pack(0xFF808080), 0f); 593 assertChannels(gainmapContents.getColor(1, 3), Color.pack(0xFFFFFFFF), 0f); 594 assertChannels(gainmapContents.getColor(1, 4), Color.pack(Color.BLACK), 0f); 595 assertChannels(gainmapContents.getColor(2, 4), Color.pack(Color.BLACK), 0f); 596 } 597 598 @Test 599 public void testRenderingDropsGainmap() { 600 Bitmap dest = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); 601 Gainmap gainmap = new Gainmap(Bitmap.createBitmap(5, 5, Bitmap.Config.ALPHA_8)); 602 dest.setGainmap(gainmap); 603 assertTrue(dest.hasGainmap()); 604 Canvas canvas = new Canvas(dest); 605 assertFalse(dest.hasGainmap()); 606 canvas.setBitmap(null); 607 dest.setGainmap(gainmap); 608 assertTrue(dest.hasGainmap()); 609 canvas.setBitmap(dest); 610 assertFalse(dest.hasGainmap()); 611 } 612 613 @Test 614 public void testHardwareHandlingHLG() { 615 Bitmap testImage = sTestImage.copy(Bitmap.Config.HARDWARE, false); 616 assertTrue(testImage.hasGainmap()); 617 assertEquals(testImage.getGainmap().getGainmapContents().getConfig(), 618 Bitmap.Config.HARDWARE); 619 Bitmap result = renderWithHardware(BT2020_HLG, canvas -> { 620 canvas.drawBitmap(testImage, 0, 0, null); 621 }); 622 assertTestImageResult(result); 623 } 624 625 @Test 626 public void testHardwareHandlingPQ() { 627 Bitmap testImage = sTestImage.copy(Bitmap.Config.HARDWARE, false); 628 assertTrue(testImage.hasGainmap()); 629 assertEquals(testImage.getGainmap().getGainmapContents().getConfig(), 630 Bitmap.Config.HARDWARE); 631 Bitmap result = renderWithHardware(BT2020_PQ, canvas -> { 632 canvas.drawBitmap(testImage, 0, 0, null); 633 }); 634 assertTestImageResult(result); 635 } 636 637 @Test 638 public void testHardwareA8HandlingHLG() { 639 Bitmap testImage = sTestImageA8.copy(Bitmap.Config.HARDWARE, false); 640 assertTrue(testImage.hasGainmap()); 641 assertEquals(testImage.getGainmap().getGainmapContents().getConfig(), 642 Bitmap.Config.HARDWARE); 643 Bitmap result = renderWithHardware(BT2020_HLG, canvas -> { 644 canvas.drawBitmap(testImage, 0, 0, null); 645 }); 646 assertTestImageResult(result); 647 } 648 649 @Test 650 public void testHardwareA8HandlingPQ() { 651 Bitmap testImage = sTestImageA8.copy(Bitmap.Config.HARDWARE, false); 652 assertTrue(testImage.hasGainmap()); 653 assertEquals(testImage.getGainmap().getGainmapContents().getConfig(), 654 Bitmap.Config.HARDWARE); 655 Bitmap result = renderWithHardware(BT2020_PQ, canvas -> { 656 canvas.drawBitmap(testImage, 0, 0, null); 657 }); 658 assertTestImageResult(result); 659 } 660 } 661