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.

Romain Guy

May 18, 2017
Tweet

More Decks by Romain Guy

Other Decks in Programming

Transcript

  1. UNDERSTANDING
    COLOR
    @romainguy

    View full-size slide

  2. UNDERSTANDING
    COLOR
    @romainguy

    View full-size slide

  3. What is color?

    View full-size slide

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

    View full-size slide

  5. ⚛ ☢ ☀ ♨
    10-16 108
    wavelength (m)

    View full-size slide

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

    View full-size slide

  7. 0
    1
    Short
    Medium
    Long

    View full-size slide

  8. What is color?

    View full-size slide

  9. For developers, a tuple of numbers
    in a color model with a color space

    View full-size slide

  10. RGB CMYK
    L*a*b*

    View full-size slide

  11. 1.0,0.26,0.43

    View full-size slide

  12. 3 primaries
    white point

    View full-size slide

  13. transfer functions
    3 primaries
    white point

    View full-size slide

  14. sRGB
    AdobeRGB
    ProPhotoRGB

    View full-size slide

  15. Transfer functions?

    View full-size slide

  16. sRGB P3 Adobe RGB
    sRGB

    View full-size slide

  17. What you saw is how Android handles color spaces
    Colors are unmanaged

    View full-size slide

  18. Source
    COLOR MANAGEMENT

    View full-size slide

  19. Source Destination
    COLOR MANAGEMENT

    View full-size slide

  20. New in O!
    Source Destination
    COLOR MANAGEMENT

    View full-size slide

  21. Assign
    Convert

    View full-size slide

  22. When in doubt… sRGB!

    View full-size slide

  23. // ARGB in sRGB
    @ColorInt int c = 0xfff436d;

    View full-size slide

  24. // Color instance in sRGB

    Color c = Color.valueOf(1.0f, 0.26f, 0.43f);

    View full-size slide

  25. // Color instance in sRGB

    Color c = Color.valueOf(1.0f, 0.26f, 0.43f);

    View full-size slide

  26. // 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));

    View full-size slide

  27. // 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));

    View full-size slide

  28. // 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));

    View full-size slide

  29. // RGBA in Adobe RGB

    @ColorLong long c = Color.pack(1.0f, 0.26f, 0.43f, 1.0f,

    ColorSpace.get(ColorSpace.Named.ADOBE_RGB));

    View full-size slide

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

    View full-size slide

  31. Red, 16 bits Green, 16 bits Blue, 16 bits
    Alpha, 10 bits
    Colorspace, 6 bits
    @ColorLong
    See android.util.Half

    View full-size slide

  32. 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.

    View full-size slide

  33. // 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);

    View full-size slide

  34. // Change the white point with chromatic adaptation

    ColorSpace d50 = ColorSpace.adapt(

    ColorSpace.get(ColorSpace.Named.SRGB),

    ColorSpace.ILLUMINANT_D50

    );

    View full-size slide

  35. Bitmap b = BitmapFactory.decodeStream(…);

    ColorSpace cs = b.getColorSpace();

    // Most likely, cs.isSrgb() == true

    View full-size slide

  36. Bitmap b = BitmapFactory.decodeStream(…);

    ColorSpace cs = b.getColorSpace();

    // Most likely, cs.isSrgb() == true
    Bitmaps are always in the RGB color model

    View full-size slide

  37. BitmapFactory.Options opts = new BitmapFactory.Options();

    // What a silly name
    opts.inJustDecodeBounds = true;


    Bitmap b = BitmapFactory.decodeStream(…, opts);

    ColorSpace cs = opts.outColorSpace;

    View full-size slide

  38. BitmapFactory.Options opts = new BitmapFactory.Options();

    // Convert at load time
    opts.inPreferredColorSpace =

    ColorSpace.get(ColorSpace.Named.SRGB);


    Bitmap b = BitmapFactory.decodeStream(…, opts);

    View full-size slide

  39. 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

    View full-size slide

  40. // Let’s create a wide gamut bitmap
    Bitmap b = Bitmap.createBitmap(

    1920, 1080,

    Bitmap.Config.ARGB_8888, false,

    ColorSpace.get(ColorSpace.Named.ADOBE_RGB)

    );

    View full-size slide

  41. // sRGB out
    @ColorInt int c = b.getPixel(0, 0);
    // sRGB in

    b.setPixel(0, 0, 0xfff436d);

    View full-size slide

  42. // Preserve color space

    ByteBuffer dst = ByteBuffer.allocate(b.getByteCount());

    b.copyPixelsToBuffer(dst);

    dst.rewind();


    View full-size slide

  43. // 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

    View full-size slide

  44. non-sRGB sRGB

    View full-size slide

  45. [Color Space] [Color space]

    View full-size slide

  46. android:colorMode="wideColorGamut" />

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  49. Extended sRGB?
    (scRGB)

    View full-size slide

  50. res/*-widecg

    View full-size slide

  51. Configuration c = getResources().getConfiguration();

    c.isScreenWideColorGamut();


    View full-size slide

  52. Configuration c = getResources().getConfiguration();

    c.isScreenWideColorGamut();

    Display d = view.getDisplay();

    d.isWideColorGamut()

    View full-size slide

  53. DON’T PANIC

    View full-size slide

  54. DON’T PANIC
    —— —


    — —
    —— —

    View full-size slide

  55. https://goo.gl/aeJc06
    Learn more about transfer functions
    Starts at minute 29
    android.graphics.ColorSpace.Rgb

    View full-size slide

  56. https://goo.gl/5w7AQ2
    Learn about banding and dithering
    Starts at minute 36

    View full-size slide