|
Canvas:
A checkered image is drawn onto a Canvas to
extract the image's colors using getImageData()
The Extracted Pixels should read values alternating between
(0,0,0) (black) and (255,0,255) (pink).
This currently fails in all major MacOS Browsers (Safari, Chrome, Firefox) on HiDPI displays.
Safari on a Retina MacBook Pro will automatically double the canvas size behind the
scenes (backingStoreRatio = 2) but pretend it's still the same. When drawing an
image to this double size canvas it will get interpolated (blurred). Then, when extracting
the pixels from the image using getImageData(), Safari will scale the canvas down
again, blurring the image once again. The result is unpredictable pixel puree.
Bug ID: 12310706 / screenshot
Even though Chrome 25 doesn't support HiDPI for the Canvas element (everything else on the page does)
and it supports imageSmoothingEnabled, it is completely ignored for the 2x
retina scaling. This makes sense from an implementation standpoint, as the Canvas element essentially
get's scaled up after rendering. This explains why the resulting Canvas looks mushed, the pixel
data returned from getImageData() is still correct.
The CSS image-rendering property should be supported here.
Firefox 17 doesn't support HiDPI at all. The whole page is rendered in normal resolution. Yet,
the 2x scaling that MacOS does after rendering the page, still manages to affect the Canvas element somehow.
The rendered Canvas looks exactly like it should, but Update: the PNG file had an ICC color profile embeded.
I was (wrongfully) under the impression that these were ignored in modern browsers.
The result in FF17 is correct.
getImageData() returns the wrong result.
I have no idea what's going on here. It still works fine on a non-retina display. The planned HiDPI support
should fix this.
With this bug, you can't extract the original colors from an image. This is bad for all kinds of applications that want to analyze image data. The effect is most noticable in games and apps that try to present or work with pixel style images, like this scaling algorithm.
There is a possible solutions to make this all work on Safari 6 again: drawing at half
the size to the canvas (in reality that's at full size then) and extracting the
real pixels using the Apple's new getImageDataHD().
This solution is extremely ugly to implement and complicates a lot of previously very simple use cases for the Canvas element.
A better solution would be setting the context's imageSmoothingEnabled to
false for a doubled backing store or support for the CSS
image-rendering property for an undoubled backing store.
imageSmoothingEnabledimage-rendering propertyCurrently, scaling pixel art in a cross browser way is extremely difficult. It's getting easier in Chrome and Firefox, but Safari makes things more complicated yet again. You can read a bit more about this whole issue in my blog.