- From: Kenneth Russell <kbr@google.com>
- Date: Tue, 12 Mar 2013 16:53:48 -0700
- To: Rik Cabanier <cabanier@gmail.com>
- Cc: WHAT Working Group <whatwg@whatwg.org>
On Tue, Mar 12, 2013 at 3:49 PM, Rik Cabanier <cabanier@gmail.com> wrote: > > > On Tue, Mar 12, 2013 at 3:03 PM, Kenneth Russell <kbr@google.com> wrote: >> >> On Tue, Mar 12, 2013 at 2:04 PM, Rik Cabanier <cabanier@gmail.com> wrote: >> > >> > >> > On Tue, Mar 12, 2013 at 11:40 AM, Kenneth Russell <kbr@google.com> >> > wrote: >> >> >> >> On Tue, Mar 12, 2013 at 11:15 AM, Rik Cabanier <cabanier@gmail.com> >> >> wrote: >> >> > sounds good! >> >> > I think this is a convenient and useful addition. >> >> >> >> Great. >> >> >> >> > do you want to keep doubles to define the dimensions instead of >> >> > integers? If >> >> > so, the size should probably 4 * ceil(sw) * ceil(sh) >> >> >> >> I would prefer to use integers, and only used doubles to be consistent >> >> with the other APIs like getImageData and createImageData. In this >> >> case it would make more sense to use integers, since the width and >> >> height are simply being used to interpret preexisting data in the >> >> Uint8ClampedArray. >> > >> > >> > The current canvas spec doesn't specifically state what happens with >> > partial >> > pixels. What happens today? >> > (Also is there a definition somewhere that states when a pixel is >> > considered >> > filled?) >> >> Safari, Firefox and Chrome all round the double arguments to >> putImageData to integers using the "truncate" rounding mode and then >> draw the source ImageData pixel-for-pixel. For example, passing 64.5 >> or 64.99 for the dx or dy arguments is equivalent to passing 64. >> Here's a test case. >> >> <canvas id="canvas" width="256" height="256"></canvas> >> <script> >> var canvas = document.getElementById("canvas"); >> var ctx = canvas.getContext("2d"); >> var width = canvas.width; >> var height = canvas.height; >> ctx.fillRect(0, 0, width, height); >> var imageData = ctx.createImageData(width / 2, height / 2); >> for (var ii = 0; ii < imageData.data.length; ii += 4) { >> imageData.data[ii + 0] = 0; >> imageData.data[ii + 1] = 255; >> imageData.data[ii + 2] = 0; >> imageData.data[ii + 3] = 255; >> } >> // Try passing 64.5, 64.99, or 65 for one or both of these arguments >> and see the results >> ctx.putImageData(imageData, 64, 64); >> </script> >> >> In other words, the source ImageData would not be rendered into the >> canvas at a half-pixel offset if ctx.putImageData(imageData, 64.5, >> 64.5) were called. > > > Thanks for investigating this. The fact that 'truncate' is called, should > probably go in the spec. > Maybe we should change the IDL to integer. I think that would be a good idea. I believe it would be backward compatible and leave the definition of double -> long conversion to the Web IDL and ECMAScript specs. >> >> I don't think it is necessary to provide a createImageDataHD in this >> >> interface. The caller will know the devicePixelRatio and determine >> >> whether to generate high-DPI data. >> > >> > That probably won't work since it results in code that executes >> > differently >> > on devices that are HD. >> >> I think it works. The application will call the new ImageData >> constructor and pass it to either putImageData or putImageDataHD. >> These interpret the incoming ImageData differently depending on the >> devicePixelRatio. >> >> In contrast, CanvasRenderingContext2D's existing createImageDataHD and >> getImageDataHD methods will create an ImageData that may have a >> different width and height from those passed in. The reason for this >> is that these methods are referring to the canvas's backing store. For >> this new constructor which simply wraps existing pixel data, the >> application knows exactly how many pixels are contained in the array, >> so it makes the most sense to take the incoming width and height >> verbatim. I don't see any advantage to having an alternate "high-DPI" >> constructor which would multiply the width and height by the >> devicePixelRatio behind the scenes. >> > > Your proposal is: > > createImageData would throw an exception if the length of the > Uint8ClampedArray was not equal to 4 * floor(sw) * floor(sh), or at > least, if the length of the array was less than this value. Yes. > So, if you create an imageData that is going to be used in putImageDataHD, > the bounds checking happens when you pass it into putImageDataHD? > It seems the imageData object should know if it was meant for an HD call. > There is no real reason why you could use it in both HD and non-HD APIs. Glenn already answered this, but you can already call getImageData and pass the result to putImageDataHD (and vice versa -- getImageDataHD/putImageData). The only difference between putImageData and putImageDataHD is that on high-DPI displays putImageDataHD will take the same image data and display it in a smaller region. All of the size checking would be performed in the new ImageData constructor we're discussing. I don't think ImageData itself should know anything about high DPI because it's designed for pixel-by-pixel manipulation. -Ken >> >> >> >> >> >> >> > On Tue, Mar 12, 2013 at 10:50 AM, Kenneth Russell <kbr@google.com> >> >> > wrote: >> >> >> >> >> >> It should simply reference the Uint8ClampedArray, not copy it or do >> >> >> anything else esoteric. The only way to display an ImageData in the >> >> >> 2D >> >> >> canvas context is via the putImageData API. I am not proposing >> >> >> changing those semantics. >> >> >> >> >> >> -Ken >> >> >> >> >> >> >> >> >> >> >> >> On Mon, Mar 11, 2013 at 5:00 PM, Rik Cabanier <cabanier@gmail.com> >> >> >> wrote: >> >> >> > Do you expect that createImageData creates an internal copy of the >> >> >> > Uint8ClampedArray object or is it live? >> >> >> > >> >> >> > >> >> >> > On Mon, Mar 11, 2013 at 4:28 PM, Kenneth Russell <kbr@google.com> >> >> >> > wrote: >> >> >> >> >> >> >> >> It would be useful to be able to create an ImageData [1] object >> >> >> >> with >> >> >> >> preexisting data. The main use case is to display arbitrary data >> >> >> >> in >> >> >> >> the 2D canvas context with no data copies. >> >> >> >> >> >> >> >> Proposed IDL: >> >> >> >> >> >> >> >> [NoInterfaceObject] >> >> >> >> interface ImageDataFactories { >> >> >> >> ImageData createImageData(Uint8ClampedArray data, double sw, >> >> >> >> double >> >> >> >> sh); >> >> >> >> }; >> >> >> >> Window implements ImageDataFactories; >> >> >> >> WorkerGlobalScope implements ImageDataFactories; >> >> >> >> >> >> >> >> createImageData would throw an exception if the length of the >> >> >> >> Uint8ClampedArray was not equal to 4 * floor(sw) * floor(sh), or >> >> >> >> at >> >> >> >> least, if the length of the array was less than this value. >> >> >> >> (Similar >> >> >> >> wording would be used to that of CanvasRenderingContext2D's >> >> >> >> createImageData.) >> >> >> >> >> >> >> >> I don't think it is necessary to provide a createImageDataHD in >> >> >> >> this >> >> >> >> interface. The caller will know the devicePixelRatio and >> >> >> >> determine >> >> >> >> whether to generate high-DPI data. >> >> >> >> >> >> >> >> [1] >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata >> >> >> >> >> >> >> >> Comments? >> >> >> >> >> >> >> >> Thanks, >> >> >> >> >> >> >> >> -Ken >> >> >> > >> >> >> > >> >> > >> >> > >> > >> > > >
Received on Tuesday, 12 March 2013 23:54:15 UTC