Created
October 20, 2021 19:54
-
-
Save Fordi/88fea5af78586d43838312d296187f20 to your computer and use it in GitHub Desktop.
node script to convert an image into a spritesheet C++ header suitable for picosystem
This file contains 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
#!/usr/bin/env node | |
const getPixels = require('get-pixels'); | |
const { basename } = require('path'); | |
const { writeFile } = require('fs/promises'); | |
const pixels = async src => new Promise((resolve, reject) => { | |
getPixels(src, (err, pixels) => { | |
if (err) return reject(err); | |
return resolve(pixels); | |
}); | |
}); | |
const spriteSize = [8, 8]; | |
const inputFile = process.argv[2]; | |
if (!inputFile) { | |
console.error(`Usage: ${basename(process.argv[1])} [imageFile]`); | |
console.log('Converts an image file to a 16-bit RGBA/4444 little-endian array of words in an C++ header file'); | |
console.log('You can enable the sheet using `use_{filename-sans-extension}()`.'); | |
console.log('e.g., for `mysptires.png`, you\'ll have a `use_mysprites()` function'); | |
process.exit(-1); | |
} | |
const outputFile = `${inputFile.replace(/\.[^\.]+$/, '')}.hpp`; | |
const varName = basename(outputFile, '.hpp').toLowerCase(); | |
const pragmaName = basename(outputFile).toUpperCase().replace(/\W+/g, '_'); | |
(async () => { | |
const buf = []; | |
const px = await pixels(inputFile); | |
const [width, height] = px.shape; | |
const [across, down] = [width / spriteSize[0], height / spriteSize[1]]; | |
buf.push( | |
`#ifndef ${pragmaName}`, | |
`#define ${pragmaName}`, | |
'#include "picosystem.hpp"', | |
`const color_t _sheet_${varName}[${width * height}] = {` | |
); | |
console.log(`Creating spritesheet with ${across *down} sprites`); | |
for (let sy = 0; sy < down; sy++) { | |
for (let sx = 0; sx < across; sx++) { | |
for (let y = 0; y < spriteSize[1]; y++) { | |
const lbuf = []; | |
for (let x = 0; x < spriteSize[0]; x++) { | |
const lx = sx * spriteSize[0] + x; | |
const ly = sy * spriteSize[1] + y; | |
const r = Math.round(px.get(lx, ly, 0) * 15 / 255); | |
const g = Math.round(px.get(lx, ly, 1) * 15 / 255); | |
const b = Math.round(px.get(lx, ly, 2) * 15 / 255); | |
const a = Math.round(px.get(lx, ly, 3) * 15 / 255); | |
const c = g << 12 | b << 8 | a << 4 | r; | |
lbuf.push(`0x${c.toString(16).padStart(4, '0')}`); | |
} | |
buf.push(`\t${lbuf.join(', ')}${y === spriteSize[y] - 1 && sy === across - 1 ? '' : ','}`); | |
} | |
if (sy !== across - 1) buf.push(''); | |
} | |
} | |
buf.push( | |
'};', | |
'', | |
`inline void use_${varName}() {`, | |
` spritesheet(buffer(${spriteSize[0]}, ${spriteSize[1] * across * down}, (void*) _sheet_${varName}));`, | |
`}` | |
); | |
buf.push( | |
'#endif', | |
'' | |
); | |
await writeFile(outputFile, buf.join('\n'), { encoding: 'utf8' }); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment