Справочник функций

Ваш аккаунт

Логин:
Пароль:
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:
Убрать блок ВКонтакте навсегда

Последние темы форума

Показать новые сообщения »

Почтовая рассылка



Подписчиков: 19017
Последний выпуск: 23.04.2012

Заливка замкнутой области

Пример показывает один из самых простых и эффективных способов заливки. Использовать его в таком варианте не рекомендую, рисовать на TImage->Canvas довольно медленно, но в качестве примера очень удобно.

Процедура последовательно просматривает соседние точки, и если они не залиты, то заливает и добавляет 4 соседние точки в очередь, на рассмотрение. И так пока очередь не кончится.

На рисунке черными стрелками показаны точки, которые будут добавлены в очередь для просмотра, а красными, которые не будут добавлены, так как уже залиты.

Теперь собственно - исходник. (Borland C++ Builder). На форме достаточно иметь TImage - Image1.

void ImageFill(short x, short y, TColor color) {
    // Получим размеры изображения
    int imw=Form1->Image1->Width;
    int imh=Form1->Image1->Height;
    // Выделим памяти для складирования координат, которые еще предстоит залить
    int STACK_SIZE=(imw+2)*(imh+2);
    short *floodfill_stackx=(short*)malloc(STACK_SIZE*sizeof(short));
    short *floodfill_stacky=(short*)malloc(STACK_SIZE*sizeof(short));
    if (floodfill_stacky==NULL || floodfill_stackx==NULL) return;
    int stack_head=0;
    int stack_tail=0;
    TColor clr=Form1->Image1->Canvas->Pixels[x][y];
    floodfill_stackx[stack_head]=x;
    floodfill_stacky[stack_head]=y;
    Form1->Image1->Canvas->Pixels[x][y]=color;
    stack_head++;
    // Пока не кончится память или точки на изображении
    while (stack_head<STACK_SIZE && stack_head>stack_tail) {
        x=floodfill_stackx[stack_tail];
        y=floodfill_stacky[stack_tail];
        stack_tail++;
        if (x>=0 && y>=0 && x<imw && y<imh) {
            // Проверим точку справа, если она не залита, то зальем
	        if (Form1->Image1->Canvas->Pixels[x+1][y]==clr) {
                floodfill_stackx[stack_head]=x+1;
            	floodfill_stacky[stack_head]=y;
                Form1->Image1->Canvas->Pixels[x+1][y]=color;
            	stack_head++;
                }
            // Проверим точку слева, если она не залита, то зальем
            if (Form1->Image1->Canvas->Pixels[x-1][y]==clr) {
                floodfill_stackx[stack_head]=x-1;
    	        floodfill_stacky[stack_head]=y;
                Form1->Image1->Canvas->Pixels[x-1][y]=color;
            	stack_head++;
                }
            // Проверим точку снизу, если она не залита, то зальем
            if (Form1->Image1->Canvas->Pixels[x][y+1]==clr) {
                floodfill_stackx[stack_head]=x;
                floodfill_stacky[stack_head]=y+1;
                Form1->Image1->Canvas->Pixels[x][y+1]=color;
            	stack_head++;
                }
            // Проверим точку сверху, если она не залита, то зальем
            if (Form1->Image1->Canvas->Pixels[x][y-1]==clr) {
                floodfill_stackx[stack_head]=x;
                floodfill_stacky[stack_head]=y-1;
                Form1->Image1->Canvas->Pixels[x][y-1]=color;
            	stack_head++;
                }
            }
        }
    Form1->Image1->Canvas->TextOutA(1,1,IntToStr(stack_head));
    // Освободим память
    free(floodfill_stacky);
    free(floodfill_stackx);
    }

void __fastcall TForm1::Button1Click(TObject *Sender) {
    Image1->Canvas->Ellipse(20,20,300,200);
    ImageFill(1,1,0xFF0000);
    }

Оставить комментарий

Оставлять комментарии могут только зарегистрированные пользователи.

Если вы не являетесь зарегистрированным пользователем, то вам необходимо зарегистрироваться. Регистрация бесплатна. Если вы уже зарегистрированы на CodeNet, то вам необходимо ввести логин и пароль в верхней (Alt-U) части страницы.

Комментарии

1. dark_barker / 17 марта 2006, 22:46:05
Мне нравитсяМне не нравится

Ах да, скажу - неизбежно будет переполнение стека (который таки переполнится несмотря на проверку stack_head<STACK_SIZE, поглядите внимательно). Почему? А потому, что признаком конца псевдоитерации служит считанный цвет и при равных цветах распространение всегда будет во все четыре стороны и алгоритм вообще никогда не остановится.
з.ы. if(clr==color)return; надо поставить первой строкой, чтобы зря не выделять и не удалять память.

2. dark_barker / 17 марта 2006, 22:10:49
Мне нравитсяМне не нравится

Мало того, что алгоритм ужасен в неэффективности, так ещё и... вот подумайте, что будет, если заливать область тем же цветом, что и сама область! Подумали?
А теперь ОБЯЗАТЕЛЬНО вставьте проверку if(clr==color)return;
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог