Contacto | #php_para_torpes | Enlázanos | ¿Quiénes somos?
15 usuarios Online (0)
Darse de alta en la web | Recuperar password   
Inicio / Desafios / Pintando a Nemo / Solucion de xergio

Desafío Pintando a Nemo

#3 Solución de xergio

Código de la Solución Ver código | Comentarios Ver comentarios (1) | Descargar Descargar código

Fecha: 18 abril 2005

Tamaño: 34286 caracteres

Comentarios: 1

Solución online:
Lo siento, pero no está disponible

Valoración PuntuaciónPuntuaciónPuntuaciónPuntuaciónPuntuaciónPuntuaciónPuntuaciónPuntuaciónPuntuaciónPuntuació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);
}

?>

Web alojada en Zilos

php-hispano.net 2002 - 2008 | XHTML 1.0
Datos Legales | Webmaster