Как закрасить пиксель в c

Обновлено: 06.07.2024

Загрузка. Пожалуйста,
подождите.

Репутация: нет
Всего: -1

Репутация: 55
Всего: 459

гениальность идеи состоит в том, что ее невозможно придумать

Репутация: 4
Всего: 12

Репутация: 5
Всего: 128

Добавлено через 11 секунд

Репутация: 55
Всего: 459

гениальность идеи состоит в том, что ее невозможно придумать

Репутация: 5
Всего: 128

Цитата(msdn)
After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released .

вот интересно, GetDC(0) какой контекст возвращает? видимо common

p.s. это всеголишь пример. для его использования надо немного головой еще подумать) например проверить результат возвращаемый функциями. в try..finally поместить для порядку и т.п.

Репутация: 55
Всего: 459

MetalFan, главное что ReleaseDC вернула 1, значит все выполнилось верно.

Добавлено @ 13:04
Интересно другое, что TCanvas.Destroy этого не делает . Видимо в делфях за это отвечает окно владелец.

гениальность идеи состоит в том, что ее невозможно придумать

Репутация: нет
Всего: -1

procedure TForm1.Timer1Timer(Sender: TObject);
var
C : TCanvas;
p:tpoint;
begin
GetCursorPos(p);
C := TCanvas.Create;
C.Handle := GetDC(0);
c.Pixels[p.X,p.Y]:=clRed;
c.Free;
end;

за курсором остаётся красный след. но через некоторое время вылазит ошибка, так как память, выделяемая под программу постоянно растёт, и видимо переполняется. как этого избежать?
и как сделать след мыши равномерным, а не отдельными точками, тобиш как избавиться от таймера?

Репутация: 55
Всего: 459

Модератор: используйте подсветку кода

Попробуйте сначала код

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

гениальность идеи состоит в том, что ее невозможно придумать

Репутация: 4
Всего: 12

Репутация: 5
Всего: 128

а смысл создавать объект TCanvas только для установки цвета одного пикселя?!

Репутация: 55
Всего: 459

MetalFan, объектный подход, унификация, да и возможности для дальнейшего развития.

гениальность идеи состоит в том, что ее невозможно придумать

Репутация: 5
Всего: 128

Alexeis, все должно быть в разумных пределах. а если ненужно дальнейшее расширение? в обчем вопрос имхо спорный в данном случае

Репутация: 55
Всего: 459

гениальность идеи состоит в том, что ее невозможно придумать

Репутация: 1
Всего: 9

1. Публиковать ссылки на вскрытые компоненты

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

FAQ раздела лежит здесь!

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

[ Время генерации скрипта: 0.1449 ] [ Использовано запросов: 21 ] [ GZIP включён ]

Image I

Для использования в CodeBlocks я нашел это (вы должны добавить опцию компоновщика -lgdi32):
// Блоки кода: параметры сборки проекта Параметры компоновщика Опции компоновщика Othoer: add -lgdi32

Код всего косинуса снова. Готов к компиляции

ответил(а) 2016-12-09T14:42:00+03:00 4 года, 11 месяцев назад

Это зависит от вашей ОС. Я предполагаю, что вы программируете на платформе Windows, поэтому вы можете использовать SetPixel, но вам нужно использовать "windows.h" для получения дескриптора консоли, поэтому здесь приведен пример рисование функции cos():

Вы также можете использовать некоторые другие библиотеки, такие как: conio.h allegro.h sdl и т.д.

Если вы хотите, чтобы изображение выглядело нечетким, вы могли бы воспользоваться символами блока из кодовой страницы консоли.

    █ = '\ xDB' = U + 2588 FULL BLOCK
    ▄ = '\ xDC' = U + 2584 LOWER HALF BLOCK
    ▀ = '\ xDF' = U + 2580 UPPER HALF BLOCK
    и пробел

