Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Understanding Color

Understanding Color

Why doesn't your application look the same across multiple devices? Why does your designer's mock look different on your computer? After learning what color really is, you will understand how to setup your design environment and how to use new APIs in Android O to manage colors properly and take advantage of wide color gamut displays.

237be48129b762b31847d6167597366d?s=128

Romain Guy

May 18, 2017
Tweet

Transcript

  1. UNDERSTANDING COLOR @romainguy

  2. UNDERSTANDING COLOR @romainguy

  3. What is color?

  4. A visual perception that can be described by hue, brightness

    and colorfulness
  5. None
  6. ⚛ ☢ ☀ ♨ 10-16 108 wavelength (m)

  7. ⚛ ☢ ☀ ♨ 10-16 108 wavelength (m) 380 700

    nanometers
  8. 0 1 Short Medium Long

  9. 0 1

  10. ×

  11. 0 1

  12. ☀ ×

  13. × ☀ ×

  14. × ☀ ×

  15. None
  16. What is color?

  17. For developers, a tuple of numbers in a color model

    with a color space
  18. RGB CMYK L*a*b*

  19. RGB

  20. #ff436d

  21. 255,67,109

  22. 1.0,0.26,0.43

  23. None
  24. None
  25. COLOR SPACE?

  26. None
  27. 3 primaries

  28. 3 primaries white point

  29. transfer functions 3 primaries white point

  30. sRGB AdobeRGB ProPhotoRGB

  31. Transfer functions?

  32. None
  33. sRGB P3 Adobe RGB sRGB

  34. None
  35. None
  36. None
  37. None
  38. None
  39. What you saw is how Android handles color spaces Colors

    are unmanaged
  40. Source COLOR MANAGEMENT

  41. Source Destination COLOR MANAGEMENT

  42. New in O! Source Destination COLOR MANAGEMENT

  43. Assign Convert

  44. When in doubt… sRGB!

  45. None
  46. None
  47. None
  48. None
  49. // ARGB in sRGB @ColorInt int c = 0xfff436d;

  50. None
  51. // Color instance in sRGB
 Color c = Color.valueOf(1.0f, 0.26f,

    0.43f);
  52. // Color instance in sRGB
 Color c = Color.valueOf(1.0f, 0.26f,

    0.43f);
  53. // Color instance in sRGB
 Color c = Color.valueOf(1.0f, 0.26f,

    0.43f); // Color instance in Adobe RGB
 Color c = Color.valueOf(1.0f, 0.26f, 0.43f, 1.0f,
 ColorSpace.get(ColorSpace.Named.ADOBE_RGB));
  54. // Color instance in sRGB
 Color c = Color.valueOf(1.0f, 0.26f,

    0.43f); // Color instance in Adobe RGB
 Color c = Color.valueOf(1.0f, 0.26f, 0.43f, 1.0f,
 ColorSpace.get(ColorSpace.Named.ADOBE_RGB));
  55. // Color instance in sRGB
 Color c = Color.valueOf(1.0f, 0.26f,

    0.43f); // Color instance in Adobe RGB
 Color c = Color.valueOf(1.0f, 0.26f, 0.43f, 1.0f,
 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); // From Adobe RGB to Display P3
 Color r = c.convert(
 ColorSpace.get(ColorSpace.Named.DISPLAY_P3));
  56. // RGBA in Adobe RGB
 @ColorLong long c = Color.pack(1.0f,

    0.26f, 0.43f, 1.0f,
 ColorSpace.get(ColorSpace.Named.ADOBE_RGB));
  57. Red, 16 bits Green, 16 bits Blue, 16 bits Alpha,

    10 bits Colorspace, 6 bits @ColorLong
  58. Red, 16 bits Green, 16 bits Blue, 16 bits Alpha,

    10 bits Colorspace, 6 bits @ColorLong See android.util.Half
  59. ColorSpace cs = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
 cs.isWideGamut(); // Returns true
 cs.getModel(); //

    Returns ColorSpace.Model.RGB // Cast to ColorSpace.Rgb to get primaries, white point, etc.
  60. // Use connectors for conversions
 ColorSpace.Connector c = ColorSpace.connect(
 ColorSpace.get(ColorSpace.Named.SRGB),


    ColorSpace.get(ColorSpace.Named.ADOBE_RGB)
 );
 float[] adobeRGB = c.transform(1.0f, 0.26f, 0.43f);
  61. // Change the white point with chromatic adaptation
 ColorSpace d50

    = ColorSpace.adapt(
 ColorSpace.get(ColorSpace.Named.SRGB),
 ColorSpace.ILLUMINANT_D50
 );
  62. Bitmap b = BitmapFactory.decodeStream(…);
 ColorSpace cs = b.getColorSpace();
 // Most

    likely, cs.isSrgb() == true
  63. Bitmap b = BitmapFactory.decodeStream(…);
 ColorSpace cs = b.getColorSpace();
 // Most

    likely, cs.isSrgb() == true Bitmaps are always in the RGB color model
  64. BitmapFactory.Options opts = new BitmapFactory.Options();
 // What a silly name

    opts.inJustDecodeBounds = true;
 
 Bitmap b = BitmapFactory.decodeStream(…, opts);
 ColorSpace cs = opts.outColorSpace;
  65. BitmapFactory.Options opts = new BitmapFactory.Options();
 // Convert at load time

    opts.inPreferredColorSpace =
 ColorSpace.get(ColorSpace.Named.SRGB);
 
 Bitmap b = BitmapFactory.decodeStream(…, opts);
  66. BitmapFactory.Options opts = new BitmapFactory.Options();
 // Convert at load time

    opts.inPreferredColorSpace =
 ColorSpace.get(ColorSpace.Named.SRGB);
 
 Bitmap b = BitmapFactory.decodeStream(…, opts); 16 bit bitmaps are always in linear extended sRGB
  67. // Let’s create a wide gamut bitmap Bitmap b =

    Bitmap.createBitmap(
 1920, 1080,
 Bitmap.Config.ARGB_8888, false,
 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)
 );
  68. // sRGB out @ColorInt int c = b.getPixel(0, 0); //

    sRGB in
 b.setPixel(0, 0, 0xfff436d);
  69. None
  70. // Preserve color space
 ByteBuffer dst = ByteBuffer.allocate(b.getByteCount());
 b.copyPixelsToBuffer(dst);
 dst.rewind();


  71. // Preserve color space
 ByteBuffer dst = ByteBuffer.allocate(b.getByteCount());
 b.copyPixelsToBuffer(dst);
 dst.rewind();


    // If the bitmap’s config is RGBA_F16
 // the byte buffer contains half floats
 // See android.util.Half
  72. sRGB

  73. non-sRGB sRGB

  74. [Color Space] [Color space]

  75. <activity
 android:colorMode="wideColorGamut" />

  76. non-sRGB sRGB sRGB No wide gamut support ARGB_8888

  77. non-sRGB extended sRGB sRGB Wide gamut support RGBA_F16

  78. Extended sRGB? (scRGB)

  79. res/*-widecg

  80. None
  81. Configuration c = getResources().getConfiguration();
 c.isScreenWideColorGamut();


  82. Configuration c = getResources().getConfiguration();
 c.isScreenWideColorGamut();
 Display d = view.getDisplay();
 d.isWideColorGamut()

  83. DON’T PANIC

  84. DON’T PANIC —— — — — — — —— —

  85. https://goo.gl/aeJc06 Learn more about transfer functions Starts at minute 29

    android.graphics.ColorSpace.Rgb
  86. https://goo.gl/5w7AQ2 Learn about banding and dithering Starts at minute 36

  87. Questions