Permalink
Browse files

Added Asynchronous Web Worker support (animWorker.js), modified GIFEn…

…coder.js to support animWorker and added anim.js: example code to show how to use animWorker.
  • Loading branch information...
1 parent 8e8b212 commit e67b3bad56bff73276e39b0bf77a3fe91112a31d @thejbw thejbw committed Sep 29, 2012
Showing with 167 additions and 0 deletions.
  1. +13 −0 GIFEncoder.js
  2. +107 −0 anim.js
  3. +47 −0 animWorker.js
View
13 GIFEncoder.js 100644 → 100755
@@ -298,6 +298,18 @@
}
+ var cont = exports.cont = function cont()/*Boolean*/
+ {
+
+ reset();
+ var ok/*Boolean*/ = true;
+ closeStream = false;
+ out = new ByteArray;
+
+ return started = ok;
+
+ }
+
/**
* Analyzes image colors and creates color map.
*/
@@ -534,6 +546,7 @@
var setProperties = exports.setProperties = function setProperties(has_start, is_first){
started = has_start;
firstFrame = is_first;
+ //out = new ByteArray; //??
}
return exports
View
@@ -0,0 +1,107 @@
+//This Demonstrates calling the animWorker.js web worker, allowing for non-blocking
+//Gif building.
+
+
+function animDelayValue() //Gets a user defined frame delay from user input (dom element), displays current value on dom
+{
+ var value = new Number(document.getElementById("animDelay").value/1000);
+ value.toFixed(2);
+ document.getElementById("animDelayVal").innerHTML = value;
+}
+animDelayValue(); //initialize delay value display
+this.animDelayValue = animDelayValue; //make animDelayValue global
+this.gifalizer = function() //function, called from DOM to build gif.
+{
+ function getAnimScaleFactor()
+ {
+ var autosaveElements = document.getElementsByName("animScale"); //DOM widget to set scale factor to 100%, 50% or 25%
+ var autosaveValue = "4"
+ for (var i=0; i < autosaveElements.length; i++)
+ {
+ if (autosaveElements[i].checked)
+ {
+ autosaveValue = autosaveElements[i].value;
+ break;
+ }
+ }
+ if(autosaveValue == "1")
+ {
+ return 1;
+ }
+ if(autosaveValue == "2")
+ {
+ return 2;
+ }
+ else
+ {
+ return 4;
+ }
+ }
+
+ var delay = document.getElementById("animDelay").value;
+ var scale = getAnimScaleFactor();
+
+ var animation_parts = new Array(paintedCanvases.length);
+
+ var worker = new Worker('animWorker.js');
+ //worker.onmessage = function(e)
+ //{
+ // console.log(e.data);
+ //}
+
+ //call web worker.
+ worker.onmessage = function(e)
+ {
+ //handle stuff, like get the frame_index
+ var frame_index = e.data["frame_index"];
+ var frame_data = e.data["frame_data"];
+ animation_parts[frame_index] = frame_data;
+ console.log(frame_index);
+ for(var j = 0; j < paintedCanvases.length; j++)
+ {
+ if(animation_parts[j] == null)
+ {
+ return;
+ }
+ }
+ console.log("append");
+ //check when everything else is done and then do animation_parts.join('') and have fun
+ var binary_gif = animation_parts.join('');
+ var data_url = 'data:image/gif;base64,'+window.btoa(binary_gif);
+
+ var gifItem = new Image();
+ gifItem.src = data_url;
+ var thumbs = document.getElementById("gifContainer");
+
+ //nuke all child nodes!
+ while(thumbs.hasChildNodes())
+ {
+ thumbs.removeChild(thumbs.lastChild);
+ }
+ document.getElementById("gifContainer").appendChild(gifItem);
+ }
+
+ var imageItems = new Array(); //hacky way to ensure that an arbitrary number of onload events occur.
+ //paintedCanvases is an array of canvas data generated by a canvas toDataURL calls elsewhere in the parent scope. Replicate this how you wish.
+ for(var i = 0; i < paintedCanvases.length; i++)
+ {
+ imageItems[i] = new Image();
+ imageItems[i].src = paintedCanvases[i];
+ imageItems[i].isloaded = false;
+ imageItems[i].index = i;
+ imageItems[i].onload = function()
+ {
+ var scratchCanvas = document.createElement("canvas");
+ scratchCanvas.width = comicPane.width/scale;
+ scratchCanvas.height = comicPane.height/scale;
+ var scratchCanvasContext = scratchCanvas.getContext("2d");
+ scratchCanvasContext.fillStyle = "#FFFFFF";
+ scratchCanvasContext.fillRect(0,0,scratchCanvas.width, scratchCanvas.height);
+ scratchCanvasContext.drawImage(this,0,0,scratchCanvas.width,scratchCanvas.height);
+ var imdata = scratchCanvasContext.getImageData(0,0, scratchCanvas.width, scratchCanvas.height).data;
+ console.log(this.index);
+ worker.postMessage({"frame_index": this.index, "delay": delay, "frame_length":paintedCanvases.length-1, "height":scratchCanvas.height, "width":scratchCanvas.width, "imageData":imdata}); //imarray.join(',')
+
+ }
+ }
+}
View
@@ -0,0 +1,47 @@
+importScripts('LZWEncoder.js', 'NeuQuant.js', 'GIFEncoder.js'); /* imports three scripts */
+
+self.onmessage = function(event) {
+ //console.log("message!");
+ //alert("message");
+ //self.postMessage(event.data);
+ //return;
+ var frame_index,
+ frame_length,
+ height,
+ width,
+ delay,
+ imageData; //get it from onmessage
+
+ frame_index = event.data["frame_index"];
+ frame_length = event.data["frame_length"];
+ height = event.data["height"];
+ width = event.data["width"];
+ imageData = event.data["imageData"];
+ delay = event.data["delay"];
+
+ var encoder = new GIFEncoder(); //create a new GIFEncoder for every new job
+ encoder.setRepeat(0); //0 -> loop forever
+ //1+ -> loop n times then stop
+ encoder.setQuality(1);
+ encoder.setSize(width, height);
+ encoder.setDelay(delay); //go to next frame every n milliseconds
+
+ if(frame_index == 0)
+ {
+
+ encoder.start();
+ }
+ else
+ {
+ //alert();
+ encoder.cont();
+ encoder.setProperties(true, false); //started, firstFrame
+ }
+
+ encoder.addFrame(imageData, true);
+ if(frame_length == frame_index)
+ {
+ encoder.finish();
+ }
+ self.postMessage({"frame_index":frame_index, "frame_data":encoder.stream().getData()}) //on the page, search for the GIF89a to see the frame_index
+};

0 comments on commit e67b3ba

Please sign in to comment.