Используя полублоки в сочетании с цветным текстом, вы можете превратить консольное окно 80 и times; 25 в 80-кратное и 50-цветное 16-цветные дисплеи. (Это был подход, используемый QBasic-версией Nibbles.)

Затем вам просто нужно преобразовать изображение в 16-цветную палитру и достаточно маленький размер.

Mario in 8 lines and 10 columns of

windows.h предоставляет функцию SetPixel() для печати пикселя в указанном месте окна. Общий вид функции

где, x и y - координаты пикселя для отображения, а цвет - цвет пикселя.

Важно. Чтобы напечатать пиксель на вашем компьютере с помощью Code:: blocks IDE, добавьте библиотеку ссылок libgdi32.a (обычно внутри MinGW\lib ) в настройках компоновщика.

Я нарисовал прямую линию, используя windows.h в code:: blocks. Я не могу объяснить это подробно, но я могу предоставить вам код и процедуру для его компиляции в code:: blocks.

    перейдите в меню настроек и выберите компилятор и отладчик.
    Перейдите на вкладку компоновщика и добавьте библиотеку ссылок libgdi32.a, которая находится в каталоге C:\Program Files\CodeBlocks\MinGW\lib.

Скомпилируйте эту программу

В этой программе я использовал алгоритм рисования линии DDA. Задачи рисования пикселей выполняются функцией setPixel (ROUND (x), ROUND (y)).
Это программа Windows, в которой вы можете узнать подробности здесь

Консоль - это текстовое устройство, поэтому, как правило, вы не записываете отдельные пиксели. Вы можете создать специальный шрифт и выбрать его как шрифт для консоли, но он будет монохроматическим. Существуют библиотеки, которые упрощают создание пользовательского интерфейса консоли управления (например, Curses), но я считаю, что у вас также есть более функциональная функциональность, а просто показывается спрайт.

Если вы хотите написать игру, я предлагаю взглянуть на некоторые из графических/игровых фреймворков /libs, например. SDL

image


Заливка изображений — часто нужная на практике задача, суть которой — заполнить некоторую область изображения, ограниченную контуром, заданным цветом. И казалось бы все просто, однако часто медленно и криво. В данной статье рассказывается об известных алгоритмах заливки на основе стека и приводится реализация на псевдокоде MatLab. Я постарался наполнить столь скучную тему интересными видео роликами, и описал процесс их получения, опять же с использованием MatLab. В этой статье мы будем заливать Карлсона который живет на крыше, так как хабралоготипа для этих целей в нормальном разрешении я не нашел. А так же несколько строк кода о том как читать и работать с картинками в MatLab.

Предварительные сведения и предпосылки


Простым путем введем на упорядоченном наборе пар координат отношение связности или соседства. Будем различать случаи, когда точка имеет четыре соседа (Рис.1а) и случай когда у точки восемь соседей (Рис.1б).

image


Зачем это делать и что выбрать показано на рисунке 2.

image

На рисунке 2 квадратики изображают условные пиксели цифрового изображения, при этом черные пиксели описывают границу между двумя областями — верхней и нижней. Будем заливать верхнюю белую область синей краской. В случае если мы вводим только 4 соседа для точки, то синяя краска через черную границу не пройдет (Рис.2б) и нижняя область останется белой, а если использовать уже восемь соседей, то черная граница и не граница вовсе, а решето — через которое и проливается краска в нижнюю область.

Какой вид связности выбрать? На плоскости выбор небольшой — либо 4 либо 8 соседей и выбор зависит от постановки исходной задачи, однако в многомерном пространстве все сложнее, даже представить невозможно, и в статье мы рассмотрим лишь плоский случай. При этом будем рассматривать случай четырех соседей, который простым образом распространяется и на случай восьми.

image

