-
Notifications
You must be signed in to change notification settings - Fork 19
Update examples section #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -198,9 +198,134 @@ The ``getImageData`` method is responsible for converting the data from the canv | |
## Examples | ||
|
||
### Selecting the best color space match for the user agent's display device | ||
<pre> | ||
var colorSpace = window.matchMedia("(color-gamut: p3)").matches ? "display-p3" : "srgb"; | ||
</pre> | ||
|
||
This example selects a wide color gamut canvas only if the underlying display has a P3 gamut or larger. | ||
|
||
```html | ||
// Note that the gamut is named p3, but the color space is 'display-p3'. | ||
var matchingColorSpace = window.matchMedia( | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'(color-gamut: p3)').matches ? 'display-p3' : 'srgb'; | ||
var canvas = document.getElementById('Canvas'); | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var context = canvas.getContext('2d', {colorSpace:matchingColorSpace}); | ||
``` | ||
|
||
### Drawing wide color gamut content to a 2D Canvas | ||
|
||
This example shows drawing a wide color gamut image to an sRGB and a Display-P3 canvas, and discusses the different expected results. | ||
|
||
```html | ||
// Let |myWCGImage| be a loaded wide color gamut Image. | ||
var myWCGImage; | ||
|
||
// Let |defaultCanvas| be a default (sRGB) canvas. This code will draw the | ||
// specified image, but will clip it to the sRGB color gamut. | ||
var defaultCanvas = document.getElementById('DefaultCanvas'); | ||
var defaultCtx = defaultCanvas.getContext('2d'); | ||
defaultCtx.drawImage(myWCGImage, 0, 0, image.width, image.height) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any formal spec on clipping behavior? Same question for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CSS Color Module 4 goes over the formal color space conversion math and clamping. If it is ambiguous, it should be made clear. (There is no fancy conversion -- values that don't fit in the target gamut are chopped off). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes, [here]
Per-component clamping is discouraged because it can produce massive hue shifts. CSS Color 4 talks about gamut mapping but that section has not yet been specce'ed out. open issue It has been incubated though, again the algorithm is fairly simple. For some use cases, simple clamping is still what you want; so there will be both options.
Yes, and it will be. Also I should point out that in CSS Color 4, partly driven by the needs of Canvas for WCG & HDR, the domain and range f the RGB transfer functions are unbounded. This is to avoid any premature clipping, which would preclude round-tripping; and also because HDR will need that. |
||
|
||
// Let |wcgCanvas| be a Display-P3 canvas. This code will draw the specified | ||
// image, which will not be clipped to the sRGB color gamut (it will be | ||
// restricted only to the P3 color gamut). | ||
var wcgCanvas = document.getElementById('DefaultCanvas'); | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var wcgCtx = wcgCanvas.getContext('2d', {colorSpace:'display-p3'}); | ||
wcgCtx.drawImage(myWCGImage, 0, 0, image.width, image.height) | ||
``` | ||
|
||
### Drawing and retrieving content using ``ImageData`` | ||
|
||
This example shows use of the new ``ImageData`` color management APIs. | ||
|
||
```html | ||
var canvas = document.getElementById('Canvas'); | ||
var context = defaultCanvas.getContext('2d', {colorSpace:'display-p3'}); | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Creating a ImageData without specifying ImageDataSettings will create an | ||
// sRGB ImageData. This will draw the color sRGB-red to the canvas. | ||
var srgbImageData = new ImageData(1, 1); | ||
srgbImageData.data[0] = srgbImageData.data[3] = 255; | ||
srgbImageData.data[1] = srgbImageData.data[2] = 0; | ||
context.putImageData(srgbImageData, 0, 0); | ||
|
||
// This will draw P3-red to the canvas. | ||
var p3ImageData = new ImageData(1, 1, {colorSpace:'display-p3'}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we expect There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. We removed from this proposal along with >8-bit 2D canvas support. It will be re-introduced in a separate proposal that covers high dynamic range. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
p3ImageData.data[0] = p3ImageData.data[3] = 255; | ||
p3ImageData.data[1] = p3ImageData.data[2] = 0; | ||
context.putImageData(p3ImageData, 0, 0); | ||
|
||
// The color space of an ImageData can be retrieved through its | ||
// ImageDataSettings. | ||
console.log(srgbImageData.getSettings().colorSpace); | ||
console.log(p3ImageData.getSettings().colorSpace); | ||
|
||
// Reading back an ImageData without specifying a color space will retrieve | ||
// pixel values converted to sRGB. This will clamp color values to sRGB, and | ||
// so |readSrgbImageData.data| will be [255,0,0,255, 255,0,0,255]; | ||
var readSrgbImageData = context.getImageData(0, 0, 2, 1); | ||
console.log(readSrgbImageData.data); | ||
|
||
// Reading back an ImageData specifying a color space will retrieve the pixel | ||
// values converted to that color space. |readP3ImageData.data| will be | ||
// [234,51,35,255, 255,0,0,255]. | ||
var readP3ImageData = context.getImageData(0, 0, 2, 1, | ||
{colorSpace:'display-p3'}); | ||
console.log(readP3ImageData.data); | ||
``` | ||
|
||
### Drawing WebGL wide color gamut content | ||
|
||
This example shows a WebGL application that clears the screen to Display P3 red. | ||
|
||
```html | ||
var canvas = document.getElementById('Canvas'); | ||
var gl = defaultCanvas.getContext('webgl2'); | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
gl.colorSpace = 'display-p3'; | ||
gl.clearColor(1.0, 0.0, 0.0, 1.0); | ||
gl.clear(gl.COLOR_BUFFER_BIT); | ||
``` | ||
|
||
### Uploading an image as Display-P3 pixels | ||
|
||
This example shows uploading an image and converting its color profile. | ||
Note that this example assumes the conversion behavior of ``BROWSER_DEFAULT_WEBGL``. | ||
Also note that in this example the color conversion happens synchronously at the moment that ``texImage2D`` is called, which may not be ideal. | ||
|
||
```html | ||
// Let |myImage| be an image that has some (unknown) color profile. | ||
var myImage; | ||
var canvas = document.getElementById('Canvas'); | ||
var gl = defaultCanvas.getContext('webgl2'); | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Let texInP3 be the image converted to Display-P3. | ||
var texInP3 = gl.createTexture(); | ||
gl.bindTexture(gl.TEXTURE_2D, texInP3); | ||
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, | ||
gl.BROWSER_DEFAULT_WEBGL); | ||
gl.colorSpace = 'display-p3'; | ||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, image.width, image.height, 0, | ||
gl.RGBA, gl.UNSIGNED_BYTE, image); | ||
``` | ||
|
||
In this example, the ``ImageBitmap`` API is used to allow the color conversion of the image to be performed asynchronously at decode time. | ||
|
||
```html | ||
// Let |myImageUrl| be the URL for an image that has some (unknown) color | ||
// profile. | ||
var myImageUrl; | ||
var canvas = document.getElementById('Canvas'); | ||
var gl = defaultCanvas.getContext('webgl2'); | ||
kenrussell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
fetch(myImageUrl).then(function(response) { | ||
return response.blob(); | ||
}).then(function(blob) { | ||
return createImageBitmap(blob, {colorSpace:'display-p3'}); | ||
}).then(function(bitmap) { | ||
const texInP3 = gl.createTexture(); | ||
gl.bindTexture(gl.TEXTURE_2D, texInP3); | ||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, bitmap.width, | ||
bitmap.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, bitmap); | ||
|
||
}); | ||
``` | ||
|
||
## Adoption | ||
Lack of color management and color interoperability is a longstanding complaint about the canvas API. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct - this is unfortunate but deliberate. The three MQ gamut buckets are deliberately approximate, basically "normal" "wide" and "superwide". p3 would match an Adobe RGB screen, for example.
While the color spaces, like display-p3, are much more specific and tightly defined.