Soyez le premier à donner votre avis sur cette source.
Vue 21 809 fois - Téléchargée 745 fois
<?php function decompose($a){ $b=(int)$a/256/256; $v=(int)$a/256%256; $r=(int)$a%256; return array($r, $v, $b); } function recompose($r, $v, $b){ return (($b*256+$v)*256+$r); } function colorfor($a, $x, $y, $nx, $ny, $alphabet){ $alphabetcouleursN=array(); $alphabetcouleursR=array(); $alphabetcouleursV=array(); $alphabetcouleursB=array(); $rm=0; $vm=0; $bm=0; $n=0; foreach($alphabet as $k=>$img){ $alphabetcouleursR[$k]=0; $alphabetcouleursV[$k]=0; $alphabetcouleursB[$k]=0; $alphabetcouleursN[$k]=0; } for ($i=$x*$nx;$i<($x+1)*$nx;$i++){ for ($j=$y*$ny;$j<($y+1)*$ny;$j++){ list($r, $v, $b)=decompose(imagecolorat($a, $i,$j)); $rm+=$r; $vm+=$v; $bm+=$b; $n++; $px=$i-$x*$nx; $py=$j-$y*$ny; foreach($alphabet as $k=>$img){ if (!imagecolorat($img, $px, $py)){ $alphabetcouleursR[$k]+=$r; $alphabetcouleursV[$k]+=$v; $alphabetcouleursB[$k]+=$b; $alphabetcouleursN[$k]++; } } } } $rm=intval($rm/$n); $vm=intval($vm/$n); $bm=intval($bm/$n); $car=-1; $diff=0; for($k=0;$k<sizeof($alphabet);$k++){ $alphabetcouleursR[$k]=intval($alphabetcouleursR[$k]/$alphabetcouleursN[$k]); $alphabetcouleursV[$k]=intval($alphabetcouleursV[$k]/$alphabetcouleursN[$k]); $alphabetcouleursB[$k]=intval($alphabetcouleursB[$k]/$alphabetcouleursN[$k]); $d=abs($alphabetcouleursR[$k]-$rm)+ abs($alphabetcouleursV[$k]-$vm)+ abs($alphabetcouleursB[$k]-$bm); if ($d>=$diff){ $diff=$d; $car=$k; } } $c1=recompose($rm, $vm, $bm); $c2=recompose($alphabetcouleursR[$car], $alphabetcouleursV[$car], $alphabetcouleursB[$car]); return array($c1, $c2, $car); } function tohex($a){ $hex='0123456789ABCDEF'; $C=$a%16; $B=($a-$C)/16; return ($hex{$B}.$hex{$C}); } function color($a){ list($r, $v, $b)=decompose($a); return '#'.tohex($b).tohex($v).tohex($r); } set_time_limit(0); $npx=8; $npy=15; $alphabet=array(); //ici, si vous voulez plus de caractères possibles, il faut augmenter le nombre de caractères... $alphabetstr='abcdefABCDEF0123456789-|`\_#"~@?,.;/:§!%*$&'; for ($i=0;$i<strlen($alphabetstr);$i++){ $alphabet[$i]=ImageCreateTrueColor($npx,$npy); $back = ImageColorAllocate ($alphabet[$i], 200, 200, 200); $for = ImageColorAllocate ($alphabet[$i], 0, 0, 0); ImageFilledRectangle($alphabet[$i],0, 0,$npx, $npy,$back); imagechar($alphabet[$i], 12, 0,0, $alphabetstr[$i],$for); } $a=ImageCreateFromJpeg('img.jpg'); $x=imagesX($a); $y=imagesY($a); $ncx=60; $ncy=(int)$y*$ncx/$x*$npx/$npy; $ny=$ncy*$npy; $nx=$ncx*$npx; $b=ImageCreateTrueColor($nx,$ny); ImageCopyResized($b,$a,0,0,0,0,$nx,$ny,$x,$y); imagedestroy($a); echo '<table>'; for ($y=0;$y<$ncy-1;$y++){ echo '<tr>'; for ($x=0;$x<$ncx-1;$x++){ list($c1, $c2, $c3)=colorfor($b, $x, $y, $npx, $npy, $alphabet); echo '<td style="background-color:'.color($c1).';color:'.color($c2).'">'.$alphabetstr{$c3}.'</td>'; flush(); } echo '</tr>'; } echo '</table>'; imagedestroy($b); ?>
sprintf() est certes lent, mais toujours plus rapide (à peu près 3 fois plus rapide) que ta combinaison color()=decompose()+tohex(), c'est le résultat d'un "bench" des plus basique que j'ai effectué sur 100000 itérations.
Amicalement.
90 secondes pour afficher une image de 60x60 pixels et de 1,6 KB (il s'agit en fait ton "avatar")!
Mon pc n'est pas de première jeunesse, mais quand même!
Bien que je ne sois pas sûr que ton script s'exécute correctement chez moi (par exemple certains caractères de l'"alphabet" ne s'affichent pas d'une couleur qui permette de les différencier du fond : est-ce normal?), ce qui est certain, c'est qu'il gagnerait à être optimisé.
Sur la forme,
passons vite fait sur les divisions et les multiplications par des puissances de 2 que l'on peut optimiser par des décalages avec >> et <<,
l'appel à ta fonction color() (qui fait elle appel aux fonctions decompose() et tohex()!) peut être remplacé
sans état d'âme par celui de la fonction sprintf(), certainement plus optimisée (un grand merci en passant
aux inventeurs du langage C).
ex :
color($c1)
est équivalent à :
sprintf('#%06X',$c1)
Sur le fond,
la fonction colorfor($a,$x,$y,$nx,$ny,$alphabet), qui calcule, en faisant des moyennes, la couleur pour chaque cellule de ton tableau html, est-ce qu'on obtiendrait pas la même chose en réduisant l'image, avec imagecopyresized(), directement aux dimensions $ncx et $ncy ? (et après on prendrait la couleur de chacun de ses pixels pour la reporter dans le tableau?).
Amicalement.
Un petit peu long à l'exécution sur mon poste (image de 12Ko). Mais le résultat vaut bien d'attendre 4 secondes.
Sympa également pour la pixelisation d'images.
très amusant et sympa :-)
Pour coller plus à l'esprit ascii art, je proposerais même une version en dégradés de gris, si j'étais toi.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.