Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  18:37[Войти] | [Зарегистрироваться]
Ответ на вопрос № 45267

20-09-2006 00:31
Бодрое время суток, товарищи!

Хочу проконсультироваться на счет одной проблемы. Пишу одно приложение, которое представлет из себя что-то вроде расписания движения поездов (Направление поезда -> Время). Информация о движении выводится в такое табло, которое раньше можно было наблюдать на железнодорожных вокзалах и аэропортах: каждая буква и цифра в отдельной ячейке на табло. При изменении информации (меняется только Время) цифры начинают перелистываться на подобие того, как это имело бы место при перелистывании страниц книги. Вид этого табло можно посмотреть здесь: http://podonok-studio.jino-net.ru/screen.jpg

Для реализации этого табло я использовал класс TDrawGrid, в ячейки объекта класса TDrawGrid выводил буквы и цифры. Объект DrawGrid1 занимает весь экран. Все цифры и все промежуточные состояния при их перелистывании (при изменении времени движения поездов) прорисовал в CorelDraw, получил кучу *.bmp файлов и засунул их в ImageList1, из которого потом методом ImageList1.Draw(DrawGrid.Canvas,R.Left,R.Top,i) по событию Timer1Timer выводил информацию на табло (т.е. вся эта мультипликация реализована в виде спрайтов). Так вот, изображения из ImageList1 в DrawGrid1 должны выводиться достаточно быстро, чтобы создавалась иллюзия перелистывания цифр. Максимальное число полей, которое может одновременно меняться (перелистываться) 30. При этом меня бы устроило, если бы следующее движение (изображение) выводилось через 30 ms. Однако по моим замерам при изменении изображений в 30 полях время составляет 90 ms (и это на моем достаточно новом ноутбуке: WinXP, Pentium 1.7 GHz mobile, RAM 512 MB, 256 MB video NVIDIA GeForce Go 6200, 798 MHz шина).

В связи с этим вопрос: как ускорить вывод изображений в табло? Создается впечатление, что это можно сделать только, используя DirectX или OpenGL, с которыми я не знаком. В частности, я не могу найти статей, которые бы описывали работу с DirectX при выводе спрайтов на какую либо форму (т.е. работу НЕ в полноэкранном режиме). Буду рад ЛЮБЫМ ИДЕЯМ по поводу создания данного приложения и ссылкам на статьи по работе с DirectX НЕ в полноэкранном режиме.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

23-09-2006 07:36
В качестве дальнейшей оптимизации

MainBm := TBitmap.Create;
MainBm.Width := 3*49+22;     
MainBm.Height := 11*61+22;
Template := TBitmap.Create;
Template.LoadFromFile('numbers.bmp');


лучше вынести в Create, а

Template.Free;
MainBm.Free;

в destroy.

22-09-2006 23:33 | Сообщение от автора вопроса
Если кому еще интересно, проблема была решена простой оптимизацией,
следующим образом:


procedure TForm2.Timer2Timer(Sender: TObject);
var
i, j: integer;
Source, Dest, R: TRect;
MainBm, Template: TBitmap;
begin
inc(Frame);
if Frame > 79 then Frame := 0;

MainBm := TBitmap.Create;
MainBm.Width := 3*49+22;     
MainBm.Height := 11*61+22;

Template := TBitmap.Create;
Template.LoadFromFile('numbers.bmp');

Source.Left := Frame*49;
Source.Top := 0;
Source.Right := Source.Left+49;
Source.Bottom := 61;

for i := 0 to 2 do
  for j := 0 to 10 do
  begin
    Dest.Left := i*49+i*2;
    Dest.Top :=j*61+j*2;
    Dest.Right := Dest.Left+49;
    Dest.Bottom := Dest.Top+61;

    MainBm.Canvas.CopyRect(Dest, Template.Canvas, Source);
  end;
Template.Free;

r:=DrawGrid1.CellRect(22,0);
with r.TopLeft do  DrawGrid1.Canvas.Draw(x,y,MainBm);
MainBm.Free;
end;

