Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.09.2010, 01:27   #1
NSvirus
пропагандирую жизЪ
Форумчанин
 
Аватар для NSvirus
 
Регистрация: 19.03.2007
Сообщений: 950
По умолчанию Закрас попиксельно.

Приветствую, очень важная для меня тема.

Есть абсолютна любая фигура, есть точка внутри ее. Нужно ореентируясь от точки закрасить все что внутри фигуры.

Выполняя это задание столкнулся с небольшими проблемами.
Во первых использование массива (640, 480) - размеры экрана "великовато", во вторых производительность данного алгоритма не велика.
Вот небольшой набросок:

Код:
for N:=1 to 640 do //перебор для проверки на значения в массиве =30, если есть - точка не обрабатывается, если какое-то значение = 10 - обработка.
  begin
    for t:=1 to 480 do
    begin
      if a[N,t]=10 then
      begin
        x1:=N,x2:=N,y1:=t,y2:=t; //запись во вторичные координаты
        x1:=x1-1; //проверяем соседние координаты на наличие запретной линии
        x2:=x2+1;
        y1:=y1-1;
        y2:=y2+1;
          repeat
             f1:=Getcolor(x1,t); // проверка цвета
             f2:=getColor(x2,t);
             f3:=getColor(n,y1);
             f4:=getColor(n,y2);
             if f1=black(цвет фона)  then
                begin
                   a[x1,t]:=10; // метка перекрашенной клетки
                   putPixel(x1,t,green); 
                   x1:=x1-1; 
                end;
             if f2=black(цвет фона)  then
                begin
                   a[x2,t]:=10;
                   putPixel(x2,t,green);
                   x2:=x2+1;
                end;
             if f3=black(цвет фона)  then
                begin
                   a[n,y1]:=10;
                   putPixel(n,y1,green);
                   y1:=y1-1;
                end;
             if f4=black(цвет фона)  then
                begin
                   a[n,y2]:=10;
                   putPixel(n,y2,green);
                   y2:=y2+1;
                end;
          until not(f1=black) and not(f2=black) and not(f3=black) and not(f4=black) // пока все пути не врежутся в запретную линию
       a[N,t]=30 //обработанная точка метится для запрета последующей обработки.
end;end;end.
Нечто такое сотворил я, больше ничего придумать не смог, есть у кого идеи? Может уже существует оригинальный алгоритм без заморочек?
Изображения
Тип файла: png pix.PNG (9.8 Кб, 113 просмотров)
Посторонним В.

Последний раз редактировалось NSvirus; 14.09.2010 в 01:29.
NSvirus вне форума Ответить с цитированием
Старый 14.09.2010, 06:41   #2
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,856
По умолчанию

Цитата:
Есть абсолютна любая фигура
А как она задана? Только массив с координатами точек?
Точки расположены в случайном порядке, или в порядке следования?

Если порядок точек в массиве случайный, то результат в общем случае неопределён:

EducatedFool вне форума Ответить с цитированием
Старый 14.09.2010, 06:59   #3
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

У тебя идёт просмотр всего поля рисунка. В этом и кроется причина неэффективности алгоритма. На практике применяют способ обхода контура. От точки координат, с которой надо производить закрашивание, делается N шагов до нахождения 1-края рисунка; 2-пикселя закрашенного другим цветом. После этого, делается обход контура. Только проверок на окружение будет не 4 а 8. Поскольку закрашиваемая область всегда меньше общей площади рисунка, алгоритм работает быстрее.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 14.09.2010, 08:31   #4
puporev
Старожил
 
Регистрация: 13.10.2007
Сообщений: 2,740
По умолчанию

Не понял к чему такие мучения. Если цвет контура и цвет закраски отличаются, то рисуем фигуру цветом закраски, floodfill(), перерисовываем фигуру изначальным цветом.
puporev вне форума Ответить с цитированием
Старый 14.09.2010, 09:06   #5
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Цитата:
Сообщение от puporev Посмотреть сообщение
Не понял к чему такие мучения. Если цвет контура и цвет закраски отличаются, то рисуем фигуру цветом закраски, floodfill(), перерисовываем фигуру изначальным цветом.
А если не отличаються?
Сравнивать надо контур с цветом фона и заполнять цветом закраски.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 14.09.2010, 09:07   #6
puporev
Старожил
 
