piskel/src/js/worker/ImageProcessor.js

170 lines
4.8 KiB
JavaScript
Raw Normal View History

2014-09-20 11:14:21 +04:00
(function () {
var ns = $.namespace('pskl.worker');
var worker = function () {
var postStep_ = function (step, total) {
this.postMessage({
type : 'STEP',
step : step,
total : total
});
};
var rgbToHex = function(r, g, b) {
return '#' + ((r << 16) | (g << 8) | b).toString(16);
};
2014-09-20 11:14:21 +04:00
var imageDataToGrid = function (imageData, width, height, transparent) {
// Draw the zoomed-up pixels to a different canvas context
var grid = [];
for (var x = 0 ; x < width ; x++){
grid[x] = [];
postStep_(x, (width-1)*2);
for (var y = 0 ; y < height ; y++){
// Find the starting index in the one-dimensional image data
var i = (y * width + x)*4;
var r = imageData[i ];
var g = imageData[i+1];
var b = imageData[i+2];
var a = imageData[i+3];
if (a < 125) {
grid[x][y] = transparent;
} else {
grid[x][y] = rgbToHex(r,g,b);
2014-09-20 11:14:21 +04:00
}
}
}
return grid;
};
var getColorsMapFromImageData = function (imageData, width, height) {
var grid = imageDataToGrid(imageData, width, height, 'transparent');
var colorsMap = {};
for (var i = 0 ; i < grid.length ; i++) {
var step = (grid.length-1) + i;
var total = (grid.length-1)*2;
postStep_(step, total);
for (var j = 0 ; j < grid[i].length ; j++) {
var color = grid[i][j];
if (color != 'transparent') {
colorsMap[color] = true;
}
}
}
return colorsMap;
};
this.onmessage = function(event) {
var data = event.data;
if (data.type === 'RUN_SCRIPT') {
this.importScripts(data.script);
} else {
try {
var colorsMap = getColorsMapFromImageData(data.imageData, data.width, data.height);
this.postMessage({
type : 'SUCCESS',
colorsMap : colorsMap
});
} catch(e) {
this.postMessage({
type : 'ERROR',
message : e.message
});
}
}
};
};
try {
// create worker from blob
var typedArray = [(worker+"").replace(/function \(\) \{/,"").replace(/\}[^}]*$/, "")];
var blob = new Blob(typedArray, {type: "application/javascript"}); // pass a useful mime type here
var blobUrl = window.URL.createObjectURL(blob);
} catch (e) {
console.error("Could not create worker", e.message);
}
ns.ImageProcessor = function (image, onSuccess, onStep, onError) {
this.image = image;
this.onStep = onStep;
this.onSuccess = onSuccess;
this.onError = onError;
this.worker = new Worker(blobUrl);
this.worker.onmessage = this.onWorkerMessage.bind(this);
};
ns.ImageProcessor.prototype.process = function () {
var canvas = pskl.utils.CanvasUtils.createFromImage(this.image);
var imageData = pskl.utils.CanvasUtils.getImageDataFromCanvas(canvas);
2014-09-20 11:14:21 +04:00
this.worker.postMessage({
imageData : imageData,
width : this.image.width,
height : this.image.height
});
};
ns.ImageProcessor.prototype.createNamespace = function (name) {
var createNamespace = (function () {
var parts = name.split('.');
if (parts.length > 0) {
var node = this;
for (var i = 0 ; i < parts.length ; i++) {
if (!node[parts[i]]) {
node[parts[i]] = {};
}
node = node[parts[i]];
}
}
});
var script = createNamespace + "";
script = script.replace(/function \(\) \{/,"").replace(/\}[^}]*$/, "");
script = "var name = '" + name + "';" + script;
this.runScript(script);
};
ns.ImageProcessor.prototype.onWorkerMessage = function (event) {
if (event.data.type === 'STEP') {
this.onStep(event);
} else if (event.data.type === 'SUCCESS') {
this.onSuccess(event);
this.worker.terminate();
} else if (event.data.type === 'ERROR') {
this.onError(event);
this.worker.terminate();
}
};
ns.ImageProcessor.prototype.importAll__ = function (classToImport, classpath) {
this.createNamespace(classpath);
2014-09-20 11:14:21 +04:00
for (var key in classToImport) {
if (classToImport.hasOwnProperty(key)) {
this.addMethod(classToImport[key], classpath + '.' + key);
}
}
};
ns.ImageProcessor.prototype.addMethod__ = function (method, name) {
2014-09-20 11:14:21 +04:00
this.runScript(name + "=" + method);
};
ns.ImageProcessor.prototype.runScript__ = function (script) {
2014-09-20 11:14:21 +04:00
this.worker.postMessage({
type : 'RUN_SCRIPT',
script : this.getScriptAsUrl(script)
});
};
ns.ImageProcessor.prototype.getScriptAsUrl__ = function (script) {
2014-09-20 11:14:21 +04:00
var blob = new Blob([script], {type: "application/javascript"}); // pass a useful mime type here
return window.URL.createObjectURL(blob);
};
})();