Конференция "Начинающим" » Fill pointer. [Delphi, Windows]
 
  • Б (09.03.10 04:50) [0]
    Здрасти!

    Загоняю данные растра в P функцией GetDIBits. (Где P: Pointer)
    Вопрос: как можно МАКСИМАЛЬНО БЫСТРО залить все пиксели растра через этот указатель цветом TColor?

    P.S. Растры 24-х и 32-х битные.
  • miek (09.03.10 21:40) [1]
    Написать процедурку на ассемблере или использовать чужую (FastLib, Graphics32, SpriteUtils).
  • Б (21.03.10 05:41) [2]
    Процедурку вытащил из GR32.
    Но почему-то растр заливается не корректно - становится полосатым.



    procedure FillLongword(var X; Count: Integer; Value: Longword);
    asm
     PUSH    EDI
     MOV     EDI,EAX  // Point EDI to destination
     MOV     EAX,ECX
     MOV     ECX,EDX
     TEST    ECX,ECX
     JS      @exit
     REP     STOSD    // Fill count dwords
    @exit:
     POP     EDI
    end;

    Type
     PArrColorQ = ^TArrColorQ;
     TArrColorQ = array [0..0] of LongWord;
    Var
     Bits : PArrColorQ;
    begin
    // В Bits загружен 24-х битный растр.

     FillLongword(FBits[0],  FW * FH, clRed); // *
     // ZeroMemory(FBits, FW * FH * 4);       // Корректно заполняет чёрным.

    End;


  • Sapersky (21.03.10 14:26) [3]
    Процедурка предназначена для заполнения 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);

  • Б (21.03.10 16:02) [4]
    А чему будут равны?:
    Bmp.Scanlines[i],
    Bmp.BWidth
    Bmp.Gap

    Scanline в TFastDIB.LoadFromFile что-то не заполняется.
  • Sapersky (21.03.10 18:01) [5]
    Scanlines и прочее заполняется в SetInterface. По сути тот же сканлайн, что и в TBitmap, только более быстрый и не перевёрнутый, в Медиа я уже писал.
    BWidth - полная ширина строки (с "хвостом" в конце), Gap - длина "хвоста". В общем, берётся размер строки в байтах, можно было и Width * 3 написать.
  • Б (21.03.10 20:27) [6]
    Вообщем так.
    Программа вылетает, если раскомментировать 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;    (* Texture - 256 x 256 *)
    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
     // ZeroMemory(FBits, FW * FH * 3);

    // Clear24(clBlue);

     BitBlt(Form1.Canvas.Handle, X, Y, FW, FH, FDC, 0, 0, SRCCOPY);
    End;

  • Sapersky (21.03.10 21:33) [7]
    Там где не надо - скопировал 1 в 1 (сканлайны для данной задачи не очень нужны), там где надо - пропустил символ :)
    Move(FBits^, Scan[i]^, BWidth - Gap);
    (Scan[i] - указатель, а в Move нужно передавать переменную).
    И не факт, что TColor будет корректно воспринят в данном случае. Возможно, потребуется сдвинуть... к тому же в TColor может быть системный цвет - см. функцию ColorToRGB в Graphics.pas.
  • Б (21.03.10 22:22) [8]
    Какой же я не внимательный. ;)
    Всё работает.
    Только цвет заливки воспринимался не правильно, пока не поменял каналы R-B.

    У меня ещё такой вопрос:
    Если убрать флаг LR_CREATEDIBSECTION, то приложение вылетает.
    Почему не коректно ведёт себя DDB?
  • Sapersky (22.03.10 13:19) [9]
    Возможно, GetObject не поддерживает DDB. У DDB вроде бы вообще нет нормального доступа к пикселям, так что (ИМХО) смысла использовать его немного.
  • Б (22.03.10 14:02) [10]

    > так что (ИМХО) смысла использовать его немного.


    Смысл использования DDB есть.
    Об этом я отписал тут:
    http://www.delphikingdom.com/asp/answer.asp?IDAnswer=75631

    P.S. В целом, при таком раскладе, заливать растр можно и обычными WinAPI-функциями.
  • Sapersky (22.03.10 16:04) [11]
    Ну если всё что тебе нужно - заливать цветом (рисовать прямоугольники) и выводить через BitBlt - то да, DDB "уделывает всех". Это те немногие функции, что GDI умеет аппаратно ускорять. Но для того, чтобы нарисовать что-то более-менее интересное их, мягко говоря, недостаточно.
    А доступ к пикселям DDB тормозит катастрофически. На том же Королевстве есть статья и тесты Антона Григорьева.
  • Б (22.03.10 19:53) [12]

    > Ну если всё что тебе нужно - заливать цветом (рисовать прямоугольники)
    > и выводить через BitBlt - то да, DDB "уделывает всех".


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


    > А доступ к пикселям DDB тормозит катастрофически.


    Я предлагаю след. способ: создавать DIB, что даёт скорость в обработке, а при выводе переводить в DIB, этим самым получаем быстрый вывод.


      B.Canvas...                // Рисуем.
       B.ScanLine...              // Обрабатываем пиксели.

       B.PixelFormat:= pfDevice;
       B.Canvas.Draw...           // Шустрый блиттинг.
       B.PixelFormat:= pf24bit;   // Восстанавливаемся.


  • Sapersky (23.03.10 12:29) [13]
    В целом мне не так уж много и надо: быстрая заливка, поворот, альфа-наложение, поддержка цветового ключа, быстрый блиттинг, доступ к пикселям.

    Аппаратная графика, конечно, не рассматривается по принципиальным соображениям? Ну дело твоё...

    B.PixelFormat:= pfDevice;

    Каждая такая строчка означает "создаём новый битмап, копируем в него, старый уничтожаем". Какое уж тут ускорение.
    Даже если не создавать - пророчествую: копия в DDB + блиттинг DDB на экран по времени будет равно или почти равно блиттингу DIB на экран (или в бэкбуфер).
  • Б (25.03.10 19:01) [14]

    > Аппаратная графика, конечно, не рассматривается по принципиальным
    > соображениям? Ну дело твоё...


    Занимаюсь изучением OpenGL и параллельно GDI, для общего ознакомления.


    > Какое уж тут ускорение.


    Тестил в по примеру BitmapSpeed от Антона Григорьева.
  • Sapersky (26.03.10 18:33) [15]
    Тестил в по примеру BitmapSpeed от Антона Григорьева.

    Погонял блиттинг на GF220 / Win 7. DIB 24 бита - в 2 раза медленнее DDB, 32 бита (1000 раз говорили - 32->32 быстрее!) - почти без разницы, DIB даже немного быстрее.
    Заполнение через сканлайн + блиттинг - "чистый" DIB-32 в 2 с лишним раза быстрее варианта с преобразованиями DDB<->DIB.
 
Конференция "Начинающим" » Fill pointer. [Delphi, Windows]
Есть новые Нет новых   [134430   +2][b:0][p:0.003]