2008-11-08 13 views
6

Todos los programas de pintura, independientemente de cuán simples o complejos sean, vienen con una herramienta de relleno. Esto básicamente reemplaza el color de una región cerrada con otro color. Sé que hay diferentes API para hacer esto, pero estoy interesado en el algoritmo. ¿Cuál sería un algoritmo eficiente para implementar esta herramienta?¿Cómo funciona la operación de llenado en aplicaciones de pintura?

Un par de cosas que se me ocurren rápidamente son:

  1. imagen convertir en un mapa binario, donde los píxeles del color a ser reemplazados son 1 y todos los demás colores son 0.
  2. Encuentra una región cerrada alrededor del punto que desea cambiar de tal manera que todos los píxeles en el interior son 1 y todos los píxeles vecinos son 0.

Sample Image

+0

@dbr: "vecinos"? Ustedes los británicos hablan nuestro idioma gracioso. :-) ¡Título mucho mejor, sin embargo! –

Respuesta

9

Muchas implementaciones se realizan como una conquista y recursiva dividir algoritmo. Si haces un rápido Google para "algoritmo de inundación", encontrarás muchos recursos, incluida la excelente página de wikipedia en the topic.

+2

¡Dios mío, las animaciones son increíbles! Recuerdo cuando pude ** ver ** el algoritmo en Deluxe Paint en mi Amiga 500. – akuhn

+0

@akuhn O verlo durante un juego cuando juegas Scorched Earth en un 486. – DevNull

1

Si quieres un algoritmo eficiente de tiempo que no le importa muy acerca de la eficiencia de memoria, puede hacerlo a través de:

1) mantener una memoria booleano de la cual las células que ya ha visitado: Vis[]

2) mantener una lista de puntos que ya ha visitado, pero todavía no han marcado los vecinos para: Busy[]

3) comienzan ambas cosas lo más vacío

4) añadir el punto de inicio de Busy

5)

while you have a point P in Busy: 
{ 
    for each neighbour N of the point P for which Vis[N] is still false 
    { 
     if appropriate (not crossing the boundary of the fill region) 
     { 
      set Vis[N] to true 
      update the colour of N in the bitmap 
      add N to the end of Busy[] 
     } 
     remove P from Busy[] 
    } 
} 
7

El algoritmo de relleno por inundación es lo que se usa más comúnmente. La siguiente es una versión ingenua de ella hacia fuera de mi viejo libro de texto universitario, "Computer Graphics con OpenGL" por Hearn panadero, 3ª ed:

void floodFill4 (int x, int y, int fillColor, int interiorColor) 
{ 
    int color; 

    /* Set current color to fillColor, then perform the following operations */ 
    getPixel(x, y, color); 
    if (color == interiorColor) 
    { 
    setPixel(x,y); // Set color of pixel to fillColor. 
    floodFill4(x + 1, y, fillColor, interiorColor); 
    floodFill4(x - 1, y, fillColor, interiorColor); 
    floodFill4(x, y + 1, fillColor, interiorColor); 
    floodFill4(x, y - 1, fillColor, interiorColor); 
    } 
} 

Para grandes imágenes, sin embargo, lo anterior probablemente le dará una pila -el error de desbordamiento debido a la recurrencia de cada píxel. A menudo, este algoritmo se modifica para que utilice la iteración cuando se llena una fila de píxeles, y luego rellena de manera recursiva las filas arriba y abajo. Como dijo @kasperjj, wikipedia tiene un buen artículo sobre esto.

+0

¡Upmodded para mencionar el desbordamiento de pila en contexto ...! –

3

Este tipo de algoritmos se discuten en detalle en Computer Graphics: Principles and Practice. Recomiendo encarecidamente este libro si está interesado en entender cómo rastrillar líneas, rellenar polígonos, escribir códigos en 3D sin el beneficio de utilizar las API de DirectX o OpenGL. Por supuesto, para las aplicaciones del mundo real, es probable que desee utilizar las bibliotecas existentes, pero si tiene curiosidad sobre cómo funcionan estas bibliotecas, esta es una lectura impresionante.

+0

El libro que cité, "Computer Graphics with OpenGL" es también excelente para profundizar en la teoría detrás de la representación 2D y 3D y está muy bien escrito. Solo usa OpenGL para mostrar cómo se aplican algunos de los algoritmos y ecuaciones. Aunque es bastante intenso en las matemáticas. – Cybis

+0

¡Es bueno saberlo, gracias! –

1

Lea también sobre etiquetado de componentes conectados. Esta es una forma eficiente de encontrar píxeles conectados, mientras que solo visita cada píxel dos veces.

Wikipedia article.

La ventaja de esto es que los valores de píxel no tienen que ser necesariamente la misma o la función que describe píxeles como conectado podría ser algo distinto de valor en bruto - gradiente tal vez.

Cuestiones relacionadas