Refactored some tooling.
This commit is contained in:
12
tools/utils/args.js
Normal file
12
tools/utils/args.js
Normal file
@ -0,0 +1,12 @@
|
||||
const args = process.argv.splice(2).reduce((x,y) => {
|
||||
const bits = y.split('=');
|
||||
const name = bits[0].replace('--', '');
|
||||
const val = bits[1];
|
||||
|
||||
x[name] = val;
|
||||
return x;
|
||||
}, {});
|
||||
|
||||
module.exports = {
|
||||
args
|
||||
};
|
103
tools/utils/image.js
Normal file
103
tools/utils/image.js
Normal file
@ -0,0 +1,103 @@
|
||||
const { PNG } = require("pngjs");
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
/**
|
||||
* Loads an image into memory.
|
||||
* @param image Image to load
|
||||
* @returns A promise that resolves to the loaded image.
|
||||
*/
|
||||
const imageLoad = (image) => new Promise(resolve => {
|
||||
fs.createReadStream(image)
|
||||
.pipe(new PNG({ filterType: 4 }))
|
||||
.on("parsed", function () {
|
||||
// Normalize
|
||||
const pixels = [];
|
||||
for(let y = 0; y < this.height; y++) {
|
||||
for(let x = 0; x < this.width; x++) {
|
||||
const idx = (this.width * y + x) << 2;
|
||||
const r = this.data[idx];
|
||||
const g = this.data[idx + 1];
|
||||
const b = this.data[idx + 2];
|
||||
const a = this.data[idx + 3];
|
||||
|
||||
pixels.push({ r, g, b, a });
|
||||
}
|
||||
}
|
||||
resolve({ pixels, width: this.width, height: this.height });
|
||||
})
|
||||
;
|
||||
});
|
||||
|
||||
/**
|
||||
* Writes an image to an output file.
|
||||
* @param image Image to write.
|
||||
* @param file File to write to.
|
||||
* @returns A promise that, when resolved, has saved the image.
|
||||
*/
|
||||
const imageWrite = (image, file) => new Promise(resolve => {
|
||||
const png = new PNG({ width: image.width, height: image.height });
|
||||
png.width = image.width;
|
||||
png.height = image.height;
|
||||
|
||||
for(let y = 0; y < image.height; y++) {
|
||||
for(let x = 0; x < image.width; x++) {
|
||||
const i = (image.width * y + x);
|
||||
const idx = i << 2;
|
||||
|
||||
const pixel = image.pixels[i];
|
||||
png.data[idx] = pixel.r;
|
||||
png.data[idx + 1] = pixel.g;
|
||||
png.data[idx + 2] = pixel.b;
|
||||
png.data[idx + 3] = pixel.a;
|
||||
}
|
||||
}
|
||||
|
||||
png.pack().pipe(fs.createWriteStream(file))
|
||||
.on('close', () => resolve(true))
|
||||
;
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a blank image
|
||||
* @param width Width of the image.
|
||||
* @param height Height of the image.
|
||||
* @param fill Optional pixel to fill with, defaults to 0,0,0,0
|
||||
* @returns The newly created image.
|
||||
*/
|
||||
const imageCreate = (width, height, pixel) => {
|
||||
if(!pixel || !pixel.r) pixel = { r:0, g:0, b:0, a:0 };
|
||||
const pixels = [];
|
||||
for(let i = 0; i < width * height; i++) pixels.push({ ...pixel });
|
||||
return { pixels, width, height };
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies an area of a source image into a target image.
|
||||
* @param target Target image to copy into.
|
||||
* @param source Source image to copy from.
|
||||
* @param tx Target X position to copy into
|
||||
* @param ty Target Y position to copy into
|
||||
* @param sub Optional source area to use, defined as { x, y, width, height }.
|
||||
*/
|
||||
const imageCopy = (target, source, tx, ty, sub) => {
|
||||
if(!sub) sub = { x: 0, y: 0, width: source.width, height: source.height };
|
||||
|
||||
for(let x = sub.x; x < sub.x+sub.width; x++) {
|
||||
for(let y = sub.y; y < sub.y+sub.height; y++) {
|
||||
let absX = x - sub.x + tx;
|
||||
let absY = y - sub.y + ty;
|
||||
if(absX > target.width || absY > target.height) continue;
|
||||
let ti = absY * target.width + absX;
|
||||
let si = y * source.width + x;
|
||||
target.pixels[ti] = { ...source.pixels[si] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
imageWrite,
|
||||
imageCreate,
|
||||
imageLoad,
|
||||
imageCopy
|
||||
}
|
Reference in New Issue
Block a user