File: vince.c - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off


#include <stdlib.h>
#include <string.h>

/*
** D�finition des notions d'image et de pixel ; tout ceci peut �tre remplac�
** en fonction de la plate-forme cible (que je ne connais pas), la seule
** contrainte est de disposer de fonctions "GetPixel" et "SetPixel"
** quelconques sur une image.
*/


typedef struct
{
    unsigned char   r;
    unsigned char   g;
    unsigned char   b;
} Color;

typedef struct
{
    unsigned int    width;
    unsigned int    height;
    Color*          pixels;
} Image;

void    imageGet (Image* image, unsigned int x, unsigned y, Color** color)
{
    *color = &image->pixels[x + image->width * y];
}

void    imageSet (Image* image, unsigned int x, unsigned y, Color* color)
{
    Color*  pixel = &image->pixels[x + image->width * y];

    pixel->r = color->r;
    pixel->g = color->g;
    pixel->b = color->b;
}

/*
** D�finition d'une pile de coordonn�es et des op�rations habituelles dessus,
** pour remplacer la r�cursivit�.
*/


typedef struct
{
    unsigned int    x;
    unsigned int    y;
} Location;

typedef struct
{
    unsigned int    capacity;
    unsigned int    count;
    Location*       items;
} Stack;

void    stackCreate (Stack* stack)
{
    stack->capacity = 0;
    stack->count = 0;
    stack->items = NULL;
}

void    stackDelete (Stack* stack)
{
    if (stack->items)
        free (stack->items);
}

int stackPop (Stack* stack, unsigned int* x, unsigned int* y)
{
    Location*   top;

    if (stack->count < 1)
        return 0;

    top = &stack->items[--stack->count];
    *x = top->x;
    *y = top->y;

    return 1;
}

int stackPush (Stack* stack, unsigned int x, unsigned int y)
{
    unsigned int    capacity;
    Location*       items;
    Location*       top;

    if (stack->count >= stack->capacity)
    {
        capacity = stack->capacity * 2 + 1;
        items = realloc (stack->items, capacity * sizeof (*stack->items));

        if (!items)
            return 0;

        stack->capacity = capacity;
        stack->items = items;
    }

    top = &stack->items[stack->count++];
    top->x = x;
    top->y = y;

    return 1;
}

/*
** Le remplissage en lui-m�me.
** image:   image source (� adapter � la plate-forme, cf. plus haut)
** x:       coordonn�e X de d�part du remplissage
** y:       coordonn�e Y de d�part du remplissage
** color:   couleur de remplissage (� adapter �galement)
*/


void floodFill (Image* image, unsigned int x, unsigned int y, Color* color)
{
    Color*  pixel;
    Stack   stack;

    stackCreate (&stack);
    stackPush (&stack, x, y);

    while (stack.count > 0)
    {
        stackPop (&stack, &x, &y);
        imageGet (image, x, y, &pixel); // � remplacer par GetPixel

        if (color->r != pixel->r || color->g != pixel->g || color->b != pixel->b)
        {
            if (x > 0)
                stackPush (&stack, x - 1, y);

            if (x + 1 < image->width)
                stackPush (&stack, x + 1, y);

            if (y > 0)
                stackPush (&stack, x, y - 1);

            if (y + 1 < image->height)
                stackPush (&stack, x, y + 1);

            imageSet (image, x, y, color); // � remplacer par SetPixel
        }
    }

    stackDelete (&stack);
}