-
Здрасти!
Загоняю данные растра в P функцией GetDIBits. (Где P: Pointer) Вопрос: как можно МАКСИМАЛЬНО БЫСТРО залить все пиксели растра через этот указатель цветом TColor?
P.S. Растры 24-х и 32-х битные.
-
Написать процедурку на ассемблере или использовать чужую (FastLib, Graphics32, SpriteUtils).
-
Процедурку вытащил из GR32. Но почему-то растр заливается не корректно - становится полосатым.
procedure FillLongword(var X; Count: Integer; Value: Longword);
asm
PUSH EDI
MOV EDI,EAX MOV EAX,ECX
MOV ECX,EDX
TEST ECX,ECX
JS @exit
REP STOSD @exit:
POP EDI
end;
Type
PArrColorQ = ^TArrColorQ;
TArrColorQ = array [0..0] of LongWord;
Var
Bits : PArrColorQ;
begin
FillLongword(FBits[0], FW * FH, clRed);
End;
-
Процедурка предназначена для заполнения 32-битных растров. FastLib, 24 бита:
pc:=Pointer(Bmp.Bits);
for i:=0 to Bmp.Width-1 do begin
pc^:=PFColor(@c)^; Inc(pc);
end;
for i:=1 to Bmp.AbsHeight-1 do
Move(Bmp.Bits^,Bmp.Scanlines[i]^,Bmp.BWidth-Bmp.Gap);
-
А чему будут равны?: Bmp.Scanlines[i], Bmp.BWidth Bmp.Gap
Scanline в TFastDIB.LoadFromFile что-то не заполняется.
-
Scanlines и прочее заполняется в SetInterface. По сути тот же сканлайн, что и в TBitmap, только более быстрый и не перевёрнутый, в Медиа я уже писал. BWidth - полная ширина строки (с "хвостом" в конце), Gap - длина "хвоста". В общем, берётся размер строки в байтах, можно было и Width * 3 написать.
-
Вообщем так. Программа вылетает, если раскомментировать Clear24. Что не так?
Type
PFColor =^TFColor;
TFColor = packed record
b,g,r: Byte;
end;
PArrColorQ = ^TArrColorQ;
TArrColorQ = array [BYTE] of TColor;
PLines = ^TLines;
TLines = array[BYTE]of Pointer;
Var
FBits: PArrColorQ;
Scan : PLines;
FW, FH: LongWord;
BWidth, Gap: LongInt;
FDC: LongWord;
FHB: LongWord;
Function XLoadBMP(const FileName: string): boolean;
Var
BMP : Bitmap;
x, i: LongInt;
begin
Result:= False;
FHB:= LoadImage(0, PCHAR(FileName), 0, 0, 0, LR_LOADFROMFILE or LR_CREATEDIBSECTION);
If (FHB = 0) then Exit;
GetObject(FHB, SizeoF(BMP), @BMP);
With BMP do
begin
If (bmBitsPixel <> 24) then Exit;
FW:= bmWidth;
FH:= bmHeight;
GetMem(FBits, FW * FH * 3);
FBits := bmBits;
Result:= (FBits <> nil);
end;
FDC:= CreateCompatibleDC(0);
DeleteObject(SelectObject(FDC, FHB));
BWidth:=(((FW * 24) + 31) and - 32) shr 3;
Gap := BWidth - ((FW shl 1) + FW);
ReallocMem(Scan, FH shl 2);
x:= Integer(FBits);
for i:= 0 to FH-1 do
begin
Scan[i]:= Ptr(x);
Inc(x, BWidth);
end;
End;
procedure TForm1.FormCreate(Sender: TObject);
begin
If not XLoadBMP('C:\Texture.bmp') then Close;
End;
Procedure Clear24(Color: TColor);
Var
pc: PFColor;
i: LongWord;
begin
pc:=Pointer(FBits);
for i:=0 to FW-1 do
begin
pc^:=PFColor(@Color)^;
Inc(pc);
end;
for i:=1 to FH-1 do
Move(FBits^, Scan[i], BWidth - Gap);
End;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
BitBlt(Form1.Canvas.Handle, X, Y, FW, FH, FDC, 0, 0, SRCCOPY);
End;
-
Там где не надо - скопировал 1 в 1 (сканлайны для данной задачи не очень нужны), там где надо - пропустил символ :) Move(FBits^, Scan[i]^, BWidth - Gap); (Scan[i] - указатель, а в Move нужно передавать переменную). И не факт, что TColor будет корректно воспринят в данном случае. Возможно, потребуется сдвинуть... к тому же в TColor может быть системный цвет - см. функцию ColorToRGB в Graphics.pas.
-
Какой же я не внимательный. ;) Всё работает. Только цвет заливки воспринимался не правильно, пока не поменял каналы R-B.
У меня ещё такой вопрос: Если убрать флаг LR_CREATEDIBSECTION, то приложение вылетает. Почему не коректно ведёт себя DDB?
-
Возможно, GetObject не поддерживает DDB. У DDB вроде бы вообще нет нормального доступа к пикселям, так что (ИМХО) смысла использовать его немного.
-
-
Ну если всё что тебе нужно - заливать цветом (рисовать прямоугольники) и выводить через BitBlt - то да, DDB "уделывает всех". Это те немногие функции, что GDI умеет аппаратно ускорять. Но для того, чтобы нарисовать что-то более-менее интересное их, мягко говоря, недостаточно. А доступ к пикселям DDB тормозит катастрофически. На том же Королевстве есть статья и тесты Антона Григорьева.
-
> Ну если всё что тебе нужно - заливать цветом (рисовать прямоугольники) > и выводить через BitBlt - то да, DDB "уделывает всех".
В целом мне не так уж много и надо: быстрая заливка, поворот, альфа-наложение, поддержка цветового ключа, быстрый блиттинг, доступ к пикселям. Все пункты почти решены. > А доступ к пикселям DDB тормозит катастрофически.
Я предлагаю след. способ: создавать DIB, что даёт скорость в обработке, а при выводе переводить в DIB, этим самым получаем быстрый вывод.
B.Canvas... B.ScanLine...
B.PixelFormat:= pfDevice;
B.Canvas.Draw... B.PixelFormat:= pf24bit;
-
В целом мне не так уж много и надо: быстрая заливка, поворот, альфа-наложение, поддержка цветового ключа, быстрый блиттинг, доступ к пикселям.
Аппаратная графика, конечно, не рассматривается по принципиальным соображениям? Ну дело твоё...
B.PixelFormat:= pfDevice;
Каждая такая строчка означает "создаём новый битмап, копируем в него, старый уничтожаем". Какое уж тут ускорение. Даже если не создавать - пророчествую: копия в DDB + блиттинг DDB на экран по времени будет равно или почти равно блиттингу DIB на экран (или в бэкбуфер).
-
> Аппаратная графика, конечно, не рассматривается по принципиальным > соображениям? Ну дело твоё...
Занимаюсь изучением OpenGL и параллельно GDI, для общего ознакомления.
> Какое уж тут ускорение.
Тестил в по примеру BitmapSpeed от Антона Григорьева.
-
Тестил в по примеру BitmapSpeed от Антона Григорьева.
Погонял блиттинг на GF220 / Win 7. DIB 24 бита - в 2 раза медленнее DDB, 32 бита (1000 раз говорили - 32->32 быстрее!) - почти без разницы, DIB даже немного быстрее. Заполнение через сканлайн + блиттинг - "чистый" DIB-32 в 2 с лишним раза быстрее варианта с преобразованиями DDB<->DIB.
|