Wednesday, March 4th, 2009

Detect if the browser supports APNG

Category: Canvas, JavaScript, Library


  1. (function(_global) {
  3.   var apng_test = new Image(),
  5.   canvas = document.createElement("canvas"),
  7.   ctx = canvas.getContext("2d");
  9.   apng_test.src = "apng-test.png"; // a data URI will cause a security error so you _have_ to link to external resource
  11.   // frame 1 (skipped on apng-supporting browsers): 0,0,0,255
  12.   // frame 2: 0,0,0,0
  13.   apng_test.onload = function() {
  15.     ctx.drawImage(apng_test, 0, 0);
  17.     _global.apng_supported = ( ctx.getImageData(0, 0, 1, 1).data[3] == 0 );
  19.   }
  20. })(this);

The code above, written by Elijah Grey, will detect if a browser supports APNG or not. You can see a demo of it in action. Armed with this info you can choose whether to send down GIF files or APNGs.

Why the apng-test image? Elijah lays it out:

Due to a stupid restriction of on loading image data from an image that uses a data URI you will need to download apng-test.png and put its location in the script.

Posted by Dion Almaer at 7:00 am

2.9 rating from 28 votes


Comments feed TrackBack URI

The security violation raised when trying to import a data URI image into a Canvas may be annoying but it is not a stupid restriction. It is a necessary security and privacy measure.

Comment by p01 — March 4, 2009

@p01: Do you have any link for that? Or perhaps a more elaborate explanation?

Comment by Joeri — March 4, 2009

Is the assumption that a browser that doesn’t support canvas also doesn’t support APNG? Because that’s just wrong.

Comment by MrMoo — March 4, 2009

Is the assumption that a browser that doesn’t support canvas also doesn’t support APNG? Because that’s just wrong.

No. The code (and inline comments) suggest that you use the canvas to detect whether or not the browser supports APNGs. By testing the color of a particular pixel at a particular time, you can detect if the image moved to the second frame or not.

Comment by 0x336699 — March 4, 2009

You dont need to do this at all. Just create PNG-8 files that degrade well in IE6.

Comment by GlenLipka — March 4, 2009

@GlenLipka RTFA, this has nothing to do with IE6. Not even IE8 supports this.

Comment by EliGrey — March 4, 2009

Sorry, my bad. Was reading a bit too quickly.

Comment by GlenLipka — March 4, 2009

My point was that in browsers that don’t support canvas (IE) the code will throw an error. IE7 “supports” 32-bit PNGs but not canvas (I say “supports” because as soon as you apply any kind of transparency on them things get nasty).

Comment by MrMoo — March 5, 2009

And by transparency I mean opacity. And by opacity, in IE, I mean the Alpha filter. Which inevitably ends with using the AlphaImageLoader filter, so perhaps “supports” is too strong a word.

Comment by MrMoo — March 5, 2009

@MrMoo APNG is animated PNG. IE does not support anything of the sort.
As of yet, there are no browsers that support APNG and not canvas so no worries.

Comment by EliGrey — March 5, 2009

Aah. I interpreted that as Alpha PNGs – as in 32-bit PNGs. I didn’t even think of Animated PNGs. My bad, and you have my apologies. I still think that tossing an error in IE is bad.

Comment by MrMoo — March 5, 2009

I don’t see how banning dataURI imports into Canvas changes the security dynamics, since I can parse a dataURI in Javascript, compute the pixel data, and rasterize it into the Canvas using normal draw operations (e.g. fillRect)

For example, if I was doing an XSS attack against you, by retrieving a GIF from a domain you were logged into which contains you bank account credentials embedded in the image, then it makes sense to mark the canvas dirty with cross domain images. However, if I were to instead, somehow retrieve a dataURI from the XSS site, there is nothing you could do to stop me. I wouldn’t even need to use the Canvas, the mere position of the dataURI is enough. I could then post it to any URL I own and decode it locally on my desktop.

The banning of dataURIs seems like security through obscurity.

Comment by cromwellian — March 5, 2009

Huh, that seems kind of a roundabout way of detecting APNG support. A more surefire way seems to be this:

Comment by PacoBell — March 19, 2009

Leave a comment

You must be logged in to post a comment.