1 /* 2 * Copyright (C) 2017 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.graphics.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotEquals; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertSame; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 27 import android.content.res.Resources; 28 import android.graphics.Bitmap; 29 import android.graphics.BitmapFactory; 30 import android.graphics.ColorSpace; 31 import android.os.Parcel; 32 import android.support.annotation.ColorInt; 33 import android.support.annotation.NonNull; 34 import android.support.test.InstrumentationRegistry; 35 import android.support.test.filters.SmallTest; 36 import android.support.test.runner.AndroidJUnit4; 37 import android.util.Log; 38 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.io.IOException; 44 import java.io.InputStream; 45 import java.nio.ByteBuffer; 46 import java.nio.IntBuffer; 47 import java.util.Arrays; 48 49 @SmallTest 50 @RunWith(AndroidJUnit4.class) 51 public class BitmapColorSpaceTest { 52 private static final String LOG_TAG = "BitmapColorSpaceTest"; 53 54 private Resources mResources; 55 56 @Before setup()57 public void setup() { 58 mResources = InstrumentationRegistry.getTargetContext().getResources(); 59 } 60 61 @SuppressWarnings("deprecation") 62 @Test createWithColorSpace()63 public void createWithColorSpace() { 64 Bitmap b; 65 ColorSpace cs; 66 ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB); 67 68 // We don't test HARDWARE configs because they are not compatible with mutable bitmaps 69 70 b = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, sRGB); 71 cs = b.getColorSpace(); 72 assertNotNull(cs); 73 assertSame(sRGB, cs); 74 75 b = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, 76 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); 77 cs = b.getColorSpace(); 78 assertNotNull(cs); 79 assertSame(ColorSpace.get(ColorSpace.Named.ADOBE_RGB), cs); 80 81 b = Bitmap.createBitmap(32, 32, Bitmap.Config.RGBA_F16, true, sRGB); 82 cs = b.getColorSpace(); 83 assertNotNull(cs); 84 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 85 86 b = Bitmap.createBitmap(32, 32, Bitmap.Config.RGBA_F16, true, 87 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); 88 cs = b.getColorSpace(); 89 assertNotNull(cs); 90 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 91 92 b = Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565, true, sRGB); 93 cs = b.getColorSpace(); 94 assertNotNull(cs); 95 assertSame(sRGB, cs); 96 97 b = Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565, true, 98 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); 99 cs = b.getColorSpace(); 100 assertNotNull(cs); 101 assertSame(sRGB, cs); 102 103 b = Bitmap.createBitmap(32, 32, Bitmap.Config.ALPHA_8, true, sRGB); 104 cs = b.getColorSpace(); 105 assertNotNull(cs); 106 assertSame(sRGB, cs); 107 108 b = Bitmap.createBitmap(32, 32, Bitmap.Config.ALPHA_8, true, 109 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); 110 cs = b.getColorSpace(); 111 assertNotNull(cs); 112 assertSame(sRGB, cs); 113 114 b = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_4444, true, sRGB); 115 cs = b.getColorSpace(); 116 assertNotNull(cs); 117 assertSame(sRGB, cs); 118 119 b = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_4444, true, 120 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); 121 cs = b.getColorSpace(); 122 assertNotNull(cs); 123 assertSame(sRGB, cs); 124 } 125 126 @Test createDefaultColorSpace()127 public void createDefaultColorSpace() { 128 ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB); 129 Bitmap.Config[] configs = new Bitmap.Config[] { 130 Bitmap.Config.ALPHA_8, Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 131 }; 132 for (Bitmap.Config config : configs) { 133 Bitmap bitmap = Bitmap.createBitmap(32, 32, config, true); 134 assertSame(sRGB, bitmap.getColorSpace()); 135 } 136 } 137 138 @Test(expected = IllegalArgumentException.class) createWithoutColorSpace()139 public void createWithoutColorSpace() { 140 Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, null); 141 } 142 143 @Test(expected = IllegalArgumentException.class) createWithNonRgbColorSpace()144 public void createWithNonRgbColorSpace() { 145 Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, 146 ColorSpace.get(ColorSpace.Named.CIE_LAB)); 147 } 148 149 @Test sRGB()150 public void sRGB() { 151 Bitmap b = BitmapFactory.decodeResource(mResources, R.drawable.robot); 152 ColorSpace cs = b.getColorSpace(); 153 assertNotNull(cs); 154 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 155 156 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 157 cs = b.getColorSpace(); 158 assertNotNull(cs); 159 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 160 161 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 162 cs = b.getColorSpace(); 163 assertNotNull(cs); 164 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 165 } 166 167 @Test p3()168 public void p3() { 169 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 170 Bitmap b = BitmapFactory.decodeStream(in); 171 ColorSpace cs = b.getColorSpace(); 172 assertNotNull(cs); 173 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 174 175 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 176 cs = b.getColorSpace(); 177 assertNotNull(cs); 178 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 179 180 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 181 cs = b.getColorSpace(); 182 assertNotNull(cs); 183 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 184 } catch (IOException e) { 185 fail(); 186 } 187 } 188 189 @Test extendedSRGB()190 public void extendedSRGB() { 191 try (InputStream in = mResources.getAssets().open("prophoto-rgba16f.png")) { 192 Bitmap b = BitmapFactory.decodeStream(in); 193 ColorSpace cs = b.getColorSpace(); 194 assertNotNull(cs); 195 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 196 197 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 198 cs = b.getColorSpace(); 199 assertNotNull(cs); 200 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 201 202 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 203 cs = b.getColorSpace(); 204 assertNotNull(cs); 205 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 206 } catch (IOException e) { 207 fail(); 208 } 209 } 210 211 @Test reconfigure()212 public void reconfigure() { 213 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 214 BitmapFactory.Options opts = new BitmapFactory.Options(); 215 opts.inMutable = true; 216 217 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 218 ColorSpace cs = b.getColorSpace(); 219 assertNotNull(cs); 220 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 221 222 b.reconfigure(b.getWidth() / 2, b.getHeight() / 2, Bitmap.Config.RGBA_F16); 223 cs = b.getColorSpace(); 224 assertNotNull(cs); 225 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 226 227 b.reconfigure(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888); 228 cs = b.getColorSpace(); 229 assertNotNull(cs); 230 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 231 } catch (IOException e) { 232 fail(); 233 } 234 } 235 236 @Test reuse()237 public void reuse() { 238 BitmapFactory.Options opts = new BitmapFactory.Options(); 239 opts.inMutable = true; 240 241 Bitmap bitmap1 = null; 242 try (InputStream in = mResources.getAssets().open("green-srgb.png")) { 243 bitmap1 = BitmapFactory.decodeStream(in, null, opts); 244 ColorSpace cs = bitmap1.getColorSpace(); 245 assertNotNull(cs); 246 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 247 } catch (IOException e) { 248 fail(); 249 } 250 251 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 252 opts.inBitmap = bitmap1; 253 254 Bitmap bitmap2 = BitmapFactory.decodeStream(in, null, opts); 255 assertSame(bitmap1, bitmap2); 256 ColorSpace cs = bitmap2.getColorSpace(); 257 assertNotNull(cs); 258 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 259 } catch (IOException e) { 260 fail(); 261 } 262 } 263 264 @Test getPixel()265 public void getPixel() { 266 verifyGetPixel("green-p3.png", 0x75fb4cff, 0xff00ff00); 267 verifyGetPixel("translucent-green-p3.png", 0x3a7d267f, 0x7f00ff00); // 50% translucent 268 } 269 verifyGetPixel(@onNull String fileName, @ColorInt int rawColor, @ColorInt int srgbColor)270 private void verifyGetPixel(@NonNull String fileName, 271 @ColorInt int rawColor, @ColorInt int srgbColor) { 272 try (InputStream in = mResources.getAssets().open(fileName)) { 273 Bitmap b = BitmapFactory.decodeStream(in); 274 ColorSpace cs = b.getColorSpace(); 275 assertNotNull(cs); 276 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 277 278 verifyGetPixel(b, rawColor, srgbColor); 279 280 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 281 verifyGetPixel(b, rawColor, srgbColor); 282 283 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 284 verifyGetPixel(b, rawColor, srgbColor); 285 } catch (IOException e) { 286 fail(); 287 } 288 } 289 verifyGetPixel(@onNull Bitmap b, @ColorInt int rawColor, @ColorInt int srgbColor)290 private static void verifyGetPixel(@NonNull Bitmap b, 291 @ColorInt int rawColor, @ColorInt int srgbColor) { 292 ByteBuffer dst = ByteBuffer.allocate(b.getByteCount()); 293 b.copyPixelsToBuffer(dst); 294 dst.rewind(); 295 296 // Stored as RGBA 297 assertEquals(rawColor, dst.asIntBuffer().get()); 298 299 int srgb = b.getPixel(15, 15); 300 almostEqual(srgbColor, srgb, 3, 15 * b.getWidth() + 15); 301 } 302 303 @Test getPixels()304 public void getPixels() { 305 verifyGetPixels("green-p3.png", 0xff00ff00); 306 verifyGetPixels("translucent-green-p3.png", 0x7f00ff00); // 50% translucent 307 } 308 verifyGetPixels(@onNull String fileName, @ColorInt int expected)309 private void verifyGetPixels(@NonNull String fileName, @ColorInt int expected) { 310 try (InputStream in = mResources.getAssets().open(fileName)) { 311 Bitmap b = BitmapFactory.decodeStream(in); 312 ColorSpace cs = b.getColorSpace(); 313 assertNotNull(cs); 314 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 315 316 verifyGetPixels(b, expected); 317 318 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 319 verifyGetPixels(b, expected); 320 321 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 322 verifyGetPixels(b, expected); 323 } catch (IOException e) { 324 fail(); 325 } 326 } 327 verifyGetPixels(@onNull Bitmap b, @ColorInt int expected)328 private static void verifyGetPixels(@NonNull Bitmap b, @ColorInt int expected) { 329 int[] pixels = new int[b.getWidth() * b.getHeight()]; 330 b.getPixels(pixels, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight()); 331 332 for (int i = 0; i < pixels.length; i++) { 333 int pixel = pixels[i]; 334 almostEqual(expected, pixel, 3, i); 335 } 336 } 337 338 @Test setPixel()339 public void setPixel() { 340 verifySetPixel("green-p3.png", 0xffff0000, 0xea3323ff); 341 verifySetPixel("translucent-green-p3.png", 0x7fff0000, 0x7519117f); 342 } 343 verifySetPixel(@onNull String fileName, @ColorInt int newColor, @ColorInt int expectedColor)344 private void verifySetPixel(@NonNull String fileName, 345 @ColorInt int newColor, @ColorInt int expectedColor) { 346 try (InputStream in = mResources.getAssets().open(fileName)) { 347 BitmapFactory.Options opts = new BitmapFactory.Options(); 348 opts.inMutable = true; 349 350 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 351 ColorSpace cs = b.getColorSpace(); 352 assertNotNull(cs); 353 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 354 355 verifySetPixel(b, newColor, expectedColor); 356 357 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 358 verifySetPixel(b, newColor, expectedColor); 359 360 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 361 verifySetPixel(b, newColor, expectedColor); 362 } catch (IOException e) { 363 fail(); 364 } 365 } 366 verifySetPixel(@onNull Bitmap b, @ColorInt int newColor, @ColorInt int expectedColor)367 private static void verifySetPixel(@NonNull Bitmap b, 368 @ColorInt int newColor, @ColorInt int expectedColor) { 369 b.setPixel(0, 0, newColor); 370 371 ByteBuffer dst = ByteBuffer.allocate(b.getByteCount()); 372 b.copyPixelsToBuffer(dst); 373 dst.rewind(); 374 // Stored as RGBA 375 assertEquals(expectedColor, dst.asIntBuffer().get()); 376 } 377 378 @Test setPixels()379 public void setPixels() { 380 verifySetPixels("green-p3.png", 0xffff0000, 0xea3323ff); 381 verifySetPixels("translucent-green-p3.png", 0x7fff0000, 0x7519117f); 382 } 383 verifySetPixels(@onNull String fileName, @ColorInt int newColor, @ColorInt int expectedColor)384 private void verifySetPixels(@NonNull String fileName, 385 @ColorInt int newColor, @ColorInt int expectedColor) { 386 try (InputStream in = mResources.getAssets().open(fileName)) { 387 BitmapFactory.Options opts = new BitmapFactory.Options(); 388 opts.inMutable = true; 389 390 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 391 ColorSpace cs = b.getColorSpace(); 392 assertNotNull(cs); 393 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 394 395 verifySetPixels(b, newColor, expectedColor); 396 397 b = Bitmap.createBitmap(b, 0, 0, b.getWidth() / 2, b.getHeight() / 2); 398 verifySetPixels(b, newColor, expectedColor); 399 400 b = Bitmap.createScaledBitmap(b, b.getWidth() / 2, b.getHeight() / 2, true); 401 verifySetPixels(b, newColor, expectedColor); 402 } catch (IOException e) { 403 fail(); 404 } 405 } 406 verifySetPixels(@onNull Bitmap b, @ColorInt int newColor, @ColorInt int expectedColor)407 private static void verifySetPixels(@NonNull Bitmap b, 408 @ColorInt int newColor, @ColorInt int expectedColor) { 409 int[] pixels = new int[b.getWidth() * b.getHeight()]; 410 Arrays.fill(pixels, newColor); 411 b.setPixels(pixels, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight()); 412 413 ByteBuffer dst = ByteBuffer.allocate(b.getByteCount()); 414 b.copyPixelsToBuffer(dst); 415 dst.rewind(); 416 417 IntBuffer buffer = dst.asIntBuffer(); 418 //noinspection ForLoopReplaceableByForEach 419 for (int i = 0; i < pixels.length; i++) { 420 // Stored as RGBA 421 assertEquals(expectedColor, buffer.get()); 422 } 423 } 424 425 @Test writeColorSpace()426 public void writeColorSpace() { 427 verifyColorSpaceMarshalling("green-srgb.png", ColorSpace.get(ColorSpace.Named.SRGB)); 428 verifyColorSpaceMarshalling("green-p3.png", ColorSpace.get(ColorSpace.Named.DISPLAY_P3)); 429 verifyColorSpaceMarshalling("prophoto-rgba16f.png", 430 ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB)); 431 432 // Special case where the color space will be null in native 433 Bitmap bitmapIn = BitmapFactory.decodeResource(mResources, R.drawable.robot); 434 verifyParcelUnparcel(bitmapIn, ColorSpace.get(ColorSpace.Named.SRGB)); 435 } 436 verifyColorSpaceMarshalling( @onNull String fileName, @NonNull ColorSpace colorSpace)437 private void verifyColorSpaceMarshalling( 438 @NonNull String fileName, @NonNull ColorSpace colorSpace) { 439 try (InputStream in = mResources.getAssets().open(fileName)) { 440 Bitmap bitmapIn = BitmapFactory.decodeStream(in); 441 verifyParcelUnparcel(bitmapIn, colorSpace); 442 } catch (IOException e) { 443 fail(); 444 } 445 } 446 verifyParcelUnparcel(Bitmap bitmapIn, ColorSpace expected)447 private void verifyParcelUnparcel(Bitmap bitmapIn, ColorSpace expected) { 448 ColorSpace cs = bitmapIn.getColorSpace(); 449 assertNotNull(cs); 450 assertSame(expected, cs); 451 452 Parcel p = Parcel.obtain(); 453 bitmapIn.writeToParcel(p, 0); 454 p.setDataPosition(0); 455 456 Bitmap bitmapOut = Bitmap.CREATOR.createFromParcel(p); 457 cs = bitmapOut.getColorSpace(); 458 assertNotNull(cs); 459 assertSame(expected, cs); 460 461 p.recycle(); 462 } 463 464 @Test p3rgb565()465 public void p3rgb565() { 466 BitmapFactory.Options opts = new BitmapFactory.Options(); 467 opts.inPreferredConfig = Bitmap.Config.RGB_565; 468 469 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 470 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 471 ColorSpace cs = b.getColorSpace(); 472 assertNotNull(cs); 473 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 474 } catch (IOException e) { 475 fail(); 476 } 477 } 478 479 @Test p3hardware()480 public void p3hardware() { 481 BitmapFactory.Options opts = new BitmapFactory.Options(); 482 opts.inPreferredConfig = Bitmap.Config.HARDWARE; 483 484 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 485 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 486 ColorSpace cs = b.getColorSpace(); 487 assertNotNull(cs); 488 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 489 } catch (IOException e) { 490 fail(); 491 } 492 } 493 494 @Test guessSRGB()495 public void guessSRGB() { 496 BitmapFactory.Options opts = new BitmapFactory.Options(); 497 opts.inJustDecodeBounds = true; 498 499 try (InputStream in = mResources.getAssets().open("green-srgb.png")) { 500 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 501 ColorSpace cs = opts.outColorSpace; 502 assertNull(b); 503 assertNotNull(cs); 504 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 505 } catch (IOException e) { 506 fail(); 507 } 508 } 509 510 @Test guessProPhotoRGB()511 public void guessProPhotoRGB() { 512 BitmapFactory.Options opts = new BitmapFactory.Options(); 513 opts.inJustDecodeBounds = true; 514 515 try (InputStream in = mResources.getAssets().open("prophoto-rgba16f.png")) { 516 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 517 ColorSpace cs = opts.outColorSpace; 518 assertNull(b); 519 assertNotNull(cs); 520 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 521 } catch (IOException e) { 522 fail(); 523 } 524 } 525 526 @Test guessP3()527 public void guessP3() { 528 BitmapFactory.Options opts = new BitmapFactory.Options(); 529 opts.inJustDecodeBounds = true; 530 531 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 532 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 533 ColorSpace cs = opts.outColorSpace; 534 assertNull(b); 535 assertNotNull(cs); 536 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 537 } catch (IOException e) { 538 fail(); 539 } 540 } 541 542 @Test guessAdobeRGB()543 public void guessAdobeRGB() { 544 BitmapFactory.Options opts = new BitmapFactory.Options(); 545 opts.inJustDecodeBounds = true; 546 547 try (InputStream in = mResources.getAssets().open("red-adobergb.png")) { 548 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 549 ColorSpace cs = opts.outColorSpace; 550 assertNull(b); 551 assertNotNull(cs); 552 assertSame(ColorSpace.get(ColorSpace.Named.ADOBE_RGB), cs); 553 } catch (IOException e) { 554 fail(); 555 } 556 } 557 558 @Test guessUnknown()559 public void guessUnknown() { 560 BitmapFactory.Options opts = new BitmapFactory.Options(); 561 opts.inJustDecodeBounds = true; 562 563 try (InputStream in = mResources.getAssets().open("purple-displayprofile.png")) { 564 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 565 ColorSpace cs = opts.outColorSpace; 566 assertNull(b); 567 assertNotNull(cs); 568 assertEquals("Unknown", cs.getName()); 569 } catch (IOException e) { 570 fail(); 571 } 572 } 573 574 @Test guessCMYK()575 public void guessCMYK() { 576 BitmapFactory.Options opts = new BitmapFactory.Options(); 577 opts.inJustDecodeBounds = true; 578 579 try (InputStream in = mResources.getAssets().open("purple-cmyk.png")) { 580 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 581 ColorSpace cs = opts.outColorSpace; 582 assertNull(b); 583 assertNotNull(cs); 584 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 585 } catch (IOException e) { 586 fail(); 587 } 588 } 589 590 @Test inColorSpaceP3ToSRGB()591 public void inColorSpaceP3ToSRGB() { 592 BitmapFactory.Options opts = new BitmapFactory.Options(); 593 opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); 594 595 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 596 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 597 ColorSpace cs = b.getColorSpace(); 598 assertNotNull(cs); 599 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 600 assertEquals(opts.inPreferredColorSpace, opts.outColorSpace); 601 602 verifyGetPixel(b, 0x3ff00ff, 0xff00ff00); 603 } catch (IOException e) { 604 fail(); 605 } 606 } 607 608 @Test inColorSpaceSRGBToP3()609 public void inColorSpaceSRGBToP3() { 610 BitmapFactory.Options opts = new BitmapFactory.Options(); 611 opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3); 612 613 try (InputStream in = mResources.getAssets().open("green-srgb.png")) { 614 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 615 ColorSpace cs = b.getColorSpace(); 616 assertNotNull(cs); 617 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 618 assertEquals(opts.inPreferredColorSpace, opts.outColorSpace); 619 620 verifyGetPixel(b, 0x75fb4cff, 0xff00ff00); 621 } catch (IOException e) { 622 fail(); 623 } 624 } 625 626 @Test inColorSpaceRGBA16F()627 public void inColorSpaceRGBA16F() { 628 BitmapFactory.Options opts = new BitmapFactory.Options(); 629 opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB); 630 631 try (InputStream in = mResources.getAssets().open("prophoto-rgba16f.png")) { 632 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 633 ColorSpace cs = b.getColorSpace(); 634 assertNotNull(cs); 635 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 636 assertNotEquals(opts.inPreferredColorSpace, opts.outColorSpace); 637 } catch (IOException e) { 638 fail(); 639 } 640 } 641 642 @Test inColorSpace565()643 public void inColorSpace565() { 644 BitmapFactory.Options opts = new BitmapFactory.Options(); 645 opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB); 646 opts.inPreferredConfig = Bitmap.Config.RGB_565; 647 648 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 649 Bitmap b = BitmapFactory.decodeStream(in, null, opts); 650 ColorSpace cs = b.getColorSpace(); 651 assertNotNull(cs); 652 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 653 assertNotEquals(opts.inPreferredColorSpace, opts.outColorSpace); 654 } catch (IOException e) { 655 fail(); 656 } 657 } 658 659 @Test(expected = IllegalArgumentException.class) inColorSpaceNotRGB()660 public void inColorSpaceNotRGB() { 661 BitmapFactory.Options opts = new BitmapFactory.Options(); 662 opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.CIE_LAB); 663 664 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 665 BitmapFactory.decodeStream(in, null, opts); 666 } catch (IOException e) { 667 fail(); 668 } 669 } 670 671 @Test(expected = IllegalArgumentException.class) inColorSpaceNoTransferParameters()672 public void inColorSpaceNoTransferParameters() { 673 BitmapFactory.Options opts = new BitmapFactory.Options(); 674 opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB); 675 676 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 677 BitmapFactory.decodeStream(in, null, opts); 678 } catch (IOException e) { 679 fail(); 680 } 681 } 682 683 @Test copy()684 public void copy() { 685 Bitmap b = BitmapFactory.decodeResource(mResources, R.drawable.robot); 686 Bitmap c = b.copy(Bitmap.Config.ARGB_8888, false); 687 ColorSpace cs = c.getColorSpace(); 688 assertNotNull(cs); 689 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 690 691 c = b.copy(Bitmap.Config.ARGB_8888, true); 692 cs = c.getColorSpace(); 693 assertNotNull(cs); 694 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs); 695 696 try (InputStream in = mResources.getAssets().open("green-p3.png")) { 697 b = BitmapFactory.decodeStream(in); 698 c = b.copy(Bitmap.Config.ARGB_8888, false); 699 cs = c.getColorSpace(); 700 assertNotNull(cs); 701 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 702 703 c = b.copy(Bitmap.Config.ARGB_8888, true); 704 cs = c.getColorSpace(); 705 assertNotNull(cs); 706 assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs); 707 } catch (IOException e) { 708 fail(); 709 } 710 711 try (InputStream in = mResources.getAssets().open("prophoto-rgba16f.png")) { 712 b = BitmapFactory.decodeStream(in); 713 c = b.copy(Bitmap.Config.RGBA_F16, false); 714 cs = c.getColorSpace(); 715 assertNotNull(cs); 716 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 717 718 c = b.copy(Bitmap.Config.RGBA_F16, true); 719 cs = c.getColorSpace(); 720 assertNotNull(cs); 721 assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs); 722 } catch (IOException e) { 723 fail(); 724 } 725 } 726 727 @SuppressWarnings("SameParameterValue") almostEqual(@olorInt int expected, @ColorInt int pixel, int threshold, int index)728 private static void almostEqual(@ColorInt int expected, 729 @ColorInt int pixel, int threshold, int index) { 730 int diffA = Math.abs(expected >>> 24 - pixel >>> 24); 731 int diffR = Math.abs((expected >> 16) & 0xff - (pixel >> 16) & 0xff); 732 int diffG = Math.abs((expected >> 8) & 0xff - (pixel >> 8) & 0xff); 733 int diffB = Math.abs((expected ) & 0xff - (pixel ) & 0xff); 734 735 boolean pass = diffA + diffR + diffG + diffB < threshold; 736 if (!pass) { 737 Log.d(LOG_TAG, "Expected 0x" + Integer.toHexString(expected) + 738 " but was 0x" + Integer.toHexString(pixel) + " with index " + index); 739 } 740 741 assertTrue(pass); 742 } 743 } 744