This commit is contained in:
juliandescottes 2015-04-13 11:45:50 +02:00
parent 5d4b8b87a3
commit 0e817a88a7
4 changed files with 87 additions and 21 deletions

View File

@ -5,6 +5,7 @@
var MAX_GIF_COLORS = 256; var MAX_GIF_COLORS = 256;
var MAX_EXPORT_ZOOM = 20; var MAX_EXPORT_ZOOM = 20;
var DEFAULT_EXPORT_ZOOM = 10; var DEFAULT_EXPORT_ZOOM = 10;
var MAGIC_PINK = '#FF00FF';
ns.GifExportController = function (piskelController) { ns.GifExportController = function (piskelController) {
this.piskelController = piskelController; this.piskelController = piskelController;
@ -115,19 +116,24 @@
}; };
ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(zoom, fps, cb) { ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(zoom, fps, cb) {
var colorCount = pskl.app.currentColorsService.getCurrentColors().length; var currentColors = pskl.app.currentColorsService.computeCurrentColors();
var preserveColors = colorCount < MAX_GIF_COLORS;
var preserveColors = currentColors.length < MAX_GIF_COLORS;
var transparentColor = this.getTransparentColor(currentColors);
var gif = new window.GIF({ var gif = new window.GIF({
workers: 5, workers: 5,
quality: 1, quality: 1,
width: this.piskelController.getWidth() * zoom, width: this.piskelController.getWidth() * zoom,
height: this.piskelController.getHeight() * zoom, height: this.piskelController.getHeight() * zoom,
preserveColors : preserveColors preserveColors : preserveColors,
transparent : parseInt(transparentColor, 16)
}); });
for (var i = 0; i < this.piskelController.getFrameCount(); i++) { for (var i = 0; i < this.piskelController.getFrameCount(); i++) {
var frame = this.piskelController.getFrameAt(i); var frame = this.piskelController.getFrameAt(i);
var canvasRenderer = new pskl.rendering.CanvasRenderer(frame, zoom); var canvasRenderer = new pskl.rendering.CanvasRenderer(frame, zoom);
canvasRenderer.drawTransparentAs(transparentColor);
var canvas = canvasRenderer.render(); var canvas = canvasRenderer.render();
gif.addFrame(canvas.getContext('2d'), { gif.addFrame(canvas.getContext('2d'), {
delay: 1000 / fps delay: 1000 / fps
@ -147,6 +153,17 @@
gif.render(); gif.render();
}; };
ns.GifExportController.prototype.getTransparentColor = function(currentColors) {
var transparentColor = pskl.utils.ColorUtils.getUnusedColor(currentColors);
if (!transparentColor) {
console.error('Unable to find unused color to use as transparent color in the current sprite');
transparentColor = MAGIC_PINK;
} else {
transparentColor = window.tinycolor(transparentColor).toHexString();
}
return transparentColor;
};
// FIXME : HORRIBLE COPY/PASTA // FIXME : HORRIBLE COPY/PASTA
ns.GifExportController.prototype.updateStatus_ = function (imageUrl, error) { ns.GifExportController.prototype.updateStatus_ = function (imageUrl, error) {

View File

@ -32,6 +32,30 @@
} }
}; };
ns.CurrentColorsService.prototype.computeCurrentColors = function (max) {
var layers = this.piskelController.getLayers();
var frames = layers.map(function (l) {return l.getFrames();}).reduce(function (p, n) {return p.concat(n);});
var colors = {};
frames.forEach(function (f) {
var frameColors = this.cachedFrameProcessor.get(f);
Object.keys(frameColors).slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED).forEach(function (color) {
colors[color] = true;
});
}.bind(this));
// Remove transparent color from used colors
delete colors[Constants.TRANSPARENT_COLOR];
var colorsArray = Object.keys(colors);
// limit the array to the max colors to display
if (max) {
colorsArray = colorsArray.slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED);
}
return this.colorSorter.sort(colorsArray);
};
ns.CurrentColorsService.prototype.isCurrentColorsPaletteSelected_ = function () { ns.CurrentColorsService.prototype.isCurrentColorsPaletteSelected_ = function () {
var paletteId = pskl.UserSettings.get(pskl.UserSettings.SELECTED_PALETTE); var paletteId = pskl.UserSettings.get(pskl.UserSettings.SELECTED_PALETTE);
var palette = this.paletteService.getPaletteById(paletteId); var palette = this.paletteService.getPaletteById(paletteId);
@ -48,24 +72,7 @@
}; };
ns.CurrentColorsService.prototype.updateCurrentColors_ = function () { ns.CurrentColorsService.prototype.updateCurrentColors_ = function () {
var layers = this.piskelController.getLayers(); var currentColors = this.computeCurrentColors(Constants.MAX_CURRENT_COLORS_DISPLAYED);
var frames = layers.map(function (l) {return l.getFrames();}).reduce(function (p, n) {return p.concat(n);});
var colors = {};
frames.forEach(function (f) {
var frameColors = this.cachedFrameProcessor.get(f);
Object.keys(frameColors).slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED).forEach(function (color) {
colors[color] = true;
});
}.bind(this));
// Remove transparent color from used colors
delete colors[Constants.TRANSPARENT_COLOR];
// limit the array to the max colors to display
var colorsArray = Object.keys(colors).slice(0, Constants.MAX_CURRENT_COLORS_DISPLAYED);
var currentColors = this.colorSorter.sort(colorsArray);
this.setCurrentColors(currentColors); this.setCurrentColors(currentColors);
}; };

View File

@ -0,0 +1,41 @@
(function () {
var ns = $.namespace('pskl.utils');
ns.ColorUtils = {
getUnusedColor : function (usedColors) {
// start with white
var color = {
r : 255,
g : 255,
b : 255
};
// create check map
var colorMap = {};
usedColors.forEach(function (color) {
colorMap[color.toUpperCase()] = true;
});
var match = null;
while (true) {
var hex = tinycolor(color).toHexString().toUpperCase();
if (!colorMap[hex]) {
match = color;
break;
} else {
// pick a non null component to decrease its value
var component = (color.r && 'r') || (color.g && 'g') || (color.b && 'b');
if (component) {
color[component] = color[component] - 1;
} else {
// no component available, no match found
break;
}
}
}
return match;
}
};
})();

View File

@ -15,6 +15,7 @@
"js/utils/Base64.js", "js/utils/Base64.js",
"js/utils/BlobUtils.js", "js/utils/BlobUtils.js",
"js/utils/CanvasUtils.js", "js/utils/CanvasUtils.js",
"js/utils/ColorUtils.js",
"js/utils/DateUtils.js", "js/utils/DateUtils.js",
"js/utils/Dom.js", "js/utils/Dom.js",
"js/utils/Event.js", "js/utils/Event.js",