Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: Animated GIF to Data URI

I am writing open-source Falloutish 2 game in PHP+HTML+CSS+JavaScript. Right now dealing with the engine. I have this gif: https://dl.dropboxusercontent.com/u/4258402/nmwarrgb_e.gif

...which I want to convert to Data URI. I need to do this because browsers cache images and this one is not looped, so in order to be able to "run it again" when animation ends and unit goes to another tile, I need to convert it to data URI. Otherwise I'd be forced to re-download image over and over again e.g. by adding random string to the end of image file. Which works fine, but takes way too much transfer and causes lag.

This is the code I tried to use:

    var image = new Image();

    (..)

    this.convertImageObjectToDataURI = function (image) {
                var canvasTemp = document.createElement('canvas');
                canvasTemp.width = image.naturalWidth; // or 'width' if you want a special/scaled size
                canvasTemp.height = image.naturalHeight; // or 'height' if you want a special/scaled size

                canvasTemp.getContext('2d').drawImage(image, 0, 0);

                var dataUri = canvasTemp.toDataURL('image/gif');

                // Modify Data URI beginning
                dataUri = "data:image/gif;" + dataUri.substring(15);
                console.log(dataUri);

                // Return image as Data URI
                return dataUri;
};

Unfortunately it produces Data URI only for the first frame. I've tried searching plugins, reading about html canvas, but still I just don't know how to convert animated gif to data URI. Any help would be very, very mich welcomed!

like image 818
Rav Avatar asked Nov 28 '15 18:11

Rav


2 Answers

It's not possible with javascript to read server files by this mode with compatibility all browsers, but I recommend you to use sprites instead of animated gifs. A sprite is a png file (that allows alpha channel) with all frames drawn separated. Imagine that file:

Dots sprite

As you can see, it's a 600x150 image (150x150 each frame, 4 frames). So you can animate with CSS animations like this:

.dots {
    width: 150px;
    height: 150px;
    background-image: url(http://i.stack.imgur.com/bCHFq.png);
    
    -webkit-animation: play .4s steps(4) infinite;
       -moz-animation: play .4s steps(4) infinite;
        -ms-animation: play .4s steps(4) infinite;
         -o-animation: play .4s steps(4) infinite;
            animation: play .4s steps(4) infinite;
}

@-webkit-keyframes play {
   from { background-position:    0px; }
     to { background-position: -600px; }
}

@-moz-keyframes play {
   from { background-position:    0px; }
     to { background-position: -600px; }
}

@-ms-keyframes play {
   from { background-position:    0px; }
     to { background-position: -600px; }
}

@-o-keyframes play {
   from { background-position:    0px; }
     to { background-position: -600px; }
}

@keyframes play {
   from { background-position:    0px; }
     to { background-position: -600px; }
}
<div class="dots"></div>

With that, you can adjust the keyframes, the velocity, the number of frames (steps), and the most important: you don't overload CPU and RAM memory in the browser client.

Good luck.

like image 89
Marcos Pérez Gude Avatar answered Nov 05 '22 15:11

Marcos Pérez Gude


I believe there is no direct way to do that using JavaScript. Using a canvas, you'd have to draw each individual frame onto it and encode them into a GIF file. This appears to be impossible using the current API as there is no way to extract single frames (except by manually parsing the GIF file).

You might succeed by downloading the binary GIF file using JavaScript (remember cross-domain restrictions of HTTP requests) and generate a base64-encoded data URL. For example, you could use this example to get an Uint8Array which you can then convert to a base64 string.

You should probably consider generating the data URLs statically, not using JavaScript. For example, you can use this shell command to generate the data URL for your gif file:

echo "data:image/gif;base64,"`curl --silent 'https://dl.dropboxusercontent.com/u/4258402/nmwarrgb_e.gif' | base64 --wrap=0`

There is also a number of online services which will generate data URLs from files.

like image 1
Tobias Avatar answered Nov 05 '22 13:11

Tobias