| 
| 
 | Вопрос # 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) в приложениях модератором Ерёмин А.А. Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |