19

Is it possible to detect animated gif images client side?

In Internet Explorer you can use the onload event for this, since it willl be fired for every frame loaded (behaviour changed in IE8).

But is there a way for other browsers too?

doekman
  • 18,750
  • 20
  • 65
  • 86

2 Answers2

15

I just wrote some JS that detects animated gifs. Works in most modern browsers except IE 9.

Disclaimer: this only works if the domain origin of the image is the same as the page you are loading the script from.

See the gist for the latest version of the code: https://gist.github.com/3012623

function isAnimatedGif(src, cb) {
    var request = new XMLHttpRequest();
    request.open('GET', src, true);
    request.responseType = 'arraybuffer';
    request.addEventListener('load', function () {
        var arr = new Uint8Array(request.response),
            i, len, length = arr.length, frames = 0;

        // make sure it's a gif (GIF8)
        if (arr[0] !== 0x47 || arr[1] !== 0x49 || 
            arr[2] !== 0x46 || arr[3] !== 0x38)
        {
            cb(false);
            return;
        }

        //ported from php http://www.php.net/manual/en/function.imagecreatefromgif.php#104473
        //an animated gif contains multiple "frames", with each frame having a 
        //header made up of:
        // * a static 4-byte sequence (\x00\x21\xF9\x04)
        // * 4 variable bytes
        // * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?)
        // We read through the file til we reach the end of the file, or we've found 
        // at least 2 frame headers
        for (i=0, len = length - 9; i < len, frames < 2; ++i) {
            if (arr[i] === 0x00 && arr[i+1] === 0x21 &&
                arr[i+2] === 0xF9 && arr[i+3] === 0x04 &&
                arr[i+8] === 0x00 && 
                (arr[i+9] === 0x2C || arr[i+9] === 0x21))
            {
                frames++;
            }
        }

        // if frame count > 1, it's animated
        cb(frames > 1);
    });
    request.send();
}
lakenen
  • 3,436
  • 5
  • 27
  • 39
  • What if all frames have identical data? Then the gif will be detected as being animated while actually it's not. A foolproof (but more expensive) solution would be to actually compare frame data until you find two which actually differ. – Gautam Mar 13 '15 at 11:06
  • Good point @Gautam I'd be interested in seeing an implementation if you do! – lakenen Mar 13 '15 at 19:19
  • Haha, don't hold your breath :) That was meant as something to consider for someone thinking about using this function. I don't foresee myself implementing it any time soon... – Gautam Mar 16 '15 at 07:57
  • Shouldn't it be `i < len && frames < 2`? – josephrider Dec 16 '19 at 17:15
  • I can confirm that it should indeed be `i < len && frames < 2`, otherwise my browser crashed when checking a non-anim gif file. – Michael Rupp Jul 04 '20 at 10:52
0

I don't know of any way to do it on the client side, but I am not sure about that. What you could do, is parsing the HTML code and any referenced gif on the server side and add a class to these images. But that is not really recommended because it involves at least one additional parsing of HTML + parsing of every gif. As you can see from this example in PHP, checking the gifs is also not trivial in terms of CPU load.

Residuum
  • 11,878
  • 7
  • 40
  • 70
  • I agree with Residuum, I don't think there's any way to do this in javascript – Josh Aug 25 '09 at 19:26
  • I thought, maybe something is possible with the Canvas-API. Just sample an image every x milliseconds, and calculate a hash of the image. Not too reliable, but it could work... – doekman Aug 27 '09 at 13:40