44 lines
2.3 KiB
JavaScript
44 lines
2.3 KiB
JavaScript
// Deterministic export of the generated master artwork. No redraw or substitute mark.
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const { PNG } = require('pngjs');
|
|
const root = __dirname;
|
|
const source = PNG.sync.read(fs.readFileSync(path.join(root, 'safetynet-lockup.png')));
|
|
// A neutral opaque presentation keeps the navy wordmark legible in dark README viewers.
|
|
const readme = new PNG({ width: source.width, height: source.height });
|
|
for (let i = 0; i < source.data.length; i += 4) {
|
|
const alpha = source.data[i + 3] / 255;
|
|
for (let c = 0; c < 3; c++) readme.data[i + c] = Math.round(source.data[i + c] * alpha + 250 * (1 - alpha));
|
|
readme.data[i + 3] = 255;
|
|
}
|
|
fs.writeFileSync(path.join(root, 'safetynet-readme.png'), PNG.sync.write(readme));
|
|
// The original symbol occupies the first 560 px. Keep its actual transparent edges.
|
|
const symbol = new PNG({ width: 640, height: 640 });
|
|
symbol.data.fill(0);
|
|
for (let y = 0; y < 640; y++) for (let x = 0; x < 560; x++) {
|
|
const from = ((y + 60) * source.width + x) * 4;
|
|
source.data.copy(symbol.data, (y * 640 + x + 40) * 4, from, from + 4);
|
|
}
|
|
fs.writeFileSync(path.join(root, 'safetynet-icon.png'), PNG.sync.write(symbol));
|
|
// PNG-compressed 256px Windows icon with box-filter downsampling.
|
|
const icon = new PNG({ width: 256, height: 256 });
|
|
for (let y = 0; y < 256; y++) for (let x = 0; x < 256; x++) {
|
|
let a = 0; const rgb = [0, 0, 0]; let n = 0;
|
|
for (let sy = Math.floor(y * 2.5); sy < Math.ceil((y + 1) * 2.5); sy++)
|
|
for (let sx = Math.floor(x * 2.5); sx < Math.ceil((x + 1) * 2.5); sx++) {
|
|
const offset = (sy * 640 + sx) * 4; const alpha = symbol.data[offset + 3];
|
|
a += alpha; n++;
|
|
for (let c = 0; c < 3; c++) rgb[c] += symbol.data[offset + c] * alpha;
|
|
}
|
|
const offset = (y * 256 + x) * 4;
|
|
for (let c = 0; c < 3; c++) icon.data[offset + c] = a ? Math.round(rgb[c] / a) : 0;
|
|
icon.data[offset + 3] = Math.round(a / n);
|
|
}
|
|
const encoded = PNG.sync.write(icon);
|
|
const header = Buffer.alloc(22);
|
|
header.writeUInt16LE(1, 2); header.writeUInt16LE(1, 4);
|
|
header.writeUInt16LE(1, 10); header.writeUInt16LE(32, 12);
|
|
header.writeUInt32LE(encoded.length, 14); header.writeUInt32LE(22, 18);
|
|
fs.writeFileSync(path.join(root, 'safetynet.ico'), Buffer.concat([header, encoded]));
|
|
console.log('Exported README presentation, original symbol PNG and 256px Windows ICO.');
|