Все заметили, что картинка Карлсона, раскрашенная по моему вкусу и представлению в Paint, в аннотации статьи, залита как — то криво, на границе черный контур — цветная область — есть белые и серые, бросающиеся в глаза точки? Это произошло по той причине, что наш Карлсон совсем не в бинарном цвете а в градациях серого. Первым делом уберем этот вопиющий недостаток и бинаризуем картинку, при этом нам достаточно работать только с одним каналом — пусть будет первый — красный.
Итак:

% //Прочитаем исходную картинку
source_image = imread( 'karlson.bmp' );
% // Взьмем из нее только первый канал
gray_image = source_image(. 1);
% // Бинаризуем с порогом 0.5
bim=double(im2bw(gray_image, 0.5));
% // Покажем картинку
imagesc(bim);

* This source code was highlighted with Source Code Highlighter
  • Стартовая точка — пиксель в котором пользователь нажал подобно Point банкой с краской
  • Старый цвет — цвет заливаемой области
  • Новый цвет — цвет области после заливки.

Простой и медленный алгоритм заливки


Края изображения будем так же считать границей изображения.
Суть алгоритма проста: в текущей точке проверяем: если старый цвет — заменяем его на новый, если новый, то ничего не делаем. Затем выполняем эту же операцию для четырех соседей у которых цвет равен старому цвету.
Позволю себе один раз украсть исходный код, с рекурсивной реализацией, лишь для демонстрации сути:

//Recursive 4-way floodfill, crashes if recursion stack is full
void floodFill4( int x, int y, int newColor, int oldColor)
<
if (x >= 0 && x < w && y >= 0 && y < h && screenBuffer[x][y] == oldColor && screenBuffer[x][y] != newColor)
<
screenBuffer[x][y] = newColor; //set color before starting recursion

floodFill4(x + 1, y, newColor, oldColor);
floodFill4(x - 1, y, newColor, oldColor);
floodFill4(x, y + 1, newColor, oldColor);
floodFill4(x, y - 1, newColor, oldColor);
>
>
* This source code was highlighted with Source Code Highlighter

.
Как это будет выглядеть на Matlab да еще с имитацией стека? А вот как:

%Прочитаем исходную картинку
source_image = imread( 'karlson.bmp' );
% Взьмем из нее только первый канал
gray_image = source_image(. 1);
% Бинаризуем с порогом 0.5
bim= double (im2bw(gray_image, 0.5));
% Покажем картинку
imagesc(bim);

newColor = 0.5; oldColor = 1;
point.x = 48; point.y = 234;
stack = [point];
[w h] = size(bim);
stack_size = [];
mov = avifile( 'karlson_fill2.avi' , 'fps' ,50);
figure;
while (length(stack)

=0)
point = stack(1);
stack(1) = []; % Удаляем закрашенную точку из стека
bim(point.x,point.y) = newColor; %Закрашиваем текущую точку

if (point.x+1 <= w && bim(point.x+1,point.y) == oldColor)
newpoint.x = point.x+1;
newpoint.y = point.y;
stack = [stack newpoint];
end;
if (point.x-1 > 0 && bim(point.x-1,point.y) == oldColor)
newpoint.x = point.x-1;
newpoint.y = point.y;
stack = [stack newpoint];
end;
if (point.y+1 <= h && bim(point.x,point.y+1) == oldColor)
newpoint.x = point.x;
newpoint.y = point.y+1;
stack = [stack newpoint];
end;
if (point.y-1 > 0 && bim(point.x,point.y-1) == oldColor)
newpoint.x = point.x;
newpoint.y = point.y-1;
stack = [stack newpoint];
end;
stack_size = [stack_size length(stack)];
imagesc(bim); colormap gray; axis image;
F = getframe(gca); mov = addframe(mov,F);
end;
mov = close(mov);
figure; imagesc(bim);
figure; plot(stack_size);

* This source code was highlighted with Source Code Highlighter

