So while playing around with some image filtering code using the Canvas ImageData APIs I realised that the APIs as currently designed make it difficult to do certain kinds of operation. The specific issue is that there is no direct mechanism to get a working/scratch ImageData object of the same size as an existing buffer.

To illustrate imagine we have a (very) simplistic filter model (in a fairly horrific cludge of IDL, JS, etc)

interface Filter {
ImageData apply(CanvasRenderingContext2D context, ImageData input);
}

var filters = ...;
...
CanvasRenderingContext2D context = canvas.getContext("2d");
ImageData data = context.getImageData(0, 0, canvas.width, canvas.height);
...
filters.myAwesomeFilter.apply(context, filters.myLessAwesomeFilter.apply(context,input));
...

Such a setup can allow developers to (inefficiently in this case) chain a sequence of filters together to produce a desired result.

This trivial mechanism works for a variety of filters, as many filters can just mutate the input buffer (negation, hue shifting, etc, etc) but for any filter for which a single output pixel may depend on multiple input pixels a second buffer must be used.

Unfortunately with the current ImageData API it is not possible to simply create a new ImageData object with the same dimensions as an existing instance as the width and height of the ImageData object are in device pixels whereas the width and height parameters of create/ getImageData are both in CSS pixels. This means that on any platform without a 1:1 correspondence a new ImageData created in a manner similar to:

newData = context.createImageData(oldData.width, oldData.height)

will have different dimensions from the original input.

I think this is a problem that we need to resolve, but I have not yet worked out any real way to achieve this.

--Oliver


Reply via email to