Регистрация: 13.10.2007
Сообщений: 2,740
По умолчанию

Цитата:
А если не отличаються?
Тогда просто floodfill();
puporev вне форума Ответить с цитированием
Старый 14.09.2010, 09:09   #7
puporev
Старожил
 
Регистрация: 13.10.2007
Сообщений: 2,740
По умолчанию

На всякий случай, перед floodfill нужно setfillstyle();
puporev вне форума Ответить с цитированием
Старый 14.09.2010, 09:58   #8
NSvirus
пропагандирую жизЪ
Форумчанин
 
Аватар для NSvirus
 
Регистрация: 19.03.2007
Сообщений: 950
По умолчанию

Цитата:
Тогда просто floodfill();
нет, нужно закрасить без оператора floodfill. Нужно написать алгоритм закрашивания самому.
Цитата:
А как она задана? Только массив с координатами точек?
Точки расположены в случайном порядке, или в порядке следования?
мы рисуем фигуру по формуле или обычными line.
Цитата:
У тебя идёт просмотр всего поля рисунка. В этом и кроется причина неэффективности алгоритма. На практике применяют способ обхода контура. От точки координат, с которой надо производить закрашивание, делается N шагов до нахождения 1-края рисунка; 2-пикселя закрашенного другим цветом. После этого, делается обход контура. Только проверок на окружение будет не 4 а 8. Поскольку закрашиваемая область всегда меньше общей площади рисунка, алгоритм работает быстрее.
Если пользоваться таким алгоритмом, получится(смотрим на картинку EducatedFool): находим точку - E6 и красим F6, а нам этого не нужно. + Если обход идет на 8 сторон, то выход за контур рисунка обеспечен(опять смотрим на тот же рисунок): Пусть заданная точка G9- здесь проверятся точка H8, которая тоже закрашивается, в результате - чушь.
Посторонним В.
NSvirus вне форума Ответить с цитированием
Старый 14.09.2010, 10:48   #9
Tronix
Форумчанин
 
Аватар для Tronix
 
Регистрация: 15.06.2010
Сообщений: 740
По умолчанию

Если с английским и сями дружите - то вот, вполне подробно: http://www.academictutorials.com/gra...flood-fill.asp Если скорость не нужна, то самая обычная рекурсия. Процедура в пять строк.
Чтобы понять рекурсию, сперва нужно понять рекурсию.
Tronix вне форума Ответить с цитированием
Старый 14.09.2010, 11:54   #10
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,551
По умолчанию

Набросал пример в Делфи.
Процедура заливки:
Код:
procedure TFMain.MyFill (X, Y: Integer);
var
  LX, RX: Integer;
begin
  with Canvas do
  begin
    LX := X;
    RX := X;
    while Pixels[LX,Y] = clWhite do Dec (LX);
    while Pixels[RX,Y] = clWhite do Inc (RX);
    Inc (LX);
    Dec (RX);
    MoveTo (LX, Y);
    LineTo (RX + 1, Y);
    for X := LX to RX do
    begin
      if Pixels[X,Y-1] = clWhite then MyFill (X, Y - 1);
      if Pixels[X,Y+1] = clWhite then MyFill (X, Y + 1);
    end; {for}
  end; {with}
end; {proc TFMain.MyFill}
Достаточно лобовое решение, при желании может быть оптимизировано. Но суть решения подобных задач показывает.
Можно было бы рисовать не линиями, а точками, проверяя 4 направления от каждой точки, но тогда при больших областях будет переполняться стек.

P.S. В примере: левой кнопкой мыши - рисовать, правой - заливать.
Вложения
Тип файла: rar Fill.rar (1.0 Кб, 19 просмотров)

Последний раз редактировалось Arigato; 14.09.2010 в 11:57.
Arigato вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вывод картинки попиксельно SmilingBull Мультимедиа в Delphi 6 11.01.2011 02:01
Рисовать попиксельно Ooops Софт 2 15.12.2009 10:00
Сравнение попиксельно зоны рабочего стола с указанным *.bmp Travolta Общие вопросы .NET 1 02.12.2008 13:01
Как из .BMP считать попиксельно OrdJONY Мультимедиа в Delphi 7 17.08.2008 15:46
Нужно решить и объяснить задачу "В режиме точечной графики попиксельно вывести фразу" Eyeless Фриланс 3 10.01.2008 10:56