Files
safetynet/docs/brand/export-assets.cjs
T

43 lines
2.3 KiB
JavaScript
Raw Normal View History

2026-10-13 10:33:31 +02:00
// 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.');