generate(361500 + $i * 97); self::zoomPixelatePortrait($tile); } $x = ($i % self::ATLAS_COLS) * self::TILE_W; $y = intdiv($i, self::ATLAS_COLS) * self::TILE_H; imagecopyresized( $atlas, $tile, $x, $y, 0, 0, self::TILE_W, self::TILE_H, imagesx($tile), imagesy($tile), ); imagedestroy($tile); } return $atlas; } /** * Keep DeepSeek's generated portrait, but make it deliberately anonymous: * crop tightly into the face, collapse it to a 10x10 source and blow it back * up with nearest-neighbour blocks. At 320x180 it reads as "Minitel rose", * not as a recognisable person. */ private static function zoomPixelatePortrait(\GdImage $im): void { $tiny = imagecreatetruecolor(10, 10); imagecopyresized($tiny, $im, 0, 0, 100, 90, 10, 10, 200, 200); imagecopyresized($im, $tiny, 50, 45, 0, 0, 300, 300, 10, 10); imagedestroy($tiny); $frame = imagecolorallocate($im, 255, 96, 160); imagerectangle($im, 48, 43, 351, 346, $frame); } private static function advertTile(int $variant): \GdImage { $im = imagecreatetruecolor(MinitelRosePoster::WIDTH, MinitelRosePoster::HEIGHT); imagealphablending($im, true); imagesavealpha($im, true); $ink = imagecolorallocate($im, 18, 10, 28); $paper = imagecolorallocate($im, 245, 214 - ($variant % 3) * 12, 70 + ($variant % 2) * 18); $pink = imagecolorallocate($im, 242, 52, 151); $cyan = imagecolorallocate($im, 55, 226, 226); $white = imagecolorallocate($im, 250, 245, 224); imagefilledrectangle($im, 0, 0, 399, 579, $paper); imagefilledrectangle($im, 14, 14, 385, 565, $ink); imagefilledrectangle($im, 26, 30, 373, 178, $pink); imagefilledrectangle($im, 26, 194, 373, 486, $white); imagefilledrectangle($im, 26, 508, 373, 536, $cyan); // The wall poster is viewed from several metres away in a 320x180 game. // Use deliberately huge bitmap typography so the gag reads immediately. self::drawTextScaled($im, 'VOTRE', 200, 62, $white, 5); self::drawTextScaled($im, 'PUB ICI', 200, 248, $ink, 5); self::drawTextScaled($im, 'EMPLACEMENT', 200, 382, $pink, 2); self::drawTextScaled($im, 'DISPONIBLE', 200, 420, $pink, 2); self::drawTextScaled($im, '3615 / RESERVE', 200, 520, $ink, 1); imagefilledrectangle($im, 38, 210, 72, 244, $cyan); imagefilledrectangle($im, 328, 438, 362, 472, $cyan); imagerectangle($im, 5, 5, 394, 574, $pink); return $im; } private static function drawTextScaled(\GdImage $im, string $text, int $cx, int $y, int $color, int $scale): void { $font = 5; $w = imagefontwidth($font) * strlen($text); $h = imagefontheight($font); $tmp = imagecreatetruecolor(max(1, $w), $h); $white = imagecolorallocate($tmp, 255, 255, 255); $black = imagecolorallocate($tmp, 0, 0, 0); imagefill($tmp, 0, 0, $white); imagestring($tmp, $font, 0, 0, $text, $black); $drawW = $w * $scale; $x0 = $cx - intdiv($drawW, 2); for ($py = 0; $py < $h; $py++) { for ($px = 0; $px < $w; $px++) { if ((imagecolorat($tmp, $px, $py) & 0xFF) < 128) { imagefilledrectangle( $im, $x0 + $px * $scale, $y + $py * $scale, $x0 + ($px + 1) * $scale - 1, $y + ($py + 1) * $scale - 1, $color, ); } } } imagedestroy($tmp); } }