[whatwg] Canvas ImageData comments

Philip Taylor excors+whatwg at gmail.com
Fri Jun 15 20:45:47 PDT 2007

Some minor comments from looking again at the ImageData section:

Colour spaces are not dealt with at all, but are particularly relevant
for getImageData (else you have no idea what the values mean). It's
probably easiest if no conversions happen at all in the canvas, so you
could have:
  ctx.fillStyle = 'rgb(123, 45, 67)';
  ctx.fillRect(0, 0, 1, 1);
  var img = new Image();
  img.src = canvas.toDataURL();
  img.onload = function () {
    ctx.drawImage(img, 0, 0);
    ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0);
    var imgdata = ctx.getImageData(0, 0, 1, 1);
    assert(imgdata.data[0:4] == [123, 45, 67, 255]); // (except it
should accept quantisation errors, e.g. if you're using a 16-bit
which I think covers most of the cases where colour conversions might
be relevant (though there are others, like linear interpolation of
gradients, where colour space matters too), and which I think matches
current implementations (but I've not checked that). It seems CSS is
defined to use sRGB, but I don't know if that is true in reality, so
maybe it's safest to just say that all colours throughout the canvas
API must be handled consistently in the same colour space (without
saying exactly which it is).

"The putImageData(image, dx, dy) method must take the given ImageData
structure, and draw it at the specified location dx,dy in the canvas
coordinate space, mapping each pixel represented by the ImageData
structure into one device pixel." - how should it 'draw it'? Given the
requirement on putImageData(getImageData(...)), it has to be replacing
the pixels in that area rather than doing anything like normal
drawing, but that isn't explicit.

Perhaps it should say "The putImageData(image, dx, dy) method must
take the given ImageData structure, and replace the device pixels in
the rectangle with top left corner (dx, dy) and width and height as
given in the ImageData structure, by the pixel data in the ImageData
structure with each pixel mapped onto one device pixel."

"an integer array" - what is that? Does { 0:0, 1:0, 2:0, 3:0, length:4
} count, since it looks quite like an array? Why can't I use a
non-integer array like [ 255*(0.5 + 0.5*Math.sin(x/100)) for (x in [0,
1, 2, 3, ... ]) ] and have putImageData round to integers, and clamp
to the range [0, 255], since that would be closer to what I wanted
than an exception would be?

Given the quite disgusting code like "[i for (i in function (n) { for
(let i = 0; i < n; i += 1) yield 0 }(w*h*4)) ]" to generate an array
of zeros, maybe it would be nice to accepted 'undefined' element
values and treat them as zero, so that people don't have to bother
filling in parts of the array they don't care about.

(For Firefox 2 / Minefield, it throws NS_ERROR_DOM_SYNTAX_ERR if .data
is not an actual JS array, or if .data.length < w*h*4. For each of the
first w*h*4 elements, if it is not a number then it throws
NS_ERROR_DOM_SYNTAX_ERR. Otherwise it gets rounded towards zero: if
the result is an integer in the range [-2^30, 2^30), or if you're
running on Windows instead of Linux (?!), then it gets wrapped to the
range [0, 256), else it gets treated as 0. Elements after the first
w*h*4 are completely ignored. See
<http://canvex.lazyilluminati.com/misc/imagedata.html>, but not in
FF2-on-Linux because that's totally broken.)

In the example code:
"var could" - should be "var cloud".
"function FillPlasma(data) { ... }" - should be "function
FillPlasma(data, color) { ... }".
"function FillCload(data, x, y) { ... }" - should be "function
FillCloud(data, x, y) { ... }".

The example creates two ImageDatas of the same size, the putImageDatas
one on top of the other at the same position. That seems pointless,
since the second will completely overwrite the first.

"The current transformation matrix must not affect the getImageData()
and putImageData() methods." - nor must the composite operation,
global alpha, shadow, clip region ( ? In FF it does get clipped), ...

"the rectangle which has one corner at the (sx, sy) coordinate" -
s/one/its top left/

"Each component of each device pixel represented in this array must be
in the range 0..255" vs "The ImageData object's data array only
contains entries that are in the range 0 to 255 inclusive" -
inconsistent way of referring to ranges.

"the specified location dx,dy in the canvas coordinate space" - should
be "(dx, dy)" for consistent notation.

"ImageData objects must be initialised so that their height attribute
is set to h, [...] their width attribute is set to w, [...] and the
data attribute is initialised to an array of h×w×4 integers." -
height/h are written before width/w here, whereas everywhere else in
the document has widths before heights.

"The width and height (w and h) might be different than the sw and sh
arguments to the function" - 'different than' sounds a bit odd to me
here; maybe I'd prefer 'different from'.

"putImageData(image, dx, dy)" - maybe s/image/imagedata/, because it's
not at all the same as the 'image' parameter in drawImage.

"If getContext() is called with that exact string for tis contextId
argument ..." - s/tis/its/

"while one could create an ImageData object, one would net necessarily
know what resolution the canvas expected" - s/net/not/

Philip Taylor
excors at gmail.com

More information about the whatwg mailing list