.
Можно сходить попить чаю, пока бровь нашего шалопая раскрашивается в серый цвет. При этом предлагаемый код нам еще и график заполненности стека на каждой итерации нарисует и мы его обсудим. А как приятный бонус кода — на выходе еще и видео ролик иллюстрирующий заполнение. Почему я выбрал такую маленькую деталь как бровь — потому что залить что-то другое, например пузо, учитывая особенности исполняемого языка Matlab, не представляется возможным за конечное время.


Собственно вот какие у нас результаты получились: График заполненности стека приведен в логарифмических координатах на рисунке 5.
А голова с раскрашенной бровью изображена на рисунке 6. Видео иллюстрирующее процесс заполнения области предлагается к просмотру ниже. Все говорит нам о том, что алгоритм работает крайне медленно, посмотрите на рисунке 5 (по оси X — номер итерации, по оси Y — количество еще необработанных точек) как медленно опустошается стек (учтите логарифмические координаты), а дело все в том, что происходит слишком много лишних проверок точек. Те точки которые были залиты на предыдущем этапе все равно проверяются на следующем. Конечно же это никуда не годится. Далее мы устраним эту несправедливость! Видео файл — 50 кадров в секунду.

Алгоритм заливки — быстрый, линиями

Суть рекурсивного алгоритма:
Начинаем заполнять текущую линию от одного края до другого.
Вначале вверх из стартовой точки а затем вниз.
Возвращаемся в стартовую точку. Смотрим — если слева от стартовой точки старый цвет и нет границы, то выполняем заполнение новой линии.
Возвращаемся в стартовую точку. Смотрим — если справа от стартовой точки старый цвет и нет границы, то выполняем заполнение новой линии.

clear all;
%Прочитаем исходную картинку
source_image = imread( 'karlson.bmp' );
% Возьмем из нее только первый канал
gray_image = source_image(. 1);
% Бинаризуем с порогом 0.5
bim= double (im2bw(gray_image, 0.5));
% Покажем картинку
imagesc(bim);

newColor = 0.5; oldColor = 1;
point.x = 17; point.y = 143;
stack = [point];
[w h] = size(bim);
stack_size = []; spanLeft = 0; spanRight = 0;

mov = avifile( 'karlson_fill3.avi' , 'fps' ,50);
figure;
while (length(stack)

=0)
point = stack(1);
stack(1) = []; % Удаляем закрашенную точку из стека
y1 = point.y;

% Находим границу слева
while (y1 >= 1 && bim(point.x,y1) == oldColor) y1 = y1 - 1; end;
y1 = y1 + 1;
spanLeft = 0; spanRight = 0;
%Топаем по строке от левой границы вправо
while (y1 < h && bim(point.x,y1) == oldColor)
bim(point.x,y1) = newColor; %Закрашиваем текущую точку
if (spanLeft == 0 && point.x > 0 && bim(point.x-1,y1) == oldColor)
newpoint.x = point.x-1; newpoint.y = y1; stack = [stack newpoint];
spanLeft = 1;
elseif (spanLeft == 1 && point.x > 0 && bim(point.x-1,y1)

= oldColor)
spanLeft = 0;
end;

if (spanRight == 0 && point.x < w && bim(point.x+1,y1) == oldColor)
newpoint.x = point.x+1; newpoint.y = y1; stack = [stack newpoint];
spanRight= 1;
elseif (spanRight == 1 && point.x < w && bim(point.x+1,y1)

= oldColor)
spanRight = 0;
end;

y1 = y1 + 1;
stack_size = [stack_size length(stack)];
imagesc(bim); colormap gray; axis image;
F = getframe(gca); mov = addframe(mov,F);
end;
end;
mov = close(mov);

* This source code was highlighted with Source Code Highlighter

image


На рисунке 7 у нас график заполненности стека, но уже в обычных координатах. А видео, иллюстрирующее заполнение лапы новым цветом предлагается ниже. Оно сделано так же — 50 кадров в секунду.

