aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/user
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-04-14 11:06:09 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-04-14 15:18:12 +0000
commit8530211fbfd31922b55122d7bc7b28670729037d (patch)
treeb19fb33f5bfec20445585f7d35e85e9f23618827 /site/user
parent4343654bc4a93812cba168a665deef0de2ebcfdd (diff)
Add documentation for color correct skia to website
BUG=skia: NOTRY=true DOCS_PREVIEW= https://skia.org/?cl=10043 Change-Id: I025bf296518470dd2d5f62d7024a0f5d0fcc91c4 Reviewed-on: https://skia-review.googlesource.com/10043 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
Diffstat (limited to 'site/user')
-rw-r--r--site/user/sample/architecture.pngbin0 -> 23055 bytes
-rw-r--r--site/user/sample/color.md193
-rw-r--r--site/user/sample/detail_correct.pngbin0 -> 740282 bytes
-rw-r--r--site/user/sample/detail_wrong.pngbin0 -> 558558 bytes
-rw-r--r--site/user/sample/gamut_correct.pngbin0 -> 363256 bytes
-rw-r--r--site/user/sample/gamut_wrong.pngbin0 -> 378170 bytes
-rw-r--r--site/user/sample/gradient_correct.pngbin0 -> 16597 bytes
-rw-r--r--site/user/sample/gradient_wrong.pngbin0 -> 166493 bytes
-rw-r--r--site/user/sample/transfer_fn.pngbin0 -> 18749 bytes
9 files changed, 193 insertions, 0 deletions
diff --git a/site/user/sample/architecture.png b/site/user/sample/architecture.png
new file mode 100644
index 0000000000..a2b74cf10a
--- /dev/null
+++ b/site/user/sample/architecture.png
Binary files differ
diff --git a/site/user/sample/color.md b/site/user/sample/color.md
new file mode 100644
index 0000000000..28d86d396d
--- /dev/null
+++ b/site/user/sample/color.md
@@ -0,0 +1,193 @@
+Color Correct Skia
+==================
+
+Why is Skia Color Correct?
+--------------------------
+
+A color space is a **gamut** and a **transfer function**.
+
+Gamut refers to the **available range of colors** of a particular in an image or on a display
+device. Being gamut correct means that we will display colors as the designer intended and
+consistently across display devices. A common problem with new “wide gamut” devices and
+uncorrected colors is illustrated below.
+
+Device Dependent Color (Wrong)
+
+<img src='gamut_wrong.png'>
+
+Gamut Corrected Color
+
+<img src='gamut_correct.png'>
+
+Transfer function refers to **a non-linear encoding of pixel values**. A common transfer function
+is shown below.
+
+<img src='transfer_fn.png'>
+
+If we ignore the transfer function and treat non-linear values as if they are linear (when
+filtering, blending, anti-aliasing, multiplying), everything gets “too dark”.
+
+For example, we should see yellow (not brown) as the average of red and green light.
+
+Ignore Transfer Function
+
+<img src='gradient_wrong.png'>
+
+Apply Transfer Function
+
+<img src='gradient_correct.png'>
+
+Also, we should maintain fine detail when anti-aliasing (or downscaling).
+
+Ignore Transfer Function
+
+<img src='detail_wrong.png'>
+
+Apply Transfer Function
+
+<img src='detail_correct.png'>
+
+Skia Architecture for Color Correctness
+---------------------------------------
+
+<img src='architecture.png'>
+
+The major stages of the Skia drawing pipeline (premultiplication, filtering, blending) all assume
+linear inputs and linear outputs. Also, because they are linear operations, they are
+interchangeable.
+
+The gamut transform is a new operation (3x3 matrix) in the pipeline, but with similar properties:
+it is a linear operation with linear inputs and linear outputs.
+
+The important shift in logic from the legacy pipeline is that we actually apply the transfer
+function to transform the pixels to linear values before performing the linear operations.
+
+The most common transfer function, sRGB, is actually free on GPU! GPU hardware can transform sRGB
+to linear on reads and linear to sRGB on writes.
+
+Best Practices for Color Correct Skia
+-------------------------------------
+
+In order to perform color correct rendering, Skia needs to know the **SkColorSpace** of the content
+that you draw and the **SkColorSpace** of the surface that you draw to. There are useful factories
+to make color spaces.
+
+<!--?prettify lang=cc?-->
+
+ // Really common color spaces
+ sk_sp<SkColorSpace> MakeSRGB();
+ sk_sp<SkColorSpace> MakeSRGBLinear();
+
+ // Choose a common gamut and a common transfer function
+ sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma, Gamut);
+
+ // Create a color space from an ICC profile
+ sk_sp<SkColorSpace> MakeICC();
+
+Starting with **sources** (the things that draw you draw), there are a number of ways to make sure
+that they are tagged with a color space.
+
+**SkColor** (stored on **SkPaint**) is assumed to be in the sRGB color space - meaning that it
+is in the sRGB gamut and encoded with the sRGB transfer function.
+
+**SkShaders** (also stored on **SkPaint**) can be used to create more complex colors. Color and
+gradient shaders typically accept **SkColor4f** (float colors). These high precision colors
+can be in any gamut, but must have a linear transfer function.
+
+<!--?prettify lang=cc?-->
+
+ // Create a high precision color in a particular color space
+ sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>);
+
+ // Create a gradient shader in a particular color space
+ sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const SkColor4f colors[2],
+ sk_sp<SkColorSpace>, ...);
+
+ // Many more variations of shaders...
+ // Remember that SkColor is always assumed to be sRGB as a convenience
+
+**SkImage** is the preferred representation for image sources. It is easy to create **SkImages**
+ that are tagged with color spaces.
+
+<!--?prettify lang=cc?-->
+
+ // Create an image from encoded data (jpeg, png, etc.)
+ // Will be tagged with the color space of the encoded data
+ sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded);
+
+ // Create an image from a texture in a particular color space
+ // Caution: There are versions of this constructor that do not take an
+ // SkColorSpace. But without an SkColorSpace, Skia does not have
+ // enough information to draw correctly.
+ sk_sp<SkImage> MakeFromTexture(GrContext*, const GrBackendTextureDesc&,
+ SkAlphaType, sk_sp<SkColorSpace>, ...);
+
+**SkBitmap** is another (not preferred) representation for image sources. Be careful to not forget
+the color space.
+
+<!--?prettify lang=cc?-->
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(); // Bad: What is the color space?
+
+ SkBitmap bitmap;
+ SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
+ bitmap.allocPixels(info); // Bad: N32 is shorthand for 8888, no color space
+
+ SkBitmap bitmap;
+ SkImageInfo info = SkImageInfo::MakeS32(width, height, kPremul_SkAlphaType);
+ bitmap.allocPixels(info); // Good: S32 is shorthand for 8888, sRGB
+
+**SkImageInfo** is a useful struct for providing information about pixel buffers. Remember to use
+the color correct variants.
+
+<!--?prettify lang=cc?-->
+
+ // sRGB, 8888
+ SkImageInfo MakeS32(int width, int height, SkAlphaType);
+
+ // Create an SkImageInfo in a particular color space
+ SkImageInfo Make(int width, int height, SkColorType, SkAlphaType,
+ sk_sp<SkColorSpace>);
+
+Moving to **destinations** (the surfaces that you draw to), there are also constructors that allow
+them to be tagged with color spaces.
+
+<!--?prettify lang=cc?-->
+
+ // Raster backed: Make sure |info| has a non-null color space
+ sk_sp<SkSurface> MakeRaster(const SkImageInfo& info);
+
+ // Gpu backed: Make sure |info| has a non-null color space
+ sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext, SkBudgeted,
+ const SkImageInfo& info);
+
+Opting In To Color Correct Skia
+-------------------------------
+
+By itself, **adding a color space tag to a source will not change draw behavior**. In fact,
+tagging sources with color spaces is always a best practice, regardless of whether we want Skia’s
+color correct behavior.
+
+Adding a color space tag to the **destination is the trigger that turns on Skia color correct
+behavior**.
+
+Drawing a source without a color space to a destination with a color space is undefined. Skia
+cannot know how to draw without knowing the color space of the source.
+
+<style scoped><!--
+#colortable {border-collapse:collapse;}
+#colortable tr th, #colortable tr td {border:#888888 2px solid;padding: 5px;}
+--></style>
+<table id="colortable">
+<tr><th>Source SkColorSpace</th> <th>Destination SkColorSpace</th> <th>Behavior</th></tr>
+<tr><td>Non-null</td> <td>Non-null</td> <td>Color Correct Skia</td></tr>
+<tr><td>Null</td> <td>Non-null</td> <td>Undefined</td></tr>
+<tr><td>Non-null</td> <td>Null</td> <td>Legacy Skia</td></tr>
+<tr><td>Null</td> <td>Null</td> <td>Legacy Skia</td></tr>
+</table>
+
+It is possible to create **an object that is both a source and destination**, if Skia will both
+draw into it and then draw it somewhere else. The same rules from above still apply, but it is
+subtle that the color space tag could have an effect (or no effect) depending on how the object is
+used. \ No newline at end of file
diff --git a/site/user/sample/detail_correct.png b/site/user/sample/detail_correct.png
new file mode 100644
index 0000000000..3f14885ee8
--- /dev/null
+++ b/site/user/sample/detail_correct.png
Binary files differ
diff --git a/site/user/sample/detail_wrong.png b/site/user/sample/detail_wrong.png
new file mode 100644
index 0000000000..bd3c836a43
--- /dev/null
+++ b/site/user/sample/detail_wrong.png
Binary files differ
diff --git a/site/user/sample/gamut_correct.png b/site/user/sample/gamut_correct.png
new file mode 100644
index 0000000000..bb94caf5da
--- /dev/null
+++ b/site/user/sample/gamut_correct.png
Binary files differ
diff --git a/site/user/sample/gamut_wrong.png b/site/user/sample/gamut_wrong.png
new file mode 100644
index 0000000000..a5e584da64
--- /dev/null
+++ b/site/user/sample/gamut_wrong.png
Binary files differ
diff --git a/site/user/sample/gradient_correct.png b/site/user/sample/gradient_correct.png
new file mode 100644
index 0000000000..5649995186
--- /dev/null
+++ b/site/user/sample/gradient_correct.png
Binary files differ
diff --git a/site/user/sample/gradient_wrong.png b/site/user/sample/gradient_wrong.png
new file mode 100644
index 0000000000..8b70450e40
--- /dev/null
+++ b/site/user/sample/gradient_wrong.png
Binary files differ
diff --git a/site/user/sample/transfer_fn.png b/site/user/sample/transfer_fn.png
new file mode 100644
index 0000000000..14d38bd1d4
--- /dev/null
+++ b/site/user/sample/transfer_fn.png
Binary files differ