Is there a technical reason why canvas's drawImage() doesn't do sub-pixel rendering / antialiasing?
Ttl;dr:
I need to move an image VERY slowly in canvas
without obvious pixel by pixel movement. I need some sort of anti-aliasing.
Recently I was tasked with animating some "cloud" drawings horizontally in a webpage.
Easily enough I just threw the image into the DOM and used CSS3 transforms with a fallback to jQuery animation for browsers that don't support CSS transforms yet.
Everything looked pretty good. I had some clouds moving smoothly moving across the page.
Then I kept getting requests from the designer to slow the movement down...way down.
Because br开发者_开发技巧owsers don't do sub-pixel rendering for DOM objects the animation appears to run at 6 FPS.
So, I slap the image into canvas for some quick tests and find out that it doesn't do sub-pixel rendering automatically, either.
My quick canvas animation demo (it doesn't accurately time the movements, deal with it. :-p )
For older browsers, you could animate a sprite. Create maybe 4 versions of your image, each shifted 0.25px to the left from the previous one. Paste those together in a sprite and then animate the background-position.
function moveClouds(n)
{
var v = (n % 4) * 417;
var h = Math.ceil(n / 4);
clouds.style.backgroundPosition = h + " " + v;
}
This is a known Chrome issue as documented at http://code.google.com/p/chromium/issues/detail?id=7508
still no resolution or workaround for it..
There is a hack you can do here, but it's pretty ugly.
You set the resolution of the canvas element to be higher than the actual display size, and then your translations are antialiased by the browser. Tada, sub-pixel animation in chrome!
I've tried around a bit with your code example and it seems to me that slower scrolling appears very smooth:
ctx.drawImage(img, left -= 0.0025, 0, 633, 417);
The browser I use is chrome on a mac.
As I understand it ... not done much browser testing of anti-aliasing. It kicks in when drawImage(img1, x,y,width,height) x or y are not integers. And kicks in when the canvas tags width="600" height="600" are larger than the style="width:600; height:600"
Setting the style to 1/2 the canvas size is suppose to force anti-aliasing. Last time I researched the subject. I would not assume browsers will implement the standard to 100%.
Note for green screening of videos anti-aliasing is important to remove artifacts.
Update: On your example I am not getting the anti-aliasing using chrome I am with firefox. latest releases of both browsers for Win XP. Firefox fps is painfully slow on your example.
Another Update Setting canvas style size to 1/3 of the canvas size [3 canvas pixels for 1 screen pixel] does appear to get the sub pixel rendering to work ... but the performance hit may be to big to accomplish it this way.
Sub-pixel canvas test.<br/>
<canvas id="canvas" width="317" height="351"
style="border:solid 1px #000; width:100px; height:100px"></canvas>
Sorry not the answer you actually wanted.
All browsers I test support Anti-Aliasing in the canvas, just put the image on an non integer coords to see it happening. But none subpixel rendering (for clarification, that is using LCDs ordering of red, green, blue subpixels to enhance horizontal resolution, great for text.)
According to the html5 pre-standard, its up to the browser to decide if it wants to do anti-aliasing or not.
精彩评论