Как мы видим в этом случае наш стек (Рис.7) оказывается ничтожно заполненным на протяжении всей заливки, да и со скоростью мы выиграли за счет поиска с меньшей глубиной.

Заключение

В заключение хочу сказать — иллюстрируйте все, даже такие простые алгоритмы, ибо в красоте сила.
Так же прощу прощения за длинную статью и в качестве затравки для возможно следующей
статьи приведу ссылку . Там описан еще один очень интересный и очень быстрый алгоритм заливки мне незнакомый до этого. Возможно, найдется герой со свободным временем, который так же подробно и с иллюстрациями разберет этот алгоритм.
А если у кого-то ресурсы мощнее, то предлагаю все таки залить пузо Карлсону и выложить сюда ролик, а то у меня терпения не хватает пока ролик пишется. Благо для этого весь код есть.

Image I

ОТВЕТЫ

Ответ 1

Это зависит от вашей ОС. Я предполагаю, что вы программируете на платформе Windows, поэтому вы можете использовать SetPixel, но вам нужно использовать "windows.h" для получения дескриптора консоли, поэтому здесь приведен пример рисование функции cos():

Вы также можете использовать некоторые другие библиотеки, такие как: conio.h allegro.h sdl и т.д.

Ответ 2

Если вы хотите, чтобы изображение выглядело нечетким, вы могли бы воспользоваться символами блока из кодовой страницы консоли.

  • █ = '\ xDB' = U + 2588 FULL BLOCK
  • ▄ = '\ xDC' = U + 2584 LOWER HALF BLOCK
  • ▀ = '\ xDF' = U + 2580 UPPER HALF BLOCK
  • и пробел

Используя полублоки в сочетании с цветным текстом, вы можете превратить консольное окно 80 и times; 25 в 80-кратное и 50-цветное 16-цветные дисплеи. (Это был подход, используемый QBasic-версией Nibbles.)

Затем вам просто нужно преобразовать изображение в 16-цветную палитру и достаточно маленький размер.

Mario in 8 lines and 10 columns of "text"

Ответ 3

Консоль - это текстовое устройство, поэтому, как правило, вы не записываете отдельные пиксели. Вы можете создать специальный шрифт и выбрать его как шрифт для консоли, но он будет монохроматическим. Существуют библиотеки, которые упрощают создание пользовательского интерфейса консоли управления (например, Curses), но я считаю, что у вас также есть более функциональная функциональность, а просто показывается спрайт.

Если вы хотите написать игру, я предлагаю взглянуть на некоторые из графических/игровых фреймворков /libs, например. SDL

Ответ 4

Я нарисовал прямую линию, используя windows.h в code:: blocks. Я не могу объяснить это подробно, но я могу предоставить вам код и процедуру для его компиляции в code:: blocks.

  • перейдите в меню настроек и выберите компилятор и отладчик.
  • Перейдите на вкладку компоновщика и добавьте библиотеку ссылок libgdi32.a, которая находится в каталоге C:\Program Files\CodeBlocks\MinGW\lib.

Скомпилируйте эту программу

В этой программе я использовал алгоритм рисования линии DDA. Задачи рисования пикселей выполняются функцией setPixel (ROUND (x), ROUND (y)). Это программа Windows, в которой вы можете узнать подробности здесь

Ответ 5

windows.h предоставляет функцию SetPixel() для печати пикселя в указанном месте окна. Общий вид функции

где, x и y - координаты пикселя для отображения, а цвет - цвет пикселя.

Важно. Чтобы напечатать пиксель на вашем компьютере с помощью Code:: blocks IDE, добавьте библиотеку ссылок libgdi32.a (обычно внутри MinGW\lib ) в настройках компоновщика.

Ответ 6

Для использования в CodeBlocks я нашел это (вы должны добавить опцию компоновщика -lgdi32): // Блоки кода: параметры сборки проекта Параметры компоновщика Опции компоновщика Othoer: add -lgdi32

Читайте также: