|
Вопрос # 5 725/ вопрос открыт / |
|
Доброго времени суток, уважаемые эксперты! Буду очень признателен за помощь. Имеется матрица a[i,j], в которой содержатся цвета пикселей. Необходимо вывести эти пиксели на канву. (Image.Canvas.Pixels[i,j]:=a[i,j]). Но при этом нужно, чтобы пользователь мог видеть, как каждый пиксель прорисовывается на канве. Как это можно сделать?
 |
Вопрос задал: Зайцев Валентин Николаевич (статус: Посетитель)
Вопрос отправлен: 7 ноября 2011, 15:52
Состояние вопроса: открыт, ответов: 3.
|
Ответ #1. Отвечает эксперт: VKHacker
Здравствуйте, Зайцев Валентин Николаевич!
Выполняйте код в потоке.
Для справки:
http://www.interface.ru/home.asp?artId=6105
 |
Ответ отправил: VKHacker (статус: 1-ый класс)
Время отправки: 7 ноября 2011, 16:26
|
Ответ #2. Отвечает эксперт: Вадим К
Здравствуйте, Зайцев Валентин Николаевич!
Хороший ответ звучит так - Canvas+Thread.
Для начала читаем две статьи http://www.drbob42.com/uk-bug/hood-04.htm и http://www.delphisources.ru/pages/faq/base/threads_example.html
План действий будет где то такой
Идем в File-new... и там ищем thread.
Предложит ввести имя треда, введем к примеру "MyDrawThread".
в public части добавим
a:array[0..99,0..99] of TColor; // тут размерности правильные пропишите.
в private часть добавим четыре поля
x:integer;
y:integer;
cur:TColor;
im:TCanvas;
Теперь добавляем метод, который будет отрисовывать пиксель.
в private часть добавляем
procedure drawpixel;
и жмем Ctrl+Shift+C
делфи сгенерит тело метода, куда вписывам код прорисовки пикселя.
im.pixels[x,y] := cur;
теперь переходим к методу execute, который уже будет сгенерирован
var i, j:integer;
begin
for i:=0 to 99 do begin // тут нужные размеры подставляем, вполне подойдет im.height-1 и im.width-1
for j := 0 to 99 do begin
cur := a[i,j];
x := i;
y := j;
// эти пляски с переменными нужны, так как метод Synchronize требует метода без параметров.
Synchronize(drawpixel);
sleep(50); // пауза между отрисовками. Нужно медленее - вставляем больше. 1000 - это одна секунда.
end;
end;
end;
И осталось самое последнее - запустить код. Пусть это будет по нажатию кнопки
var t:TMyDrawThread;
begin
t := TMyDrawThread.create(true); // true - что бы поток не стартовал сразу
t.im := Image1.canvas; //где рисовать
// переносим массив пикселей
for i:= 0 to 99 do
for j := 0 to 99 do
t.a[i,j] := a[i,j];
t.freeonterminate := true; // что бы поток сам себя почистил по завершению.
t.resume; //запускаем поток.
end;
В принципе, должно запустится.
Что доделать
- передавать правильный размер массива
- подумать о правильном копировании массива или использовать указатель (но тогда может быть проблема с тем, что массив поменялся, пока отрисовывался)
если будет копироваться медленно, то можно копировать пиксели пачками (то есть вызывать sleep раз в несколько отрисовок, например так (вместо строки sleep(50);)
if j mod 10 = 0 then sleep(50);
И будет пауза только раз на десять пикселей.
- подумать о том, что пауза может быть динамической (для более изощренного рисования)
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 7 ноября 2011, 16:32
Оценка за ответ: 5
|
Ответ #3. Отвечает эксперт: ierihon1
Здравствуйте, Зайцев Валентин Николаевич!
Вот это самое простое решение но с потоками конечно лучше.
var i,j:integer;
procedure TForm14.FormCreate(Sender: TObject);
begin
i:=0;
j:=0;
end;
procedure TForm14.tmr1Timer(Sender: TObject);
begin
if j = 500 then
begin
j:=0;
inc(i)
end;
Image2.Canvas.Pixels[i,j]:=mas_pix[i,j]
if (i = 500) and (j = 500) then
timer1.Enabled:=False;
j:=j+1;
end;
 |
Ответ отправил: ierihon1 (статус: 1-ый класс)
Время отправки: 7 ноября 2011, 16:36
Оценка за ответ: 5
|
Мини-форум вопроса
Всего сообщений: 7; последнее сообщение — 7 ноября 2011, 16:47; участников в обсуждении: 4.
|
min@y™ (статус: Доктор наук), 7 ноября 2011, 16:04 [#1]:
Ну дык, по таймеру, наверное. Или как по-другому интерпретировать слова
Цитата (Зайцев Валентин Николаевич):
чтобы пользователь мог видеть, как каждый пиксель прорисовывается на канве
?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Зайцев Валентин Николаевич (статус: Посетитель), 7 ноября 2011, 16:15 [#2]:
вот такой код должен быть в процедуре ontimer:
for i:=1 to 500 do
for j:=1 to 500 do
Image2.Canvas.Pixels[i,j]:=mas_pix[i,j]?
не получается(
|
|
ierihon1 (статус: 1-ый класс), 7 ноября 2011, 16:20 [#3]:
так получается что он каждый раз полностью перерисовывает всё изображение.
|
|
Зайцев Валентин Николаевич (статус: Посетитель), 7 ноября 2011, 16:24 [#4]:
а возможно в image загружать изображение по пикселям? или делать часть изображения видимой, а часть нет.
|
|
min@y™ (статус: Доктор наук), 7 ноября 2011, 16:47 [#7]:
Цитата (Зайцев Валентин Николаевич):
вот такой код должен быть в процедуре ontimer: for i:=1 to 500 do for j:=1 to 500 do
Image2.Canvas.Pixels[i,j]:=mas_pix[i,j]? не получается(
Конечно. Надо на OnTimer отрисовывать 1 (АДЫН) пиксел, а не 250000.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
7 ноября 2011, 21:36: Вопрос перемещён из тематического раздела Delphi » Общие вопросы по программированию в раздел Delphi » Графика (2D и 3D) в приложениях модератором Ерёмин А.А.
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|