#!/usr/bin/env python3 """Generate the Archipelago Plymouth boot logo — pixel-art 'a' with neon glow. Outputs a 256x256 PNG with transparent background (RGBA). """ import struct import zlib import math import sys W, H = 256, 256 ORANGE = (251, 146, 60) ORANGE_BRIGHT = (255, 180, 100) # Lowercase pixel-art "a" — 6x6 grid LOGO_A = [ [0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1], [0, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 1], [0, 1, 1, 1, 1, 1], ] # "archipelago" text — same pixel font as GRUB generator PIXEL_CHARS = { 'a': [[0,1,1,0],[0,0,0,1],[0,1,1,1],[1,0,0,1],[0,1,1,1]], 'r': [[1,0,1,1],[1,1,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0]], 'c': [[0,1,1,0],[1,0,0,0],[1,0,0,0],[1,0,0,0],[0,1,1,0]], 'h': [[1,0,0,0],[1,0,0,0],[1,1,1,0],[1,0,0,1],[1,0,0,1]], 'i': [[0,1],[0,0],[0,1],[0,1],[0,1]], 'p': [[1,1,1,0],[1,0,0,1],[1,1,1,0],[1,0,0,0],[1,0,0,0]], 'e': [[0,1,1,0],[1,0,0,1],[1,1,1,0],[1,0,0,0],[0,1,1,0]], 'l': [[1,0],[1,0],[1,0],[1,0],[1,1]], 'g': [[0,1,1,1],[1,0,0,1],[0,1,1,1],[0,0,0,1],[1,1,1,0]], 'o': [[0,1,1,0],[1,0,0,1],[1,0,0,1],[1,0,0,1],[0,1,1,0]], ' ': [[0,0],[0,0],[0,0],[0,0],[0,0]], } def create_png_rgba(width, height, pixels): """Create a PNG with RGBA pixel data.""" def make_chunk(chunk_type, data): chunk = chunk_type + data return struct.pack('>I', len(data)) + chunk + struct.pack('>I', zlib.crc32(chunk) & 0xFFFFFFFF) signature = b'\x89PNG\r\n\x1a\n' ihdr_data = struct.pack('>IIBBBBB', width, height, 8, 6, 0, 0, 0) # 8-bit RGBA ihdr = make_chunk(b'IHDR', ihdr_data) raw_data = bytearray() for y in range(height): raw_data.append(0) offset = y * width * 4 raw_data.extend(pixels[offset:offset + width * 4]) compressed = zlib.compress(bytes(raw_data), 9) idat = make_chunk(b'IDAT', compressed) iend = make_chunk(b'IEND', b'') return signature + ihdr + idat + iend def generate(): pixels = bytearray(W * H * 4) # RGBA cx, cy = W // 2, W // 2 - 30 logo_rows = len(LOGO_A) logo_cols = len(LOGO_A[0]) pixel_size = 18 logo_w = logo_cols * pixel_size logo_h = logo_rows * pixel_size logo_x = cx - logo_w // 2 logo_y = 30 # Glow glow_radius = 60 for y in range(H): for x in range(W): dx = max(0, logo_x - x, x - (logo_x + logo_w)) dy = max(0, logo_y - y, y - (logo_y + logo_h)) d = math.sqrt(dx * dx + dy * dy) if d < glow_radius: alpha = (1.0 - d / glow_radius) ** 2 * 0.25 idx = (y * W + x) * 4 pixels[idx] = ORANGE[0] pixels[idx + 1] = ORANGE[1] pixels[idx + 2] = ORANGE[2] pixels[idx + 3] = int(alpha * 255) # Logo pixels with 3D bevel for row in range(logo_rows): for col in range(logo_cols): if LOGO_A[row][col]: px = logo_x + col * pixel_size py = logo_y + row * pixel_size for dy in range(pixel_size - 1): for dx in range(pixel_size - 1): x, y = px + dx, py + dy if 0 <= x < W and 0 <= y < H: t = (dx + dy) / (2 * pixel_size) r = int(ORANGE[0] * (1.0 - t * 0.3)) g = int(ORANGE[1] * (1.0 - t * 0.3)) b = int(ORANGE[2] * (1.0 - t * 0.3)) if dx < 2 or dy < 2: r = min(255, r + 40) g = min(255, g + 30) b = min(255, b + 10) idx = (y * W + x) * 4 pixels[idx] = r pixels[idx + 1] = g pixels[idx + 2] = b pixels[idx + 3] = 255 # Text "archipelago" below logo text = "archipelago" text_pixel = 3 text_gap = 2 total_w = sum(len(PIXEL_CHARS.get(c, PIXEL_CHARS[' '])[0]) * text_pixel + text_gap for c in text) - text_gap text_x = cx - total_w // 2 text_y = logo_y + logo_h + 16 cursor = text_x for ch in text: char_data = PIXEL_CHARS.get(ch, PIXEL_CHARS[' ']) for row in range(len(char_data)): for col in range(len(char_data[0])): if char_data[row][col]: for dy in range(text_pixel - 1): for dx in range(text_pixel - 1): x = cursor + col * text_pixel + dx y = text_y + row * text_pixel + dy if 0 <= x < W and 0 <= y < H: idx = (y * W + x) * 4 pixels[idx] = 180 pixels[idx + 1] = 100 pixels[idx + 2] = 30 pixels[idx + 3] = 200 cursor += len(char_data[0]) * text_pixel + text_gap return create_png_rgba(W, H, bytes(pixels)) if __name__ == '__main__': out_path = sys.argv[1] if len(sys.argv) > 1 else 'logo.png' data = generate() with open(out_path, 'wb') as f: f.write(data) print(f'Generated {out_path} ({len(data)} bytes)')