Desafío Pintando a Nemo
#3 Solución de xergio
Ver código
|
Ver comentarios (1)
|
Descargar código
Fecha: 18 abril 2005
Tamaño: 34286 caracteres
Comentarios: 1
Solución online:
Lo siento, pero no está disponible
Valoración









8.80
(5 votos)
"No pensé que PHP sería tan lento... Ah, y creo que odio a Nemo ya ;)
He explicado el algoritmo pasito a pasito, hay casi más texto de comentarios que del resto jeje."
Valora esta solución
<?
/*************************************************************
Desafío de PHP-Hispano: Simulación de ImageFill
Sergio Álvarez (xergio) # http://xergio.net @ 18/04/05
Funcionamiento real: http://es.php.net/imagefill
Detalle del desafío: http://php-hispano.net/desafios/6
Uso de la función:
ImageFill2(recurso imagen, int x, int y, int color)
******************** ALGORITMO ********************
Bien, lo que hago es pasarle a la función un punto
inicial, y tiene que colorear del color que le digo
todos los que estén al lado de ese punto inicial y
sean del mismo color.
Lo primero que miro es el color del punto original,
el que le paso, los límites de la imágen, y creo la
cola donde guardaré los puntos que deberé colorear a
lo largo del proceso. Y claro, inicialmente meto el
punto original que le ha pasado, la X y la Y porque
debe ser pintado, como los que sean igual a él.
A partir de ese punto inicial lo que hago es trazar
horizontales hacia a derecha y hacia la izquierda,
hasta que llegue al final/principio de la imágen o
hasta un punto que tiene un color diferente al original.
Eso lo hacen los dos WHILE que hay dentro del WHILE
principal, uno se ba hacia la derecha y otro hacia la
izquierda. Aquí vamos pintando los puntos, miramos
el siguiente, pintamos, miramos, pintamos... hasta
que el que haya que pintar sea de otro color, el cual
no se pinta ya y termina por el momento.
Además de pintar dicho punto de la horizontal, lo
que hago es mirar si el punto que hay encima y debajo
deben ser pintados también, en caso afirmativo los
ponemos a la cola para que sean pintados más adelante.
De esta forma conseguimos un proceso que se repite
hasta que la cola se termine, hasta que todos los
puntos mirados sean pintados.
*****************************************************
Licencia Creative Commons con las condiciones BY-SA
http://creativecommons.org/licenses/by-sa/2.0/
Muestra: http://stuff.xergio.net/imagefill2.php
*************************************************************/
function ImageFill2(&$imagen, $x, $y, $color) {
$colorOriginal = ImageColorAt($imagen, $x, $y); // color del punto inicial
$w = ImageSX($imagen); // ancho...
$h = ImageSY($imagen); // ...y alto de la imágen
$rastreo = array(); // puntos que deberemos rellenar. Será una COLA
$rastreo[] = array($x, $y); // metemos el punto inicial que le pasamos en la cola
while (count($rastreo) > 0) { // mientras la cola no esté vacia no acabará. O dicho
// de otra forma, mientras no pinte todos los puntos...
$xy = array_shift($rastreo);// sacamos el punto que esté primero en la cola actual
$xr = $xy[0]; // cogemos XRight, el que irá hacia la derecha pintando
$xl = $xr-1; // lo mismo con XLeft, pero uno menos porque XR ya se pintó supuestamente
$y = $xy[1]; // cogemos la Y
$yu = $y+1; // y calculamos YUp, la que mirará hacia arriba
$yd = $y-1; // lo mismo con YDown, la que va hacia abajo
// esto se repite mientras el color de XR se diferente al original y esté dentro de los límites de la imágen
while (($xr+1 < $w) && (ImageColorAt($imagen, $xr, $y) == $colorOriginal)) {
ImageSetPixel($imagen, $xr, $y, $color); // BIEN!! pintamos el punto, por fin :D
if ($yu < $h) // y ahora si el punto de encima está dentro de los límites...
if (ImageColorAt($imagen, $xr, $yu) == $colorOriginal) // ... y es distinto al original
$rastreo[] = array($xr, $yu); // lo metemos en la cola, para pintarlo más adelante
if ($yd > 0) // lo mismo con el punto de debajo
if (ImageColorAt($imagen, $xr, $yd) == $colorOriginal)
$rastreo[] = array($xr, $yd);
++$xr; // pasamos al punto de al lado, uno más hacia la derecha
}
// WHILE casi idéntico al de antes, pero que va hacia la izquierda
while (($xl-1 > 0) && (ImageColorAt($imagen, $xl, $y) == $colorOriginal)) {
ImageSetPixel($imagen, $xl, $y, $color);
if ($yu < $h)
if (ImageColorAt($imagen, $xl, $yu) == $colorOriginal)
$rastreo[] = array($xl, $yu);
if ($yd > 0)
if (ImageColorAt($imagen, $xl, $yd) == $colorOriginal)
$rastreo[] = array($xl, $yd);
--$xl;
}
}
return true;
}
function _microtime() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
// cogemos una imágen y la pintamos
$microtime = _microtime();
if ($im = ImageCreateFromPNG("./nemo.png")) {
$blanco = ImageColorAllocate($im, 255, 255, 255);
$negro = ImageColorAllocate($im, 0, 0, 0);
$naranja = ImageColorAllocate($im, 255, 127, 0);
$azulito = ImageColorAllocate($im, 212, 237, 255);
$azul = ImageColorAllocate($im, 0, 127, 255);
$gris = ImageColorAllocate($im, 230, 230, 230);
$rojo = ImageColorAllocate($im, 255, 0, 0);
$grisote = ImageColorAllocate($im, 100, 100, 100);
ImageFill2($im, 200, 100, $naranja); // aleta arriba 1
ImageFill2($im, 300, 100, $naranja); // aleta arriba 2
ImageFill2($im, 350, 150, $naranja); // aleta arriba 3
ImageFill2($im, 400, 200, $naranja); // culo
ImageFill2($im, 390, 300, $azulito); // franja cuello
ImageFill2($im, 350, 460, $naranja);
ImageFill2($im, 275, 475, $naranja);
ImageFill2($im, 110, 450, $naranja); // aleta abajo izquierda
ImageFill2($im, 280, 400, $rojo); // lengua
ImageFill2($im, 250, 410, $grisote); // boca
ImageFill2($im, 60, 300, $gris); // ojo
ImageFill2($im, 200, 250, $gris); // ojo
ImageFill2($im, 200, 200, $naranja); // cara*/
//ImageFill2($im, 10, 10, $azul); // mar
//ImageFill2($im, 480, 180, $rojo); // borde
ImageString($im, 2, 5, 5, round(_microtime()-$microtime, 3)."\"", $negro);
header("Content-type: image/png");
ImagePNG($im);
ImageDestroy($im);
}
?>