From 9e253cabc4cc4a25b33033d19a9d76d6dd8084a9 Mon Sep 17 00:00:00 2001 From: Frederic Cabassut Date: Fri, 20 Mar 2026 22:29:14 +0100 Subject: [PATCH] chore(screenshots): remove unused pixel-art generator No longer needed after removing image attachments from seed data. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/screenshots/bretzel-pixel.ts | 311 --------------------------- 1 file changed, 311 deletions(-) delete mode 100644 scripts/screenshots/bretzel-pixel.ts diff --git a/scripts/screenshots/bretzel-pixel.ts b/scripts/screenshots/bretzel-pixel.ts deleted file mode 100644 index f5706fd..0000000 --- a/scripts/screenshots/bretzel-pixel.ts +++ /dev/null @@ -1,311 +0,0 @@ -import { deflateSync } from 'zlib'; - -// Colors: [R, G, B, A] -const TRANSPARENT = [0, 0, 0, 0]; -const GOLD = [0xc8, 0x86, 0x0a, 255]; // #C8860A — bretzel body -const DARK = [0x8b, 0x69, 0x14, 255]; // #8B6914 — shading -const SALT = [0xf0, 0xe6, 0xd3, 255]; // #F0E6D3 — salt dots -const HIGHLIGHT = [0xe8, 0xa0, 0x20, 255]; // #E8A020 — highlight - -// Salt shaker colors -const SHAKER_BODY = [0xfa, 0xf5, 0xeb, 255]; // #FAF5EB — white body -const SHAKER_CAP = [0x6b, 0x62, 0x72, 255]; // #6B6272 — gray cap -const SHAKER_DOTS = [0xd4, 0xca, 0xbb, 255]; // #D4CABB — holes - -function encodePng(width: number, height: number, pixels: number[][]): Buffer { - // Build raw RGBA image data with filter byte per row - const rawData: number[] = []; - for (let y = 0; y < height; y++) { - rawData.push(0); // filter: None - for (let x = 0; x < width; x++) { - const color = pixels[y][x]; - rawData.push(color[0], color[1], color[2], color[3]); - } - } - - const compressed = deflateSync(Buffer.from(rawData)); - - // PNG signature - const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]); - - // IHDR chunk - const ihdr = createChunk('IHDR', () => { - const buf = Buffer.alloc(13); - buf.writeUInt32BE(width, 0); - buf.writeUInt32BE(height, 4); - buf[8] = 8; // bit depth - buf[9] = 6; // color type: RGBA - buf[10] = 0; // compression - buf[11] = 0; // filter - buf[12] = 0; // interlace - return buf; - }); - - // IDAT chunk - const idat = createChunk('IDAT', () => compressed); - - // IEND chunk - const iend = createChunk('IEND', () => Buffer.alloc(0)); - - return Buffer.concat([signature, ihdr, idat, iend]); -} - -function createChunk(type: string, dataFn: () => Buffer): Buffer { - const data = dataFn(); - const length = Buffer.alloc(4); - length.writeUInt32BE(data.length, 0); - - const typeBuffer = Buffer.from(type, 'ascii'); - const crcInput = Buffer.concat([typeBuffer, data]); - - const crc = Buffer.alloc(4); - crc.writeUInt32BE(crc32(crcInput), 0); - - return Buffer.concat([length, typeBuffer, data, crc]); -} - -function crc32(buf: Buffer): number { - let crc = 0xffffffff; - for (let i = 0; i < buf.length; i++) { - crc ^= buf[i]; - for (let j = 0; j < 8; j++) { - crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0); - } - } - return (crc ^ 0xffffffff) >>> 0; -} - -/** - * 64x64 pixel-art bretzel in warm browns/golds. - * Shape: classic pretzel knot with salt dots. - */ -export function generateBretzelPng(): Buffer { - const S = 64; - const pixels: number[][][] = Array.from({ length: S }, () => - Array.from({ length: S }, () => TRANSPARENT) - ); - - // Draw a pretzel shape using circles and arcs - // The bretzel is two loops connected by a twist in the center - - function setPixel(x: number, y: number, color: number[]) { - if (x >= 0 && x < S && y >= 0 && y < S) { - pixels[y][x] = color; - } - } - - function fillCircle(cx: number, cy: number, r: number, color: number[]) { - for (let y = -r; y <= r; y++) { - for (let x = -r; x <= r; x++) { - if (x * x + y * y <= r * r) { - setPixel(cx + x, cy + y, color); - } - } - } - } - - function drawRing(cx: number, cy: number, outerR: number, innerR: number, color: number[]) { - for (let y = -outerR; y <= outerR; y++) { - for (let x = -outerR; x <= outerR; x++) { - const d = x * x + y * y; - if (d <= outerR * outerR && d >= innerR * innerR) { - setPixel(cx + x, cy + y, color); - } - } - } - } - - // Main pretzel shape: two overlapping loops - // Left loop - drawRing(22, 28, 16, 11, GOLD); - // Right loop - drawRing(42, 28, 16, 11, GOLD); - - // Top arm going up to center crossing - fillCircle(32, 14, 5, GOLD); - // Connect top to loops with thicker arms - for (let y = 12; y <= 22; y++) { - const spread = Math.floor((22 - y) * 0.6); - for (let x = -3; x <= 3; x++) { - setPixel(22 + spread + x, y, GOLD); - setPixel(42 - spread + x, y, GOLD); - } - } - - // Cross-over: two diagonal arms crossing at center - for (let i = -8; i <= 8; i++) { - for (let w = -2; w <= 2; w++) { - // Left arm crosses to right bottom - setPixel(32 + i, 24 + Math.floor(i * 0.5) + w, GOLD); - // Right arm crosses to left bottom - setPixel(32 + i, 24 - Math.floor(i * 0.5) + w, GOLD); - } - } - - // Bottom connection - for (let x = 18; x <= 46; x++) { - for (let y = 40; y <= 44; y++) { - const dx = x - 32; - const distFromCenter = Math.abs(dx); - if (distFromCenter <= 14) { - setPixel(x, y, GOLD); - } - } - } - - // Add shading (darker on bottom-right edges) - for (let y = 0; y < S; y++) { - for (let x = 0; x < S; x++) { - if (pixels[y][x] === GOLD) { - // Check if near edge - let nearEdge = false; - for (const [dx, dy] of [ - [1, 0], - [0, 1], - [1, 1] - ]) { - const nx = x + dx; - const ny = y + dy; - if (nx >= S || ny >= S || pixels[ny][nx] === TRANSPARENT) { - nearEdge = true; - break; - } - } - if (nearEdge) { - setPixel(x, y, DARK); - } - } - } - } - - // Add highlight on top-left edges - for (let y = 0; y < S; y++) { - for (let x = 0; x < S; x++) { - if (pixels[y][x] === GOLD) { - let nearTopEdge = false; - for (const [dx, dy] of [ - [-1, 0], - [0, -1] - ]) { - const nx = x + dx; - const ny = y + dy; - if (nx < 0 || ny < 0 || pixels[ny][nx] === TRANSPARENT) { - nearTopEdge = true; - break; - } - } - if (nearTopEdge) { - setPixel(x, y, HIGHLIGHT); - } - } - } - } - - // Salt dots scattered on the bretzel - const saltPositions = [ - [20, 24], - [24, 20], - [28, 16], - [36, 16], - [40, 20], - [44, 24], - [24, 32], - [40, 32], - [30, 28], - [34, 28], - [26, 40], - [32, 42], - [38, 40] - ]; - for (const [sx, sy] of saltPositions) { - if (pixels[sy]?.[sx] && pixels[sy][sx] !== TRANSPARENT) { - setPixel(sx, sy, SALT); - setPixel(sx + 1, sy, SALT); - setPixel(sx, sy + 1, SALT); - } - } - - return encodePng(S, S, pixels); -} - -/** - * 32x32 pixel-art salt shaker. - */ -export function generateSaltShakerPng(): Buffer { - const S = 32; - const pixels: number[][][] = Array.from({ length: S }, () => - Array.from({ length: S }, () => TRANSPARENT) - ); - - function setPixel(x: number, y: number, color: number[]) { - if (x >= 0 && x < S && y >= 0 && y < S) { - pixels[y][x] = color; - } - } - - function fillRect(x1: number, y1: number, x2: number, y2: number, color: number[]) { - for (let y = y1; y <= y2; y++) { - for (let x = x1; x <= x2; x++) { - setPixel(x, y, color); - } - } - } - - // Cap (top section) - fillRect(11, 4, 20, 8, SHAKER_CAP); - - // Cap holes (salt comes out) - setPixel(13, 5, SHAKER_DOTS); - setPixel(16, 5, SHAKER_DOTS); - setPixel(19, 5, SHAKER_DOTS); - setPixel(14, 7, SHAKER_DOTS); - setPixel(17, 7, SHAKER_DOTS); - - // Neck - fillRect(12, 9, 19, 10, SHAKER_BODY); - - // Body (wider, tapered) - fillRect(10, 11, 21, 26, SHAKER_BODY); - - // Body shading (right edge darker) - for (let y = 11; y <= 26; y++) { - setPixel(21, y, SHAKER_DOTS); - } - - // Body outline - for (let y = 11; y <= 26; y++) { - setPixel(9, y, DARK); - setPixel(22, y, DARK); - } - for (let x = 10; x <= 21; x++) { - setPixel(x, 27, DARK); - } - - // Bottom rim - fillRect(9, 27, 22, 28, SHAKER_CAP); - - // "S" label on the body - const sPattern = [ - [14, 16], - [15, 16], - [16, 16], - [13, 17], - [14, 18], - [15, 18], - [16, 19], - [13, 20], - [14, 20], - [15, 20] - ]; - for (const [x, y] of sPattern) { - setPixel(x, y, SHAKER_CAP); - } - - // Falling salt particles - setPixel(14, 2, SALT); - setPixel(17, 1, SALT); - setPixel(19, 3, SALT); - setPixel(12, 1, SALT); - - return encodePng(S, S, pixels); -}