Skip to content

Instantly share code, notes, and snippets.

@skybldev
Last active July 14, 2019 15:32
Show Gist options
  • Save skybldev/42fcb189c3aa5545fd4830aa9a7c4f77 to your computer and use it in GitHub Desktop.
Save skybldev/42fcb189c3aa5545fd4830aa9a7c4f77 to your computer and use it in GitHub Desktop.
A JS wrapper for TheLastMillenial's TI-84+CE HDPICV image converter (version beta 2)
/**
* NAME:
* convpng.js - a JS wrapper for TheLastMillenial's TI-84+CE HDPICV image converter.
* SYNOPSIS:
* node convpng.js [OPTIONS] [SOURCE.png]
* DESCRIPTION:
* Since TLM is not as active on this project at the moment I decided to make a simple
* little wrapper for the old beta 2 version of the project. It requires Node.JS to be
* installed; apologies since JS is the language I am most proficient and fast with.
* Also, this only works on Windows.
* REQUIREMENTS:
* imagemagick https://imagemagick.org/ or package manager of choice
* nodejs https://nodejs.org/ or package manager of choice
* convpng specifically the windows_convpng.exe of beta 2 (v1.0.0-beta.2) here:
* https://github.com/TheLastMillennial/HD-Picture-Viewer/releases
* PARAMETERS:
* SOURCE.png [REQUIRED] the source image, unsplit and un-resized as this program
* uses imagemagick to do all that stuff.
* OPTIONS
* -a Appvar name. This is the calculator's version of a 'filename'. This
* script will automatically add 'L' or 'R' to it to signify which is
* the left or right half of the image. If not declared, it will be
* the same as the input filename shortened to the first 7 characters.
* NOTES:
* To make this script not too complicated and because I don't know how to implement
* space-separated argument vals, arguments are used like: -a=name, each argu-
* ment's val seprated by an equal.
* EXAMPLE:
* node convpng.js -a=FOREST forest.png
* The above example will process the image "forest.png", and output two appVars
* named "FORESTL.8xv" and "FORESTR.8xv" into the cwd.
* CREDITS:
* Thank you, Miller Medeiros for your brilliant shell helper module. Edited a bit for
* conciseness.
* https://gist.github.com/millermedeiros/4724047
* used in func execSeries
* WARNING - THE FOLLOWING CODE IS VERY DIRTY AND MAY CAUSE HEADACHES; PROCEED WITH CAUTION.
*/
var fs = require('fs');
var chp = require('child_process');
var input = process.argv.slice(2); // this trims off the first two elements we don't need.
var source;
var appVar = false;
var outHeader;
var execSeries = function(cmds, cb) {
var execNext = function() {
var parts = cmds.shift().split(/\s+/g); // splits by whitespaces.
var p = chp.spawn(parts[0], parts.slice(1), {stdio: 'inherit'});
p.on('exit', (code) => {
var err;
if(code) {
err.code = code;
err.cmd = cmds.shift();
cb(code); // cb = CallBack
} else if(cmds.length) {
execNext(); // recursion babyyyyy
} else {
cb();
}
});
};
execNext();
};
var delMultiple = function(files, cb) {
for(i = 0; i < files.length; i++) {
try { // try..catch..finally will catch errors even in sync methods rather than callbacks
fs.unlinkSync(files[i]);
} catch(err) {
cb(err);
} finally {
cb(); // I know I shouldn't be callbacking multple times but who cares
}
}
};
input.forEach((arg) => {
if(/-a=|-c|-o=/.test(arg)) { // a shortened form of "if the argument includes either of these"
var opt = arg.split('=')[0];
var val = arg.split('=')[1];
// Appvar option
if(opt == '-a' && val.length < 9) {
outHeader = val.toUpperCase();
appVar = val.toUpperCase().substring(0, 7); // shorten to the first 7 chars
} else if(opt == '-a' && val.length > 8) {
throw "Error: AppVar name must only be up to 8 characters long.";
}
} else if(fs.existsSync(arg)) { // assume that the arg without the dash is the required one
source = arg;
if(!appVar) {
outHeader = arg.split('.')[0].toUpperCase().substring(0, 8);
appVar = outHeader.substring(0, 7);
}
} else {
throw "Error: Source image not found. Make sure it is in the same directory as the conving.exe!";
}
});
execSeries([
`convert ${source} -resize 320x240 temp.png`,
'convert temp.png -crop 50%x100% crop_%d.png'
], (err) => {
if(err) throw `ImageMagick Error! Code ${err.code}`;
console.log('Successfully resized and split image.');
fs.readFile('convpng.template', 'utf8', (err, data) => {
if(err) throw `Error reading convpng: ${err}`;
var side = 0;
console.log("Successfully read the convpng template.");
var convFinal = function(data, cb) {
var sideLtr = (side == 0) ? 'L' : 'R';
var convIni = data
.replace(/@/g, `${side}`)
.replace('%', `${appVar}${sideLtr}`)
.replace('$', `${sideLtr}${outHeader.padEnd(8, '_')}`);
fs.writeFile('convpng.ini', convIni, 'utf8', (err) => {
if(err) throw `Error writing convpng: ${err}`;
console.log(`Successfully wrote ${sideLtr}-side convpng.ini.`);
chp.execFile('windows_convpng.exe', (err) => {
if(err) throw `Error executing convpng.exe: ${err}`;
console.log(`Successfully executed ${sideLtr}-side convpng.exe.`);
side++;
if(side == 1) {
convFinal(data); // recursion babyyyyy
} else {
delMultiple(['crop_0.png', 'crop_1.png', 'temp.png'], (err) => {
if(err) throw `Error cleaning up excess files: ${err}`;
});
console.log('Done.');
};
});
});
};
convFinal(data);
});
});
#GroupICE : all_gfx
#Palette : xlibc
#PNGImages :
crop_@.png
#AppvarICE : %
#OutputHeader : HDPICV2$
#PNGImages :
crop_@.png
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment