Re: [whatwg] proposed canvas 2d API additions
On Sat, 28 Feb 2009, JustFillBug wrote: On 2006-04-26, Ian Hickson i...@hixie.ch wrote: On Mon, 24 Apr 2006, Vladimir Vukicevic wrote: Assuming nobody has any problem with: boolean isPointInPath(in float x, in float y); ...then I'll add that to the spec when you reply to this mail. Sure, isPointInPath sounds fine. Added. We can always add isPointInStrokedPath if we ever want to bother with that (which is where the ...Fill bit came from in my API, because the region covered by a stroked path and that covered by a filled path are different, even though testing for a hit against a filled region would by far be the common case). We can also call the other one isPointOnPath(), if we want to keep the method names reasonably short. I'm not sure we'll ever need to add it, though. Getting people to click on a line is generally silly. We do have a need of isPointOnPath() for editing Bezier lines interactively (on a font editing interface). When people want to add a new point on an already existing curve, we have to know if the click is on path. besides, we need double click on the curve to pickup the whole path and then drag on the line to move the whole path. So I dig up a 2006 post... Of course it's hard to get people click on a line precisely. But we can check isPointOnPath for an 5x5 square instead to make the operation easier. Doing point on curve in javascript is painful. And since checking isPointInPath() already need to detect the on edge case, this shouldn't be too much a burdern on the browser developers. So please conside add the isPointOnPath() call to the function. On Sat, 28 Feb 2009, Philip Taylor wrote: (Or maybe we could add a convertStrokeToPath() function, which replaces the current path with a path representing the outline of what you'd get if you stroked the current path, and then use isPointInPath on it.) I haven't added either of these yet, because, as Philip pointed out in a part of his e-mail that I haven't quoted above, there are workarounds that can be done to approximate the results. I expect that when we introduce explicit Path objects we will include features like convertStrokeToPath() and so forth which will make this far easier to do. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
Philip's demonstration of how to handle detection of pointing at the curve is miserably wrong. His curve is not typographically correct (bounding box!). The detection should be in based on of precomputed regions rather than flattening. This all can be done in script library, of course, but the library would have to rely on mathematical techniques that the graphic designer need not understand. And the region information could be cached on-demand when it is first needed. I think it would be better to build the thing into the browser. See my solution at http://www.2a.pl/~ne01026/bzr.htm (VML + VBScript required). Chris
Re: [whatwg] proposed canvas 2d API additions
On Mon, 2 Mar 2009, Kristof Zelechovski wrote: [...] I would like to remind everyone that communication on this list is expected to be cordial, pleasant, and cooperative. After multiple warnings, I've taken the rare step of banning Kristof's e-mail address from the mailing list for a week. It will be restored on Monday, March 9th. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On 2006-04-26, Ian Hickson i...@hixie.ch wrote: On Mon, 24 Apr 2006, Vladimir Vukicevic wrote: Assuming nobody has any problem with: boolean isPointInPath(in float x, in float y); ...then I'll add that to the spec when you reply to this mail. Sure, isPointInPath sounds fine. Added. We can always add isPointInStrokedPath if we ever want to bother with that (which is where the ...Fill bit came from in my API, because the region covered by a stroked path and that covered by a filled path are different, even though testing for a hit against a filled region would by far be the common case). We can also call the other one isPointOnPath(), if we want to keep the method names reasonably short. I'm not sure we'll ever need to add it, though. Getting people to click on a line is generally silly. We do have a need of isPointOnPath() for editing Bezier lines interactively (on a font editing interface). When people want to add a new point on an already existing curve, we have to know if the click is on path. besides, we need double click on the curve to pickup the whole path and then drag on the line to move the whole path. So I dig up a 2006 post... Of course it's hard to get people click on a line precisely. But we can check isPointOnPath for an 5x5 square instead to make the operation easier. Doing point on curve in javascript is painful. And since checking isPointInPath() already need to detect the on edge case, this shouldn't be too much a burdern on the browser developers. So please conside add the isPointOnPath() call to the function.
Re: [whatwg] proposed canvas 2d API additions
On Sat, Feb 28, 2009 at 8:38 PM, JustFillBug mozbug...@yahoo.com.au wrote: On 2006-04-26, Ian Hickson i...@hixie.ch wrote: On Mon, 24 Apr 2006, Vladimir Vukicevic wrote: We can always add isPointInStrokedPath if we ever want to bother with that (which is where the ...Fill bit came from in my API, because the region covered by a stroked path and that covered by a filled path are different, even though testing for a hit against a filled region would by far be the common case). We can also call the other one isPointOnPath(), if we want to keep the method names reasonably short. I'm not sure we'll ever need to add it, though. Getting people to click on a line is generally silly. (Or maybe we could add a convertStrokeToPath() function, which replaces the current path with a path representing the outline of what you'd get if you stroked the current path, and then use isPointInPath on it.) We do have a need of isPointOnPath() for editing Bezier lines interactively (on a font editing interface). [...] Doing point on curve in javascript is painful. And since checking isPointInPath() already need to detect the on edge case, this shouldn't be too much a burdern on the browser developers. So please conside add the isPointOnPath() call to the function. What makes it painful? If you're only using Beziers, it doesn't seem too hard to approximate the curves as line segments and then calculate distances from that. http://philip.html5.org/demos/canvas/bezier-approx.html is fairly straightforward (and a much more accurate version shouldn't be much more complex) and can detect when your mouse is near a curve. (But if this is a common problem, it would indeed be nicer if the canvas API provided the functionality instead of forcing you to reimplement it.) -- Philip Taylor exc...@gmail.com
Re: [whatwg] proposed canvas 2d API additions
On Fri, 19 May 2006 17:34:04 +0200, Ian Hickson [EMAIL PROTECTED] wrote: One other problem I had with it was that the colors are restricted to 8 bit. That may potentially lead to data loss but I guess it's not a major concern yet. This is already the case in other aspects of the API, I think. As you pointed out some to me, not for percentage rgb color values. -- Anne van Kesteren http://annevankesteren.nl/ http://www.opera.com/
Re: [whatwg] proposed canvas 2d API additions
On Tue, 29 Aug 2006, Anne van Kesteren wrote: On Fri, 19 May 2006 17:34:04 +0200, Ian Hickson [EMAIL PROTECTED] wrote: One other problem I had with it was that the colors are restricted to 8 bit. That may potentially lead to data loss but I guess it's not a major concern yet. This is already the case in other aspects of the API, I think. As you pointed out some to me, not for percentage rgb color values. I don't recall what this thread was about. Was there a change you wanted made to the spec? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On Tue, 9 May 2006, Ric Hardacre wrote: i absolutely agree that pixels should be treated as atomic units. if a canvas pixel space is initialized as a 1x1 square then there is only one (visible) coordinate you could possibly access: (0,0) Canvas' coordinate space is not quantised. The arguments are all floats, not ints. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On 4/26/06, Ian Hickson [EMAIL PROTECTED] wrote: ImageData getImageData(in float x, in float y, in float w, in float h); void drawImageData(in float x, in float y, in ImageData d); I'm about to implement this as suggested; however, I'd call the second function here putImageData instead of drawImageData; draw implies an actual drawing operation, similar to drawImage, that would be affected by (at least) the current compositing operator. What's actually happening is a direct replacement of the pixel data in the given region, so that could be confusing. (If someone does want the operator to be involved they can use an offscreen canvas to call putImageData on and drawImage that in.) - Vlad
Re: [whatwg] proposed canvas 2d API additions
Quoting Vladimir Vukicevic [EMAIL PROTECTED]: I agree that they shouldn't be affected by the CTM, but I disagree that they should be integers. e.g. in cases like: HTML CSS canvas height=1 width=1 canvas { height: 100%; width: 100%; } /canvas ...where the JS then uses the coordinate space 0..1,0..1 the author might want to grab the top corner by grabbing the 0,0,0.25,0.25 rect. So, I really don't like this -- we need to nail down space the getPixels/setPixels coordinates should be in. I still think that they should always be in the canvas space, no matter how many pixels they refer to in the rendered content or in the device space. Note that in your example, the canvas can still be a 1x1 pixel canvas (and, I believe, will be in all current implementations) -- that one pixel will just cover the entire page. That is what Ian is saying. He's saying it's a 1x1 pixel canvas just that within that 1x1 pixel there could be different subpixels with different colors you could try to get using floating points instead of integers. -- Anne van Kesteren http://annevankesteren.nl/
Re: [whatwg] proposed canvas 2d API additions
Quoting Ian Hickson [EMAIL PROTECTED]: How about: interface ImageData { readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } I saw you added this API and noted that you haven't addressed security yet. Basically the same security considerations as for toDataURL() should apply. I suggest adding that somewhere. One other problem I had with it was that the colors are restricted to 8 bit. That may potentially lead to data loss but I guess it's not a major concern yet. -- Anne van Kesteren http://annevankesteren.nl/
Re: [whatwg] proposed canvas 2d API additions
On Fri, 28 Apr 2006, Arve Bersvendsen wrote: I would suggest that we do not use floats for the color values. While the choice of floats versus integers hardly matters on the desktop, it is a big deal on mobile devices, where you (often) may find that there is no FPU, so any floating point operations are performed entirely in software. The performance implication of this is huge, and we should not sacrifice performance for theoretical perfection. This seems like a valid argument. On Fri, 28 Apr 2006, Vladimir Vukicevic wrote: How about: interface ImageData { readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } I have a nagging feeling that this is a bad idea, but I can't explain why, because I do like the idea. If we do this, let's advance it a bit: I'd rather keep it as simple as possible in the first version. readonly attribute string format; /* only rgba is valid for now */ format would specify the type of data that is in data; only rgba would be valid for now, but we this gives us a way to extend that later on. We can always extend it in the next version by adding format, there's no reason to add it now that I can see. In fact we might (on the long run) want to add it to the context instead of the ImageData object, e.g. to make the entire API use CMYK or 16 bit RGBA instead of 8bit RGBA like today. I think until we have clear requirements on the issue we should just avoid adding features to handle it. ImageData createImageData(in string format, in string width, in string height, in Array data); for creating ImageData out of an arbitrary set of generated data (e.g. evaluating some function, drawing the results). This would be especially needed because you can't assign to data in an ImageData structure (since you have it readonly); can only change the values of its members. You could always create an arbitrarily sized ImageData structure by creating a blank canvas and using getPixels on that canvas. This would let you initialise the array to white, transparent black, or whatever is necessary. ImageData getImageData(in float x, in float y, in float w, in float h); void drawImageData(in float x, in float y, in ImageData d); I would keep x/y/w/h as integers, and explicitly specify that they're not affected by the CTM. If they are, you can't guarantee a lossless round-trip (since if you shift over by half a pixel you have to do lots of resampling, etc.). I agree that they shouldn't be affected by the CTM, but I disagree that they should be integers. e.g. in cases like: HTML CSS canvas height=1 width=1 canvas { height: 100%; width: 100%; } /canvas ...where the JS then uses the coordinate space 0..1,0..1 the author might want to grab the top corner by grabbing the 0,0,0.25,0.25 rect. On Thu, 4 May 2006, Vladimir Vukicevic wrote: interface ImageData { readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } Actually, let's step back a second; this may be massive overengineering. What if we simply had: readonly attribute float deviceScaling; on the 2D context, which would give the scaling factor between canvas-space pixels (that is, the space that the canvas width/height attributes are in) and device-space pixels (the pixels of the actual backing store). So if canvas width=200 height=200/ was represented with a 300x300 backing store, deviceScaling would be 1.5; if 400x400, it would be 2.0. (If necessary, we can have deviceScalingX, deviceScalingY.) You'd still need the object if you wanted to extend it in some other way, e.g. with your suggested format attribute. Your proposal basically just moves two attributes from that object to the canvas, and the author now has to keep track of the height and width separately all the time when he passes the array around to mutate it. Also... should the RGBA data be returned with premultiplied alpha or not? Premultiplied tends to be better for the math, non-premultiplied tends to be easier to understand. (That is, 50% opaque green is (0,255,0,128) if non-premultiplied, or (0,128,0,128) if premultiplied.) For consistency with the rest of the API I'd say non-premultiplied, but I have no strong opinion on this. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On 4/28/06, Vladimir Vukicevic [EMAIL PROTECTED] wrote: interface ImageData { readonly attribute string format; /* only rgba is valid for now */ readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } Actually, let's step back a second; this may be massive overengineering. What if we simply had: readonly attribute float deviceScaling; on the 2D context, which would give the scaling factor between canvas-space pixels (that is, the space that the canvas width/height attributes are in) and device-space pixels (the pixels of the actual backing store). So if canvas width=200 height=200/ was represented with a 300x300 backing store, deviceScaling would be 1.5; if 400x400, it would be 2.0. (If necessary, we can have deviceScalingX, deviceScalingY.) Then getPixels is defined to take parameters in canvas pixel space, and returns the ARGB array in device space; if you ask for a 50x50 region, you'll get back 100x100x4 samples, with a deviceScaling of 2.0. putPixels would take coordinates in canvas pixel space again, but would take the appropriate device-pixel-sized ARGB array. This becomes tricky with non-integer deviceScaling; that is, if a 2x2 region becomes a 3x3 region with a deviceScaling of 1.5, what do you return when you're asked for x=1 y=1 w=1 h=1? I'd say that you end up resampling and shifting over your 3x3 device space backing store by .5 pixels so that the region would start on a device pixel boundary. This would obviously not be a clean round-trip, but the spec can inform authors how to ensure a clean round trip (only request regions where your x/y * deviceScaling are integers). This removes the need for a separate ImageData object and all the extra gunk necessary there, but still maintains full resolution independence. Any thoughts on this? - Vlad
Re: [whatwg] proposed canvas 2d API additions
On 4/26/06, Ian Hickson [EMAIL PROTECTED] wrote: On Mon, 24 Apr 2006, Vladimir Vukicevic wrote: The use case that I'm thinking of is essentially: pixels = c.getPixels(x, y, width, height); /* manipulate pixels here */ c.putPixels(pixels, x, y, width, height); That is, direct pixel manipulation, for performing some operation that can't be done using the context API. Ok. That is helpful, because there have been several use cases thrown about and it wasn't clear to me which use case we actually cared about. It seems to me that a critical requirement of the use case you describe is that the result of the following script: pixels = c.getPixels(x, y, width, height); /* do nothing here */ c.putPixels(pixels, x, y, width, height); ...be a (possibly expensive) no-op. That is, you should not lose image data -- the above should not corrupt your picture. This means the pixel data returned must be native resolution data. How about: interface ImageData { readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } I have a nagging feeling that this is a bad idea, but I can't explain why, because I do like the idea. If we do this, let's advance it a bit: interface ImageData { readonly attribute string format; /* only rgba is valid for now */ readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } format would specify the type of data that is in data; only rgba would be valid for now, but we this gives us a way to extend that later on. and also add: ImageData createImageData(in string format, in string width, in string height, in Array data); for creating ImageData out of an arbitrary set of generated data (e.g. evaluating some function, drawing the results). This would be especially needed because you can't assign to data in an ImageData structure (since you have it readonly); can only change the values of its members. ImageData getImageData(in float x, in float y, in float w, in float h); void drawImageData(in float x, in float y, in ImageData d); I would keep x/y/w/h as integers, and explicitly specify that they're not affected by the CTM. If they are, you can't guarantee a lossless round-trip (since if you shift over by half a pixel you have to do lots of resampling, etc.). - Vlad
Re: [whatwg] proposed canvas 2d API additions
On Mon, 24 Apr 2006, Vladimir Vukicevic wrote: The use case that I'm thinking of is essentially: pixels = c.getPixels(x, y, width, height); /* manipulate pixels here */ c.putPixels(pixels, x, y, width, height); That is, direct pixel manipulation, for performing some operation that can't be done using the context API. Ok. That is helpful, because there have been several use cases thrown about and it wasn't clear to me which use case we actually cared about. It seems to me that a critical requirement of the use case you describe is that the result of the following script: pixels = c.getPixels(x, y, width, height); /* do nothing here */ c.putPixels(pixels, x, y, width, height); ...be a (possibly expensive) no-op. That is, you should not lose image data -- the above should not corrupt your picture. This means the pixel data returned must be native resolution data. How about: interface ImageData { readonly attribute long int width; readonly attribute long int height; readonly attribute Array data; } ImageData getImageData(in float x, in float y, in float w, in float h); void drawImageData(in float x, in float y, in ImageData d); ...where getImageData() returns an object implementing the ImageData interface which contains the actual pixel data for the backing store of the canvas, with the width and height attributes giving the number of actual data pixels returned? The array would contain, as in your proposal, 4*width*height values, giving the R, G, B, and A components of each pixel in the image, row by row. In the ECMAScript binding we could make the ImageData object have the data field as its default so it could be dereferenced directly as if the ImageData object itself were the array. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On Mon, 24 Apr 2006, Vladimir Vukicevic wrote: Assuming nobody has any problem with: boolean isPointInPath(in float x, in float y); ...then I'll add that to the spec when you reply to this mail. Sure, isPointInPath sounds fine. Added. We can always add isPointInStrokedPath if we ever want to bother with that (which is where the ...Fill bit came from in my API, because the region covered by a stroked path and that covered by a filled path are different, even though testing for a hit against a filled region would by far be the common case). We can also call the other one isPointOnPath(), if we want to keep the method names reasonably short. I'm not sure we'll ever need to add it, though. Getting people to click on a line is generally silly. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On Sat, 22 Apr 2006, Sjoerd Visscher wrote: Ian Hickson wrote: On Sat, 22 Apr 2006, Sjoerd Visscher wrote: I understand what you are proposing. What I don't understand is what colour should be returned when the many device pixels represented by the given coordinate space pixel have different colors. The weighted average of the colors in the square the size of 1 by 1 canvas pixels. ...in fact, that won't work. It would mean that this, which should be a no-op: c.putPixels(c.getPixels(x, y, width, height), x, y, width, height); ...will end up down-sampling the bitmap, which seems like it would break the main use case for this API. If this is the main use case, then putPixels is just drawImage, and getPixels should be called copyCanvas, with the 4 arguments just setting a clip region. Vlad suggested the use case was sightly more complex, basically: c.putPixels(manipulate(c.getPixels(...)), ...); The main use case of calculating the color of a (pixel-)square whould be the eye drop tool. You could manually do this using the API I suggested earlier today, FWIW, including handling transparency in special ways. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On Sun, 23 Apr 2006, Maciej Stachowiak wrote: 1) Add a call to allow copying a rect from one canvas to another. You may want to be able to control the compositing mode for this. Then you can use an offscreen canvas to store a bitmap for later drawing into your visible canvas. If this involves a change of size the implementation has the opportunity to apply intelligent scaling. We already have this. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
[ Ian Hickson ] I don't understand how these are supposed to work when the underlying bitmap's device pixel space does not map 1:1 to the coordinate space. [ Vladimir Vukicevic ] I'm not sure what you mean -- the coordinates here are explicit canvas pixels, and they specifically ignore the current canvas transform. So, given canvas width=100 height=200/canvas the coordinates would be 0..99, 0..199. Without expressing any other opinion at the moment, I'd just like to clarify how Opera's implementation of getPixel/setPixel currently follows the coordinate space, as Vlad is suggesting here, disregarding any translation and rotation. Given the following script snippet: gc = document.getElementsByTagName('canvas')[0].getContext('opera-2dgame'); for ( var y = 50; y 100; y++){ for (var x = 50; x 100; x++){ gc.setPixel(x,y,blue); } } ... with this CSS: canvas { width: 200px; height: 200px; border: 1px solid black; } and the following markup: canvas width=100 height=100 we fill the bottom-right quadrant of the canvas, with a rectangle that is comprised of 100x100 CSS pixels. -- Arve Bersvendsen, Opera Software ASA
Re: [whatwg] proposed canvas 2d API additions
Arve's example is how I imagined putPixels working -- basically as a potential optimization over a bunch of fillRect calls. Even in the presence of a higher resolution backing store, this can provide for an optimization -- load the putPixels data into a bitmap image that's width*height pixels and draw it to the canvas backing store with the appropriate resolution scaling. The use case that I'm thinking of is essentially: pixels = c.getPixels(x, y, width, height); /* manipulate pixels here */ c.putPixels(pixels, x, y, width, height); That is, direct pixel manipulation, for performing some operation that can't be done using the context API. An example might be to perform a desaturate on a region of the canvas to obtain a grayscale region from a color one. Any image-type operations (copying a region from one place to another) should be done using the existing drawImage or other APIs, with temporary canvases as needed. Because of this, putPixels will end up losing quality in a getPixels/putPixels round-trip if the backing store is higher resolution. I'm not sure what to do about that; one solution might be that we specify that a pixel in the canvas backing store must map to exactly one pixel in canvas-space; that is, that there's always a cluster of NxN device pixels that correspond to 1 canvas pixel. We can then have getPixels return the actual device-resolution pixel data, along with a resolution multiplier or somesuch. I don't really like that, though; I'd much rather leave putPixels as the fillRect-type optimization, and have getPixels return a simple average of the color of all the device pixels that compose a single target pixel. (Again, as with the putPixels case, this can be optimized by simply doing a downscaling of the appropriate region of the higher-resolution backing store into a width*height pixel buffer). - Vlad On 4/24/06, Arve Bersvendsen [EMAIL PROTECTED] wrote: [ Ian Hickson ] I don't understand how these are supposed to work when the underlying bitmap's device pixel space does not map 1:1 to the coordinate space. [ Vladimir Vukicevic ] I'm not sure what you mean -- the coordinates here are explicit canvas pixels, and they specifically ignore the current canvas transform. So, given canvas width=100 height=200/canvas the coordinates would be 0..99, 0..199. Without expressing any other opinion at the moment, I'd just like to clarify how Opera's implementation of getPixel/setPixel currently follows the coordinate space, as Vlad is suggesting here, disregarding any translation and rotation. Given the following script snippet: gc = document.getElementsByTagName('canvas')[0].getContext('opera-2dgame'); for ( var y = 50; y 100; y++){ for (var x = 50; x 100; x++){ gc.setPixel(x,y,blue); } } ... with this CSS: canvas { width: 200px; height: 200px; border: 1px solid black; } and the following markup: canvas width=100 height=100 we fill the bottom-right quadrant of the canvas, with a rectangle that is comprised of 100x100 CSS pixels. -- Arve Bersvendsen, Opera Software ASA
Re: [whatwg] proposed canvas 2d API additions
putPixels is just a cover for drawing a bunch of 1 x 1 rects. And in general it won't be much more efficient than that, due to possible device scaling. Is drawing a bunch of 1x1 rects a common enough use case to be worth it? Seems like it would almost always be better solved by drawing an image or using other drawing calls. getPixels, as others have mentioned, is hard to define sensibly when the canvas backing store is higher resolution than the canvas coordinate space. Calling these pixels also seems misleading since they are neither device pixels nor CSS px units. Proposed alternate design: 1) Add a call to allow copying a rect from one canvas to another. You may want to be able to control the compositing mode for this. Then you can use an offscreen canvas to store a bitmap for later drawing into your visible canvas. If this involves a change of size the implementation has the opportunity to apply intelligent scaling. 2) Add an averageColorInRect call for the benefit of eyedropper type tools. I'm actually not sure how people intend to use getPixels / putPixels so I'm not 100% sure this covers the use cases. Regards Maciej On Apr 21, 2006, at 12:10 PM, Vladimir Vukicevic wrote: Hi folks, I'd like to suggest extending the HTML canvas 2d context with a few additions. These are variations on some of the methods added to Opera's opera-2dgame context. The methods are intended to give content authors direct pixel access to the canvas, as well as provide some basic point-in-path testing functionality. float [] getPixels (in integer x, in integer y, in integer width, in integer height); Returns an array of floats representing the color values in the region of pixels in the canvas whose upper left corner is at (x,y) and which extends for width,height pixels. These coordinates are in canvas pixel space (that is, the same space that the canvas width and height attributes are specified in). The color values for each pixel are returned as 4 floats, each in the range of 0.0 to 1.0, in R,G,B,A order. That is, given the paramters (0,0,2,2), the returned array will be [R00 G00 B00 A00 R10 G10 B10 A10 R01 G01 B01 A01 R11 B11 G11 A11]. Note: we could return the pixels as integers in the range of 0..255, as 8-bit color is most likely what canvases will be dealing with. However, using floats allow us to easily extend into a 16-bit colorspace without any API changes. In addition, any computation using these pixels is often done in normalized colors, so the division by 255 would need to happen anyway. void putPixels (in float [] pixels, in integer x, in integer y, in integer width, in integer height); Does the opposite of getPixels; the given array must be exactly width * height * 4 elements in length. The values are to be clamped to 0.0..1.0. boolean pointInPathFill(in float x, in float y); pointInPathFill returns true if the given point would be inside the region filled by the current path, and false otherwise. The x,y coordinates are in the current space of the canvas; that is, they are transformed by the CTM and do not necessarily map directly to pixels. I'd suggest that these three functions be added directly to the 2d context; content authors can test for their presence by checking the function is not null on the 2d context object. We might want a more comprehensive way of letting authors test whether particular features are supported, e.g. shadows, pixel-access, etc, but maybe it's not necessary. How's this sound? - Vlad
Re: [whatwg] proposed canvas 2d API additions
Ian Hickson wrote: On Sat, 22 Apr 2006, Sjoerd Visscher wrote: I understand what you are proposing. What I don't understand is what colour should be returned when the many device pixels represented by the given coordinate space pixel have different colors. The weighted average of the colors in the square the size of 1 by 1 canvas pixels. ...in fact, that won't work. It would mean that this, which should be a no-op: c.putPixels(c.getPixels(x, y, width, height), x, y, width, height); ...will end up down-sampling the bitmap, which seems like it would break the main use case for this API. If this is the main use case, then putPixels is just drawImage, and getPixels should be called copyCanvas, with the 4 arguments just setting a clip region. The main use case of calculating the color of a (pixel-)square whould be the eye drop tool. -- Sjoerd Visscher http://w3future.com/weblog/
Re: [whatwg] proposed canvas 2d API additions
On Fri, 21 Apr 2006, Vladimir Vukicevic wrote: boolean pointInPathFill(in float x, in float y); This sounds fine to me (though it means you have to spin through creating many paths for hit testing, instead of just hanging on to a particular path and hit testing a list of paths, which seems silly). float [] getPixels (in integer x, in integer y, in integer width, in integer height); void putPixels (in float [] pixels, in integer x, in integer y, in integer width, in integer height); I don't understand how these are supposed to work when the underlying bitmap's device pixel space does not map 1:1 to the coordinate space. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
On 4/21/06, Ian Hickson [EMAIL PROTECTED] wrote: On Fri, 21 Apr 2006, Vladimir Vukicevic wrote: boolean pointInPathFill(in float x, in float y); This sounds fine to me (though it means you have to spin through creating many paths for hit testing, instead of just hanging on to a particular path and hit testing a list of paths, which seems silly). Hm, I'm not sure what you mean -- we have no way of holding on to a Path as a retained object. If we did, then you could hit test through this object; there would be a speedup for some paths, but not noticable for most, I would think. Adding support for retained path objects would be an additional chunk of work, though, and isn't really necessary. float [] getPixels (in integer x, in integer y, in integer width, in integer height); void putPixels (in float [] pixels, in integer x, in integer y, in integer width, in integer height); I don't understand how these are supposed to work when the underlying bitmap's device pixel space does not map 1:1 to the coordinate space. I'm not sure what you mean -- the coordinates here are explicit canvas pixels, and they specifically ignore the current canvas transform. So, given canvas width=100 height=200/canvas the coordinates would be 0..99, 0..199. Are you referring to the case where on, say, a very high resolution display the canvas might choose to create a 200x400 pixel canvas and just present it as 100x200, and quadruple the physical screen space taken up by each pixel? If so, it would still map to the original 100x200 pixels; the fact that each of those takes up 4 physical device pixels should be transparent to the user. That is, we have: CSS size (width/height style) -- canvas size -- device bitmap size The API would always operate in terms of canvas size. Does that make more sense? - Vlad
Re: [whatwg] proposed canvas 2d API additions
On Fri, 21 Apr 2006, Vladimir Vukicevic wrote: On 4/21/06, Ian Hickson [EMAIL PROTECTED] wrote: On Fri, 21 Apr 2006, Vladimir Vukicevic wrote: boolean pointInPathFill(in float x, in float y); This sounds fine to me (though it means you have to spin through creating many paths for hit testing, instead of just hanging on to a particular path and hit testing a list of paths, which seems silly). Hm, I'm not sure what you mean -- we have no way of holding on to a Path as a retained object. If we did, then you could hit test through this object; there would be a speedup for some paths, but not noticable for most, I would think. Adding support for retained path objects would be an additional chunk of work, though, and isn't really necessary. I was suggesting that we may wish to add that code. Consider a canvas implementation of a board game with many little pieces. You get a click and want to find out which piece the click was on. With the API above, you basically have to redraw the entire board, except instead of calling .fill() on each one, you call .pointInPathFill(). That seems painful. Then again, you have the same problem with .fill() in the first place, so maybe it's not a big deal. (Incidentally, I would prefer isPointInPathFill() or isPointInPath() for this method name, since it is a test that returns a boolean.) Assuming nobody has any problem with: boolean isPointInPath(in float x, in float y); ...then I'll add that to the spec when you reply to this mail. float [] getPixels (in integer x, in integer y, in integer width, in integer height); void putPixels (in float [] pixels, in integer x, in integer y, in integer width, in integer height); I don't understand how these are supposed to work when the underlying bitmap's device pixel space does not map 1:1 to the coordinate space. I'm not sure what you mean -- the coordinates here are explicit canvas pixels, and they specifically ignore the current canvas transform. So, given canvas width=100 height=200/canvas the coordinates would be 0..99, 0..199. Are you referring to the case where on, say, a very high resolution display the canvas might choose to create a 200x400 pixel canvas and just present it as 100x200, and quadruple the physical screen space taken up by each pixel? Yes, except it doesn't have to be a high-resolution display: canvas height=10 width=10/ canvas { height: 100%; width: 100%; } ...should, per spec, work perfectly fine, but each coordinate space unit pixel is likely to map to many device pixels, and thus many colors. If so, it would still map to the original 100x200 pixels; the fact that each of those takes up 4 physical device pixels should be transparent to the user. That is, we have: CSS size (width/height style) -- canvas size -- device bitmap size The API would always operate in terms of canvas size. Does that make more sense? I understand what you are proposing. What I don't understand is what colour should be returned when the many device pixels represented by the given coordinate space pixel have different colors. Incidentally, what JS type did you mean float[] to map to? A simply Array instance? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [whatwg] proposed canvas 2d API additions
I understand what you are proposing. What I don't understand is what colour should be returned when the many device pixels represented by the given coordinate space pixel have different colors. The weighted average of the colors in the square the size of 1 by 1 canvas pixels. -- Sjoerd Visscher http://w3future.com/weblog/
Re: [whatwg] proposed canvas 2d API additions
On Sat, 22 Apr 2006, Sjoerd Visscher wrote: I understand what you are proposing. What I don't understand is what colour should be returned when the many device pixels represented by the given coordinate space pixel have different colors. The weighted average of the colors in the square the size of 1 by 1 canvas pixels. ...in fact, that won't work. It would mean that this, which should be a no-op: c.putPixels(c.getPixels(x, y, width, height), x, y, width, height); ...will end up down-sampling the bitmap, which seems like it would break the main use case for this API. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'