When using the CSS zoom
property, how can I convince the browser to use "nearest neighbor", instead of "bilinear" or any other more advanced zooming algorithms?
My setup is a div that contains a canvas, and the div gets its zoom set via JavaScript to be <div style="zoom:3200%">...</div>
and to get nearest neighbor, I am using image-rendering: -webkit-optimize-contrast
in my CSS. The app is available here ('z' zooms in, 'shift-z' zooms back out), and my css is here
Here is the desired effect in Chrome on OSX (zoom is set to 3200%):
But here is the same thing in Chrome on Windows 7:
In both cases it is "vanilla" Chrome (version 15.x.x) out of the box, no experimental flags are turned on.
How can I convince Chrome on Windows to use nearest neighbor? For that matter, how can I convince all browsers? Safari also does not use nearest neighbor (so far the app only works in WebKit based browsers)
The CSS image-rendering
property does affect Chrome/OSX and gives me the desired effect. But Chrome/Windows and Safari(5.1)/OSX both seem to completely ignore it. Something tells me I'm just out of luck, but I figured I'd ask.
Using zoom
on the div container is so simple and works beautifully in Chrome/OSX, if I must resort to scaling my canvases internally, I can do that too. But would prefer the literally one line of code solution if possible!
UPDATE: I have found the use of image-rendering: optimizeSpeed
helps. However it seems finicky in Chrome/Windows. If I set it on too many elements (I initially tried, my containers and all canvases), it doesn't take effect. But if I apply it to just canvas
, I get 98% of the way there.
Now my problem is the first time I draw while zoomed in, it works perfectly, all other subsequent drawing actions are fuzzy while they are taking place, then revert to the correct nearest-neighbor afterwards (my app draws into a scratch canvas first, then applies the drawing to the real canvas). There is something odd about the scratch canvas where Chrome insists on using bilinear. I think with some digging I can resolve that.
UPDATE2: It seems like image-rendering
on Chrome/Windows just isn't implemented well and is a bit buggy. I can now confirm that the values optimizeSpeed
and optimizeQuality
are not supported on Chrome/Windows. If you set image-rendering to them, Chrome will ignore the set. Chrome/Windows does recognize -webkit-optimize-contrast
, however it does not use it consistently. Chrome will flip between what looks to be a bilinear scaling algorithm and nearest-neighbor almost at random. I've not been able to consistently get Chrome to use nearest-neighbor.
I tried a build of Chromium 17 on Windows and it behaves the same way.
Firefox (8.0.1) is looking pretty promising though as it does seem to honor -moz-crisp-edges
quite well. Originally I was targeting Chrome as my "ideal browser" for this app, I might just switch over to Firefox.
In the end, it seems like proper support for image-rendering
is in the pipeline for Chrome, just not quite there yet. WebKit itself claims to fully support all image-rendering values, but I'm guessing the build of WebKit that Chrome uses hasn't quite updated to this new fix.
See Question&Answers more detail:
os