Php : challenge ASCII art
J’ai fait un pari. Petit challenge à réaliser : faire un script (peu importe le langage) qui prend en paramètre un fichier image, et qui en sort de l’ASCII art.
Il faut qu’il soit rapidement paramétrable sur la taille des fontes.
Je l’ai fait « théorique » en 59 minutes, mais entièrement fonctionnel en une heure trente. J’ai fait deux scripts : un qui génère le fichier des fontes, et le principal qui lit le fichier image des fontes, et le fichier image en paramètre, et sort de l’ASCII art.
Exemple de résultat (si si c’est bien du texte, vous pouvez le sélectionner et copier coller en tant que texte !) :
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB¨ MBBBBBBMM0BBB BBBBBBBBBBBBBBBBBBBBBBBBBP'`BB ,BBBP¨ MBB BBBBBBBBBBBBBBBBBBBBBBBBB& %BMBPBBL ,a ¨BB BBBBBBBBBBBBBBBBBBBBBBBBBB jBB MBBaBBP BB BBBBBBBBBBBBBBBBBBBBBBBBPM BB ¨BBB^ , 0B BBBBBBBBBBBBBBBBBBBBBBP` BBb BB' mB jB BBBBBBB@P'BBBBBB@M@BBB mB $BK 0B jBP ¨B BBBBBBBK BBBP^` MBB dBB MBB jB ¨ L,aB B^¨ 'BBB %BB ,a BB &BBL BB Bh ,WBBBB B ¨BB jBB,mBM^ $B 'BBF BBL BBBBBBBBBB BL `BL BBBP¨ jB ^^ %B&mBBBBBBBBBBB B& w ¨& BBP wB B& wamBBBBBBBBBBBBBBB BB %w MBL BB¨ BBBwamBBBBBBBBBBBBBBBBBB BB MBw ¨BK ¨`, ,&BBBBBBBBBBBBBBBBBBBBBBB BBL BBN BB, aBBBBBBBBBBBBBBBBBBBBBBBBBBB BB& BBBh 0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBB MBBBhwmBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBB OBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Ne regardez pas la suite si vous voulez essayer de le faire pour vous !
<?php function usage_et_exit($message = '', $exit_error = -1) { global $argv; if ($message != '') { echo $message."\n"; } echo $argv[0]." {image gif reference} {image noir et blanc jpg}\n"; exit($exit_error); } function noir_ou_blanc($r, $g, $b) { /* http://stackoverflow.com/questions/254388/how-do-you-convert-an-image-to-black-and-white-in-php */ if (((0.299*$r) + (0.587*$g) + (0.114*$b))> 0x7F) { return 0xFFFFFF; } else { return 0x000000; } } function cherche_meilleure_correspondance( $img_src, $x, $y, $img_fonts, $font_size, $tab_base ) { $meilleur = -1; $retour = ''; foreach ($tab_base as $idx => $ch) { $match = 0; for ($t_y=0; $t_y<$font_size; $t_y++) { for ($t_x=0; $t_x<$font_size; $t_x++) { if (imagecolorat($img_src, $t_x+$x, $t_y+$y) != imagecolorat( $img_fonts, ($idx*$font_size) + $t_x, $t_y ) ) { $match++; } } } if ($match>$meilleur) { $retour = $ch; $meilleur = $match; } } return $retour; } function convert_img_noir_et_blanc($filename, $img) { list($width, $height, $type, $attr) = getimagesize($filename); /* Conversion en noir et blanc */ for ($y=0; $y<$height; $y++) { for ($x=0; $x<$width; $x++) { $rgb = imagecolorat($img, $x, $y); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; $nb = noir_ou_blanc($r, $g, $b); imagesetpixel($img, $x, $y, $nb); } } } $tab_base = array( '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', '\'', ',', ';', ':', '?', '.', '/', '!', '%', '^', '¨', '$', '~', '#', '(', ')', '[', ']', '|', '-', '`', ' ' ); $font_size = 14; $min_width = 400; $min_height = 400; if ($argc!=3) { usage_et_exit("Arguments invalides", -1); } $img_tmp = imagecreatefromstring(file_get_contents($argv[1])); $width = imagesx($img_tmp); $height = imagesy($img_tmp); $img_fonts = imagecreatetruecolor($width, $height); imagecopy($img_fonts, $img_tmp, 0, 0, 0, 0, $width, $height); imagedestroy($img_tmp); unset($img_tmp); if ($img_fonts===false) { usage_et_exit("Erreur chargement de ".$argv[1], -1); } /* Conversion en noir et blanc des fontes */ convert_img_noir_et_blanc($argv[1], $img_fonts); imagepng($img_fonts, './resultat_fonts.png', 0); list($width, $height, $type, $attr) = getimagesize($argv[2]); if ($width<$min_width) { usage_et_exit("Largeur trop petite de ".$argv[1].", taille min = ".$width_min, -1); } if ($width<$min_height) { usage_et_exit("Hauteur trop petite de ".$argv[1].", taille min = ".$width_min, -1); } $img_src = imagecreatefromjpeg($argv[2]); if ($img_src===false) { usage_et_exit("Erreur chargement de ".$argv[2], -1); } convert_img_noir_et_blanc($argv[2], $img_src); /* Ok on a l'image en noir et blanc. Parcourir toute l'image */ imagepng($img_src, './resultat_noir_et_blanc.png', 0); $y = 0; $max_result = 0; while (($y + $font_size) < $height) { $x = 0; while (($x + $font_size) < $width) { echo cherche_meilleure_correspondance( $img_src, $x, $y, $img_fonts, $font_size, $tab_base ); $x += $font_size; } echo "\n"; $y += $font_size; } echo "Done.\n"; ?>
Et le fichier qui génère les fontes (22 minutes de perdues à le faire…) :
<?php $tab_base = array( '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', '\'', ',', ';', ':', '?', '.', '/', '!', '%', '^', '¨', '$', '~', '#', '(', ')', '[', ']', '|', '-', '`', ' ' ); $x=0; $font_size = 14; $width = count($tab_base)*$font_size; echo 'width='.var_export($width,true)."\n"; $height = $font_size*4; $img = imagecreatetruecolor($width, $height); if ($img===false) { throw new Exception("Erreur"); } imagefilledrectangle($img, 0, 0, $width, $height, 0xFFFFFF); foreach ($tab_base as $idx => $char) { $ok = imagettftext( $img, $font_size, 0, $idx * $font_size, $font_size, 0x000000, './consola.ttf', $char ); } imagegif($img, './test.gif'); echo "Done.\n"; ?>