В numbers.bmp находятся все кадры перелистывающихся чисел.
Все работает шустро.


21-09-2006 02:02
Или попробовать не все картинки рисовать в одном цикле, а что-то типа:

procedure TForm1.Button1Click(Sender: TObject);
begin
  timer2.Interval := 1; //?
  timer2.Enabled := true;
end;

var
  j: integer=1;

procedure TForm1.Timer2Timer(Sender: TObject);
var
  r: trect;
begin
  begin
    R:=DrawGrid1.CellRect(1,j);
    DrawGrid1.Canvas.Draw(R.Left,R.Top,b); //это я взял bitmap

    R:=DrawGrid1.CellRect(2,j);
    DrawGrid1.Canvas.Draw(R.Left,R.Top,b);

    R:=DrawGrid1.CellRect(3,j);
    DrawGrid1.Canvas.Draw(R.Left,R.Top,b);
  end;

  inc(j);
  if j=11 then
  begin
    j:=1;
    Timer2.Enabled:=False;
  end;
end;


21-09-2006 01:34
Для измерения точного времени я использовал функции из статьи http://www.delphikingdom.com/asp/articles_forum.asp?ArticleID=455
В данном случае можно выводить 10 букв на одну большую картинку, а в таблицу выводить уже её.
У меня это дало самые хорошие результаты. Вот как я попробовал:

  T := 0;
  Bmp := TBitmap.Create;
  try
    Bmp.Height := ImageListCep1.Height;
    Bmp.Width := ImageListCep1.Width*ImageListCep1.Count;
    for j := 1 to 1000 do
    begin
      //ImageListCep1.Count = 35;
      //размер 32x32
      CountCPU(C);
      Bmp.Canvas.Brush.Color := Color;
      Bmp.Canvas.FillRect(Rect(0,0,Bmp.Width,Bmp.Height));
      for I := 0 to ImageListCep1.Count - 1 do
      begin
        ImageListCep1.Draw(Bmp.Canvas,i*ImageListCep1.Width,0,i);
      end;
      Canvas.Draw(10,50,Bmp);
      T := T + CountCPU(C);
    end;
  finally
    FreeAndNil(Bmp);
  end;
  Label3.Caption := CountCPUtoSTR((T)div(1000*ImageListCep1.Count)); //9 мкс


21-09-2006 00:54 | Сообщение от автора вопроса
С функцией BitBlt интересно, попробую.
А почему, собственно, эта функция должна работать быстрее?

21-09-2006 00:49 | Сообщение от автора вопроса
Здесь просили фрагмент кода отрисовки DrawGrid. Привожу его ниже.
В коде видно каким образом измерялось время прорисовки.


