index.js (2573B)
1const { noise } = require("./perlin.js"); 2const sharp = require("sharp"); 3const crypto = require("node:crypto"); 4const readline = require("node:readline").promises; 5 6const FLAG = process.env.FLAG ?? console.log("No flag") ?? process.exit(1); 7const WIDTH = 256; 8const HEIGHT = 256; 9 10console.log( 11 ` _ _ _ ____ _ 12 | \\ | | ___ (_)___ ___ / ___| ___ _ __ ___ _ __ __ _| |_ ___ _ __ 13 | \\| |/ _ \\| / __|/ _ \\ | | _ / _ \\ '_ \\ / _ \\ '__/ _\` | __/ _ \\| '__| 14 | |\\ | (_) | \\__ \\ __/ | |_| | __/ | | | __/ | | (_| | || (_) | | 15 |_| \\_|\\___/|_|___/\\___| \\____|\\___|_| |_|\\___|_| \\__,_|\\__\\___/|_| 16 ` 17); 18 19console.log(`Flag length: ${FLAG.length}`); 20console.log(`Image width: ${WIDTH}`); 21console.log(`Image height: ${HEIGHT}`); 22 23const paddedFlag = [ 24 ...crypto.randomBytes(8), // random prefix 25 ...Buffer.from(FLAG), 26 ...crypto.randomBytes(8), // random suffix 27]; 28 29// bytes_to_long 30let flagInt = 0n; 31for (const b of Buffer.from(paddedFlag)) { 32 flagInt = (flagInt << 8n) | BigInt(b); 33} 34 35const generateNoise = async (scaleX, scaleY) => { 36 const div = (x, y) => { 37 const p = 4; 38 return Number(BigInt.asUintN(32 + p, (x * BigInt(1 << p)) / y)) / (1 << p); 39 }; 40 41 const offsetX = div(flagInt, scaleX); 42 const offsetY = div(flagInt, scaleY); 43 44 noise.seed(crypto.randomInt(65536)); 45 const colors = []; 46 for (let y = 0; y < HEIGHT; y++) { 47 for (let x = 0; x < WIDTH; x++) { 48 let v = noise.perlin2(offsetX + x * 0.05, offsetY + y * 0.05); 49 v = (v + 1.0) * 0.5; // [-1, 1] -> [0, 1] 50 colors.push((v * 256) | 0); 51 } 52 } 53 54 const image = await sharp(Uint8Array.from(colors), { 55 raw: { 56 width: WIDTH, 57 height: HEIGHT, 58 channels: 1, 59 }, 60 }) 61 .webp({ lossless: true }) 62 .toBuffer(); 63 return image; 64}; 65 66const main = async () => { 67 const rl = readline.createInterface({ 68 input: process.stdin, 69 output: process.stdout, 70 terminal: false, 71 }); 72 73 const toBigInt = (value) => { 74 if (value.length > 100) { 75 console.log(`Invalid value: ${value}`); 76 process.exit(1); 77 } 78 const result = BigInt(value); 79 if (result <= 0n) { 80 console.log(`Invalid value: ${value}`); 81 process.exit(1); 82 } 83 return result; 84 }; 85 86 const query = async () => { 87 const scaleX = toBigInt(await rl.question("Scale x: ")); 88 const scaleY = toBigInt(await rl.question("Scale y: ")); 89 90 const image = await generateNoise(scaleX, scaleY); 91 console.log(image.toString("base64")); 92 }; 93 await query(); 94 95 rl.close(); 96}; 97 98main();