1401a61e7Swikidesign<?php 21affe9b7Swikidesign/** 3*6e2b7c94Snerun * MonsterID Generator for DokuWiki Avatar Plugin 4*6e2b7c94Snerun * 5*6e2b7c94Snerun * Generates identicon-style monster avatars based on a seed. 6*6e2b7c94Snerun * Requires PHP GD extension. 7*6e2b7c94Snerun * 81affe9b7Swikidesign * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 91affe9b7Swikidesign * @author Andreas Gohr <andi@splitbrain.org> 10*6e2b7c94Snerun * @author Daniel Dias Rodrigues <danieldiasr@gmail.com> (modernization) 111affe9b7Swikidesign */ 12401a61e7Swikidesign 13*6e2b7c94Snerundeclare(strict_types=1); 14*6e2b7c94Snerun 15*6e2b7c94Snerunif (php_sapi_name() !== 'cli') { 16*6e2b7c94Snerun $seed = preg_replace('/[^a-f0-9]/i', '', $_GET['seed'] ?? ''); 17*6e2b7c94Snerun $size = (int) ($_GET['size'] ?? 120); 18*6e2b7c94Snerun $size = max(20, min(512, $size)); // limits between 20 and 512 pixels 19*6e2b7c94Snerun 20*6e2b7c94Snerun header('Content-Type: image/png'); 21*6e2b7c94Snerun header('Cache-Control: public, max-age=86400'); 22*6e2b7c94Snerun 23*6e2b7c94Snerun $image = generate_monster($seed, $size); 24*6e2b7c94Snerun if ($image) { 25*6e2b7c94Snerun imagepng($image); 26*6e2b7c94Snerun imagedestroy($image); 27*6e2b7c94Snerun } else { 28*6e2b7c94Snerun http_response_code(500); 29*6e2b7c94Snerun echo 'Erro ao gerar imagem.'; 30*6e2b7c94Snerun } 31*6e2b7c94Snerun exit; 32*6e2b7c94Snerun} 33401a61e7Swikidesign 341affe9b7Swikidesign/** 35*6e2b7c94Snerun * Generates monster image based on seed and size 361affe9b7Swikidesign */ 37*6e2b7c94Snerunfunction generate_monster(string $seed, int $size): ?GdImage 38*6e2b7c94Snerun{ 39*6e2b7c94Snerun if (!function_exists('imagecreatetruecolor')) { 40*6e2b7c94Snerun return null; 41*6e2b7c94Snerun } 42*6e2b7c94Snerun 432e0c1c6eSGina Haeussge $hash = md5($seed); 44401a61e7Swikidesign 45*6e2b7c94Snerun $parts = [ 46*6e2b7c94Snerun 'legs' => get_part(substr($hash, 0, 2), 1, 5), 47*6e2b7c94Snerun 'hair' => get_part(substr($hash, 2, 2), 1, 5), 48*6e2b7c94Snerun 'arms' => get_part(substr($hash, 4, 2), 1, 5), 49*6e2b7c94Snerun 'body' => get_part(substr($hash, 6, 2), 1, 15), 50*6e2b7c94Snerun 'eyes' => get_part(substr($hash, 8, 2), 1, 15), 51*6e2b7c94Snerun 'mouth' => get_part(substr($hash, 10, 2), 1, 10), 52*6e2b7c94Snerun ]; 53401a61e7Swikidesign 54*6e2b7c94Snerun $monster = imagecreatetruecolor(120, 120); 55*6e2b7c94Snerun if (!$monster) return null; 56*6e2b7c94Snerun 57401a61e7Swikidesign $white = imagecolorallocate($monster, 255, 255, 255); 58401a61e7Swikidesign imagefill($monster, 0, 0, $white); 59401a61e7Swikidesign 60*6e2b7c94Snerun foreach ($parts as $part => $index) { 61*6e2b7c94Snerun $filename = __DIR__ . '/parts/' . $part . $index . '.png'; 62*6e2b7c94Snerun if (!file_exists($filename)) continue; 63*6e2b7c94Snerun $part_img = imagecreatefrompng($filename); 64*6e2b7c94Snerun if ($part_img) { 65*6e2b7c94Snerun imagecopy($monster, $part_img, 0, 0, 0, 0, 120, 120); 66*6e2b7c94Snerun imagedestroy($part_img); 67401a61e7Swikidesign } 68401a61e7Swikidesign } 69401a61e7Swikidesign 70*6e2b7c94Snerun if ($size !== 120) { 71*6e2b7c94Snerun $resized = imagecreatetruecolor($size, $size); 72*6e2b7c94Snerun imagefill($resized, 0, 0, $white); 73*6e2b7c94Snerun imagecopyresampled($resized, $monster, 0, 0, 0, 0, $size, $size, 120, 120); 74401a61e7Swikidesign imagedestroy($monster); 75*6e2b7c94Snerun return $resized; 76401a61e7Swikidesign } 772e0c1c6eSGina Haeussge 78*6e2b7c94Snerun return $monster; 792e0c1c6eSGina Haeussge} 802e0c1c6eSGina Haeussge 81*6e2b7c94Snerun/** 82*6e2b7c94Snerun * Converts part of the hash into an image index 83*6e2b7c94Snerun */ 84*6e2b7c94Snerunfunction get_part(string $hex, int $min, int $max): int 85*6e2b7c94Snerun{ 86*6e2b7c94Snerun $val = hexdec($hex); 87*6e2b7c94Snerun return ($val % ($max - $min + 1)) + $min; 88401a61e7Swikidesign} 8923415f0dSnerun 90