//-----срабатывает на все ячейки DrawGrid!---------
procedure TForm2.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  Symbol, index: integer;
begin

  //1) выяснить необходимый символ по массиву Goods
  //2) найти порядковый номер изображения в ImageList
  //3) вывести изображение с помощью ImageList1.Draw

  //Goods[ARow+1][ACol+1] - это дает символ, если Length(Goods[ARow+1])>=ACol
  //последние три поля заполняем НУЛЯМИ
  //все остальное заполняем пустым полем BLANK

  //далее используем конструкцию case, предварительно переведя буквы в коды

  Symbol:=0; //Если Symbol не переопределяется ниже, то остается=0 и index:=10 (blank)
  //Символы в типе String индексируются 1, 2, 3, ...
  //ACol меняется от 0 до 24
  if (Length(Goods[ARow+1])>=ACol)
  and (ACol<DrawGrid1.ColCount-4)              //последние 4 символа для пробела и цены
  and (Length(Goods[ARow+1])<>0)                //если строка пустая, то выводим blank
  then Symbol:=Ord(Goods[ARow+1][ACol+1]);
  case Symbol of
    192, 224: index:=37; //буква 'а'
    193, 225: index:=38; //буква 'б'
    194, 226: index:=39; //буква 'в'
    195, 227: index:=40; //буква 'г'
    196, 228: index:=41; //буква 'д'
    197, 229: index:=42; //буква 'е'
    168, 184: index:=43; //буква 'ё'
    198, 230: index:=44; //буква 'ж'
    199, 231: index:=45; //буква 'з'
    200, 232: index:=46; //буква 'и'
    201, 233: index:=47; //буква 'й'
    202, 234: index:=48; //буква 'к'
    203, 235: index:=49; //буква 'л'
    204, 236: index:=50; //буква 'м'
    205, 237: index:=51; //буква 'н'
    206, 238: index:=52; //буква 'о'
    207, 239: index:=53; //буква 'п'
    208, 240: index:=54; //буква 'р'
    209, 241: index:=55; //буква 'с'
    210, 242: index:=56; //буква 'т'
    211, 243: index:=57; //буква 'у'
    212, 244: index:=58; //буква 'ф'
    213, 245: index:=59; //буква 'х'
    214, 246: index:=60; //буква 'ц'
    215, 247: index:=61; //буква 'ч'
    216, 248: index:=62; //буква 'ш'
    217, 249: index:=63; //буква 'щ'
    218, 250: index:=64; //буква 'ъ'
    219, 251: index:=65; //буква 'ы'
    220, 252: index:=66; //буква 'ь'
    221, 253: index:=67; //буква 'э'
    222, 254: index:=68; //буква 'ю'
    223, 255: index:=69; //буква 'я'

    48: index:=0; //цифра '0'
    49: index:=1; //цифра '1'
    50: index:=2; //цифра '2'
    51: index:=3; //цифра '3'
    52: index:=4; //цифра '4'
    53: index:=5; //цифра '5'
    54: index:=6; //цифра '6'
    55: index:=7; //цифра '7'
    56: index:=8; //цифра '8'
    57: index:=9; //цифра '9'

    65, 97: index:=11; //letter 'a'
    66, 98: index:=12; //letter 'b'
    67, 99: index:=13; //letter 'c'
    68, 100: index:=14; //letter 'd'
    69, 101: index:=15; //letter 'e'
    70, 102: index:=16; //letter 'f'
    71, 103: index:=17; //letter 'g'
    72, 104: index:=18; //letter 'h'
    73, 105: index:=19; //letter 'i'
    74, 106: index:=20; //letter 'j'
    75, 107: index:=21; //letter 'k'
    76, 108: index:=22; //letter 'l'
    77, 109: index:=23; //letter 'm'
    78, 110: index:=24; //letter 'n'
    79, 111: index:=25; //letter 'o'
    80, 112: index:=26; //letter 'p'
    81, 113: index:=27; //letter 'q'
    82, 114: index:=28; //letter 'r'
    83, 115: index:=29; //letter 's'
    84, 116: index:=30; //letter 't'
    85, 117: index:=31; //letter 'u'
    86, 118: index:=32; //letter 'v'
    87, 119: index:=33; //letter 'w'
    88, 120: index:=34; //letter 'x'
    89, 121: index:=35; //letter 'y'
    90, 122: index:=36; //letter 'z'

    34: index:=70; //"""
    40: index:=71; //"("
    41: index:=72; //")"
    45: index:=73; //"-"
    44: index:=74; //","
    46: index:=75; //"."
    95: index:=76; //"_"
    61: index:=77; //"="
    58: index:=78; //":"
    59: index:=79; //";"

  else index:=10//blank
  end;

  if (Length(Goods[ARow+1])<>0) and (ACol>DrawGrid1.ColCount-4) then index:=0;

  with Sender as TDrawGrid do
  begin
    //Canvas.Brush.Color := clBlack;
    //Canvas.FillRect(Rect);
    ImageList1.Draw(Canvas,Rect.Left,Rect.Top,index);
  end;

  Timer2.Enabled:=True; //включаем перелистывание цифр (тест)
end;

procedure TForm2.Timer2Timer(Sender: TObject);
var
  j: integer;
  //t1, t2: comp;                                    //это используется для измерения скорости прорисовки
begin
  inc(i);
  if i>79 then i:=0;

  //t1:=TimeStampToMSecs(DateTimeToTimeStamp(Time));  //это используется для измерения скорости прорисовки

  for j:=0 to 10 do
  begin
    R:=DrawGrid1.CellRect(22,j);
    ImageList2.Draw(DrawGrid1.Canvas,R.Left,R.Top,i);

    R:=DrawGrid1.CellRect(23,j);
    ImageList2.Draw(DrawGrid1.Canvas,R.Left,R.Top,i);

    R:=DrawGrid1.CellRect(24,j);
    ImageList2.Draw(DrawGrid1.Canvas,R.Left,R.Top,i);
  end;

  //t2:=TimeStampToMSecs(DateTimeToTimeStamp(Time));  //это используется для измерения скорости прорисовки
  //Timer2.Enabled:=False;                            //это используется для измерения скорости прорисовки
  //Panel1.Caption:=FloatToStr(t2-t1);                //это используется для измерения скорости прорисовки

  //RESUME: чтобы перевернуть все цифры, требуется 94 ms, против 30 ms нужных
  //полей с цифрами 11(рядов)x3(колонки)=33, на одно поле примерно 3 ms
  //размер поля 49x61 пикселей, черно-белое изображение
end;


20-09-2006 09:41 | Комментарий к предыдущим ответам
Мне тут сказали что чушь во втором ответе написал, с чем вобщем-то полностью согласен. Более того - кроме первого ответа не собирался больше и писать. Ради интереса попробовал с Thread'ами посмотреть как будет... Вобщем жуть, забыли.

20-09-2006 01:48 | Вопрос к автору: запрос дополнительной информации
Хорошо бы увидеть кусок кода отрисовки. Возможно всё дело в том, что TDrawGrid при каждой перерисовке обновляет все ячейки строки.

У меня получилось скорость отрисовки одного изображения (32x32)
ImageList: 13мкс
Bitmap: 11мкс
Даже учитывая возможную разницу скорости компов, время отрисовки в 100 раз меньше необходимого.

20-09-2006 01:45
Скорей всего Off topic:

Иногда быстро прорисовывается, иногда медленно,

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

type
  TMyThread = class(TThread)
  private
    b: TBitmap;
    x, y: Integer;
    procedure DrawBitmap;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyThread }

constructor TMyThread.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  Y := 0;
  b:= tbitmap.Create;
  b.LoadFromFile('D:\2.bmp'); //?acia?u 32x32
end;

destructor TMyThread.Destroy;
begin
  b.Free;
  inherited;
end;

procedure TMyThread.DrawBitmap;
begin
  form1.canvas.Draw(x, y, b);
  //windows.BitBlt(form1.Canvas.Handle, x,y,32,32, b.Canvas.Handle, 0, 0, srccopy);
end;

procedure TMyThread.Execute;
begin
  while (not Terminated) and (y<1000) do
  begin
    Synchronize(DrawBitmap);
    Inc(Y, 1);
    //sleep(3);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
  h: array[0..30] of TMyThread;
begin
  for I := 0 to 30 do
  begin
    h[i] := TMyThread.Create(True);
    h[i].x := i*32;
    h[i].FreeOnTerminate := true;
  end;

  for I := 0 to 30 do
  begin
    h[i].Resume;
  end;
end;


20-09-2006 01:37
Извеняюсь 200 картинок будут иметь размер 3200х16 пиксел

20-09-2006 01:34
А как такой вариант: создать единственный битмап, где по порядку по горизонтали расположены все картинки, к примеру 16х16 пиксел -->
тобишь получается 200 мелких картинок будут помещены в битмап 320х16 пиксел. А для быстрого рисования я бы использовал такую штуку:

X:=i*16; //i - индекс нужной картинки
BitBlt(DrawGrid1.Canvas.Handle,Rect.Left,Rect.Top,16,16,Bmp.Canvas.Handle,X,0,SRCCOPY);

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

20-09-2006 01:05
А вместо Imagelist не пробовал с помощью массива Bitmap'ов?

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Вода мокрая или сухая?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования