Skip to content

Commit

Permalink
Merge pull request antimatter15#4 from thejbw/master
Browse files Browse the repository at this point in the history
Asynchronous web worker support.
  • Loading branch information
antimatter15 committed Sep 30, 2012
2 parents 8e8b212 + e67b3ba commit efe20df
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
13 changes: 13 additions & 0 deletions GIFEncoder.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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
Expand Down
107 changes: 107 additions & 0 deletions anim.js
Original file line number Diff line number Diff line change
@@ -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(',')

}
}
}
47 changes: 47 additions & 0 deletions animWorker.js
Original file line number Diff line number Diff line change
@@ -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 efe20df

Please sign in to comment.