Last active
May 28, 2017 11:03
-
-
Save AdmiralPotato/83f5ed4f4bacd1c64293680345749f38 to your computer and use it in GitHub Desktop.
Sometimes Photoshop is a damn fool and you need an export process that sucks less at color palette selection and dithering.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//REQUIREMENTS: The following programs must be installed and accessible in your PATH | |
// node > 6 | |
// imagemagick's command line tool "convert" | |
// giflossy - which can be installed with `npm install -g giflossy`, but only on mac and linux?? | |
//USAGE: Change params at the top to your liking. `node gif_process.js` starts it up. | |
// EXECUTES ALL TASKS IN PARALEL. | |
// If you run it like this, it will CONSUME YOUR WHOLE COMPUTER (100% cpu, 100% memory) for a few minutes while it works. | |
//DISCLOSURE: I was running terribly low on sleep when I wrote this. It's a tool. It gets a job done like ten times ever. Don't judge me on this. The code I write for my day job is like way better and I care a lot more about it because I have to maintain it all the time. | |
//LICENSE: MIT | |
let imPath = 'script_output-imagemagick/'; | |
let gsPath = 'script_output-giflossy/'; | |
let seriesName = 'electric_flower'; | |
let inputPngFolderList = [ | |
'08-comp_a', | |
]; | |
let outputParams = [ //<-- only do like 1 set at a time for sanity | |
{width: 1920, height: 1080}, | |
{width: 1080}, | |
{width: 960, height: 540, lossy: 10}, | |
{width: 480, lossy: 10}, | |
{width: 480, height: 270, lossy: 5}, | |
{width: 400, colors: 128, lossy: 35}, | |
{width: 400, height: 225, colors: 256, lossy: 5}, | |
]; | |
let sourceWidth = 1920; | |
let sourceHeight = 1080; | |
let sourceAspect = sourceWidth / sourceHeight; | |
let backgroundColor = '#000000'; | |
/*------------------------------------------------*/ | |
const fs = require('fs'); | |
const child_process = require('child_process'); | |
let makePath = function(path){ | |
if(!fs.existsSync(path)){ | |
fs.mkdirSync(path); | |
} | |
}; | |
makePath(imPath); | |
makePath(gsPath); | |
let timeTask = function(taskName, callback){ | |
var start = Date.now(); | |
return function(err, stdout, stderr) { | |
var time = (Date.now() - start); | |
console.log([taskName, stdout, time, 'ms'].join(' ').replace(/\n/g, ' ')); | |
if (err) { | |
console.error(err); | |
return; | |
} else if(callback) { | |
callback(); | |
} | |
}; | |
}; | |
let hellYeahGifProcess = function(x, y, scale, c, l){ | |
let width = x; | |
let height = y || x; | |
let resize = scale || width > height ? width : height; | |
let colors = c || 256; | |
let lossy = l || 0; | |
let targetAspect = width / height; | |
let leftRight = (width - resize) / 2; | |
let topBottom = (height - resize) / 2; | |
let scaledCount = 0; | |
let sourceCropWidth = Math.ceil(targetAspect * sourceHeight); | |
let sourceCropHeight = Math.ceil((targetAspect * sourceHeight) / targetAspect); | |
let leftRightCrop = (sourceWidth - sourceCropWidth) / 2; | |
let topBottomCrop = (sourceHeight - sourceCropHeight) / 2; | |
let crop = `-crop ${sourceCropWidth}x${sourceCropHeight}+${leftRightCrop}+${topBottomCrop}`; | |
let dimensionsLabel = `${width}x${height}`; | |
if(scale){ | |
dimensionsLabel += `x${scale}`; | |
} | |
if(c){ | |
dimensionsLabel += `-colors_${c}`; | |
} | |
let imSizePath = imPath + dimensionsLabel + '/'; | |
let gsSizePath = gsPath + dimensionsLabel + '/'; | |
makePath(imSizePath); | |
makePath(gsSizePath); | |
let imList = []; | |
let gsList = []; | |
let gifSicleImagesWhenDone = function(){ | |
imList.forEach(function(outputFileNameIM, index){ | |
let outputFileNameGS = gsList[index]; | |
let lossyArg = lossy ? `--lossy=${lossy}` : ''; | |
child_process.exec( | |
[ | |
'giflossy', | |
'-O3', | |
lossyArg, | |
`-o ${outputFileNameGS}`, | |
outputFileNameIM | |
].join(' '), | |
timeTask(outputFileNameGS) | |
); | |
}); | |
}; | |
let onComplete = function(){ | |
scaledCount++; | |
if(scaledCount === inputPngFolderList.length){ | |
gifSicleImagesWhenDone(); | |
} | |
}; | |
inputPngFolderList.forEach(function(inputFileName){ | |
let name = `${seriesName}-${inputFileName}-${dimensionsLabel}`; | |
let nameLossy = lossy ? `-lossy_${lossy}` : ''; | |
name += '-imagemagick'; | |
let outputFileNameIM = imSizePath + name + '.gif'; | |
let outputFileNameGS = gsSizePath + name + `-giflossy${nameLossy}.gif`; | |
let argument = [ | |
'convert', | |
'-dispose 2', | |
'-delay 1/24', | |
inputFileName + '/*.png', | |
'-coalesce', | |
crop, | |
'-resize ' + resize, | |
`-background "${backgroundColor}"`, | |
'-alpha remove', | |
`-bordercolor "${backgroundColor}"`, | |
//`-border ${leftRight}x${topBottom}`, | |
'-dither FloydSteinberg', | |
//'-ordered-dither o8x8,64', | |
//'-ordered-dither o2x2,128,128,64', | |
//'-ordered-dither checks,128', | |
`-colors ${colors}`, | |
'+repage', | |
outputFileNameIM | |
].join(' '); | |
console.log(argument); | |
imList.push(outputFileNameIM); | |
gsList.push(outputFileNameGS); | |
child_process.exec( | |
argument, | |
timeTask(outputFileNameIM, onComplete) | |
); | |
}); | |
}; | |
outputParams.forEach(function(params){ | |
hellYeahGifProcess(params.width, params.height, params.resize, params.colors, params.lossy); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment