Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.21;
Скачать: CL | DM;

Вниз

Как убрать тормоза при выводе битмапа?   Найти похожие ветки 

 
Alex Romasnkiy   (2005-04-06 02:05) [0]

Программа реализует что-то вроде навигации по карте города.
Квадраты карты хранятся в .gif файлах 1000х1000. В начале програмы я загружаю нужные мне квадраты в массив TBitmap-ов.
Навигация осуществляется методом drag&drop т.е. нажимаешь мышкой на карте ведешь в нужную сторону отпускаешь, карта соответсвенно перерисовывается в методе OnMouseMove при нажатой мышке, т.е. для каждой новой кординаты мышки.

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

Подскажите, плиз, как можно избавиться от сабжа. DoubleBuffer у формы включен.


 
Defunct ©   (2005-04-06 02:26) [1]

Добавить памяти и поставить проц помощьнее, отказаться от gif, взять bitmap, оптимизировать программу.

> DoubleBuffer у формы включен.
Это тут вообще не причем


 
Alex Romasnkiy   (2005-04-06 02:28) [2]

Gif я загружаю только в начале программы, далее я работаю с Bitmap-ами.


 
Defunct ©   (2005-04-06 02:36) [3]

Bitmap 1000x1000 занимает 40Mb как-никак.

Сколько у Вас памяти на компьютере?


 
Defunct ©   (2005-04-06 02:36) [4]

Cоврал.. 4Mb..


 
Defunct ©   (2005-04-06 02:40) [5]

Зы, приведите кусок кода, в котором Вы строите отображаемую картинку в соответствии с заданными координатами. Думаю так будет проще обсуждать причину жутких тормозов.


 
Alex Romasnkiy   (2005-04-06 02:46) [6]

В начале программы загружаю все нужные квадраты в массив Cells типа CellMatrix

CellsMatrix=record
             Cell:TBitmap; // Битмап, в который загружаю картинку
             Ex:Boolean; // Признак загрузил ли картинку в эту ячейку
            end;

  for i:=0 to ni-1 do
    for j:=0 to ni-1 do
      if Cells[i,j].Ex then
        MapCells.Canvas.Draw(кордината_Х,кордината_Y,Cells[i,j].Cell)

MapCells - это Image, на который вывож карту.


 
Defunct ©   (2005-04-06 03:01) [7]

 for i:=0 to ni-1 do
   for j:=0 to ni-1 do
     if Cells[i,j].Ex then
       MapCells.Canvas.Draw(кордината_Х,кордината_Y,Cells[i,j].Cell)


Вот это и причина тормозов! Вы же выводите фактически все, что есть, а надо выводить только то, что видно в текущем окне обзора (окно обзора - это Ваш Image у которого кол-во точек гораздо меньше чем 1000x1000).

Делать нужно так:
Начальная инициализация:
1. Задать/Посчитать глобальные размерами Вашей карты (зависит от числа составляющих картинок).
2. Задать размеры окна обзора.
3. Установить начальную координату верхнего-левого угла окна обзора.
4. Задать относительную координату верхнего-левого угла каждой картинки.

При перерисовке:
1. Определять какие картинки попадают в область обзора.
2. Вырезать видимые (попадающие в окно обзора) кусочки из попадающих в область обзора Bitmap"ов. (CopyRect)

CellsMatrix=record
            Cell:TBitmap; // Битмап, в который загружаю картинку
            Ex:Boolean; // Признак загрузил ли картинку в эту ячейку
            X, Y : Integer; // Координата верхнего-левого угла картинки на общей карте
           end;


 
Alex Romasnkiy   (2005-04-06 03:18) [8]


> Вот это и причина тормозов! Вы же выводите фактически все,
> что есть, а надо выводить только то, что видно в текущем
> окне обзора


Не совсем так. Я привел упрощенный вариант вывода.
ni,nj-это количество квадратов по горизонтали ивертикали, которые помещаются именно в моем окне обзора. Поэтому я не вывожу все, что у меня есть.
Да, присутствует некотарая избыточность, когда крайние картинки  не полностью отображаются, но как мне кажется это не настолко критично, и к тому же я когда-то уже пробовал использовать copyrect, но с ним тормоза только увеличивались.


 
Defunct ©   (2005-04-06 04:09) [9]

Знаете, Вы правы насчет избыточности. Если делать как у Вас (не более 4-х картинок) то торможений-то и нет.

Попробовал написать небольшой тест. Карта 10x10 кусочки - из Bitmap"ов с PixelFormat = pf32bit, каждая картинка 1000x1000. Никаких торможений нет, но программа занимает 130 Mb памяти. Может все-таки у Вас памяти недостаточно?

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, StdCtrls;

type
 TForm1 = class(TForm)
   Image1: TImage;
   procedure FormCreate(Sender: TObject);
   procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
   procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
 private
   ViewPoint  : TPoint;
   MousePos   : TPoint;
   DirectionVector : TPoint;
   Relocating : Boolean;
 public
   procedure RedrawImage;
 end;

var
 Form1: TForm1;

implementation

uses Types;

{$R *.dfm}

type
  TMapCell = record
      Bmp  : TBitmap;
      X, Y : Integer;
  end;

  TMapRow = array of TMapCell;
  TMap = array of TMapRow;

var
  Map : TMap;
  ColCount : Integer = 10; // Размеры карты (колонок)x
  RowCount : Integer = 10; // (строк)

procedure TForm1.FormCreate(Sender: TObject);
var
 i, j : integer;
begin
 ViewPoint.X := 0;
 ViewPoint.Y := 0;

 SetLength( Map, ColCount );
 for i := 0 to High(Map) do
     SetLength( Map[i], RowCount );

 for i := 0 to High(Map) do
     for j := 0 to High(Map[i]) do
         begin
            Map[i][j].Bmp := TBitmap.Create;
            Map[i][j].Bmp.LoadFromFile( "C:\Herb.bmp" );
            // 32bit-цветный Bitmap 1000x1000
            Map[i][j].X := i * 1000;
            Map[i][j].Y := j * 1000;
         end;
 RedrawImage;

end;

procedure TForm1.RedrawImage;
var
 i, j : integer;
 P    : TPoint;
begin
 for i := 0 to High(Map) do
     for j := 0 to High(Map[i]) do
         begin
            P.X := Map[i][j].X - (ViewPoint.X + DirectionVector.X);
            P.Y := Map[i][j].Y - (ViewPoint.Y + DirectionVector.Y);
            if (1000 - Abs(P.X)) >= 0 then
               if (1000 - Abs(P.Y)) >= 0 then
                  Image1.Canvas.Draw( P.X, P.Y, Map[i][j].Bmp );
         end;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 MousePos := Mouse.CursorPos;
 DirectionVector.X := 0;
 DirectionVector.Y := 0;
 Relocating := True;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
begin
 if Relocating then
 begin
    DirectionVector.X := MousePos.X - Mouse.CursorPos.X;
    DirectionVector.Y := MousePos.Y - Mouse.CursorPos.Y;
    RedrawImage;
 end
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 ViewPoint.X := ViewPoint.X + DirectionVector.X;
 ViewPoint.Y := ViewPoint.Y + DirectionVector.Y;
 DirectionVector.X := 0;
 DirectionVector.Y := 0;
 Relocating := False;
 RedrawImage
end;

end.


 
Erik1 ©   (2005-04-06 11:32) [10]

А не проще ли воспользоватся готовыми компонентами? Для работы с картами в королевстве я нидел несколько неплохих статей на эту тему. http://www.vkasoft.narod.ru/index.htm
http://www.flex-graphics.com/ru/info.html
http://www.gisdelphi.com/index_r.htm


 
Alex Romanskiy ©   (2005-04-06 14:52) [11]


Defunct ©  

Большое спасибо вам, что потратили время,
но часть вопроса все-таки остается открытой. Если размеры IMage1 вашей программы не большие около 200*200, то тормоза действительно пропадают даже при загрузке 100 картинок, но стоит увеличить рамеры Image1 до 700*600, а где-то именно такие размеры не необходимы, то тормоза появляются опять. :(


Erik1 ©  

Конечно,с готовыми компонентами было-бы на много проще, но к сожалению, они все предназначены для работы с векторными катами, а у меня нет исходных данных для создания векторных карт.


 
Spider Man   (2005-04-06 18:48) [12]

Сам создай по растру. Можешь векторизировать объекты по имеющемуся растру, например при помощи Corel Trace, потом экспортировать в DXF, ну а из него можно импортировать в тот же DataMap


 
Sapersky   (2005-04-08 13:21) [13]

1) Если gif, то и битмапы использовать 8-битные.
2) Выкинуть Image (он, видимо, что-то там буферизует или конвертирует) и рисовать прямо на форму или PaintBox.
3) Думаю, DoubleBuffer в данном случае не нужен.


 
Alex Romasnkiy   (2005-04-12 00:53) [14]


> Sapersky


Именно пункт №2 и являлся причиной тормозов, спасибо, при замене Image на PaintBox все тормоза пропали.

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


 
Sapersky   (2005-04-12 12:35) [15]

А каким образом можно задать битность для битмапа

Bitmap.PixelFormat := ...
Глюков не будет - разве что при 8-битном режиме экрана.
Не знаю, что используется для преобразования из gif, но вообще по логике оно должно устанавливать 8-битный режим битмапа (проверить PixelFormat) - если уж в gif максимум 8 бит. Так что моё замечание относится скорее к примеру [9], где используется 32 бита.
Говорят, что ещё можно поставить PixelFormat := pfDevice (преобразование в DDB, который должен рисоваться быстрее) - но у меня в приведённом примере никакого ускорения от этого не получилось.



Страницы: 1 вся ветка

Текущий архив: 2005.08.21;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.044 c
14-1122466533
Lexer
2005-07-27 16:15
2005.08.21
Кляп удаленному компьютеру


3-1121248213
linesoft
2005-07-13 13:50
2005.08.21
Отладчик процедур MS SQL


4-1119512600
Igit
2005-06-23 11:43
2005.08.21
Динамический импорт функции из DLL


1-1122642655
mazepa
2005-07-29 17:10
2005.08.21
excell


11-1104779637
Foxi
2005-01-03 22:13
2005.08.21
Ini-файлы в KOL - кто они?