2012-01-24 13 views
7

zrobiłem następujący kod:Najszybsza droga do rysowania pikseli w FireMonkey

procedure TForm15.Button1Click(Sender: TObject); 
var 
    Bitmap1: TBitmap; 
    im: TImageControl; 
    Color: TColor; 
    Scanline: PAlphaColorArray; 
    x,y,i: Integer; 
begin 
    for i:= 1 to 100 do begin 
    im:= ImageControl1; 
    Bitmap1:= TBitmap.Create(100,100); 
    try 
     for y:= 0 to 99 do begin 
     ScanLine:= Bitmap1.ScanLine[y]; 
     for x:= 0 to 99 do begin 
      ScanLine[x]:= Random(MaxInt); 
     end; 
     end; 
     ImageControl1.Canvas.BeginScene; 
     ImageControl1.Canvas.DrawBitmap(Bitmap1, RectF(0,0,Bitmap1.Width, Bitmap1.Height) 
            ,im.ParentedRect,1,true); 
     ImageControl1.Canvas.EndScene; 
    finally 
     Bitmap1.Free; 
    end; 
    end; 
end; 

Czy istnieje szybszy sposób narysować piksele Firemonkey?
Zamierzam zrobić program demonstracyjny za pomocą gry życia Conwaya.

+0

Jaka jest wersja swojej Firemonkey? W Berlinie 10.1 kod nie działa. –

Odpowiedz

6

Cały czas spędza wykonując poniższe dwa wiersze kodu:

ImageControl1.Canvas.BeginScene; 
ImageControl1.Canvas.EndScene; 

Można usunąć wszystkie kod, który działa z bitmapy i kod, który faktycznie rysuje bitmapę i to nie stanowi żadnego wyjątku dla środowiska wykonawczego. Innymi słowy, wąskim gardłem jest kod sceny, a nie kod bitmapy. I nie widzę sposobu, żeby to zoptymalizować.

Mój kod testowy wyglądał następująco:

Stopwatch := TStopwatch.StartNew; 
for i:= 1 to 100 do begin 
    ImageControl1.Canvas.BeginScene; 
    ImageControl1.Canvas.EndScene; 
end; 
ShowMessage(IntToStr(Stopwatch.ElapsedMilliseconds)); 

ten ma taki sam czas, który upłynął jak kod, 1600ms na moim komputerze. Jeśli usuniesz wywołania BeginScene, DrawBitmap i EndScene, twój kod będzie działać przez 3ms na moim komputerze.

+0

Po przetestowaniu okazuje się, że niezbędna jest para 'begincene-endscene'. Jeśli ** ** obejmuje cały czas pracy, utknąłem.Przyjrzę się kodowi źródłowemu na początku i na końcu sceny i zobaczę, co się zżerało w całym tym czasie pracy, a tam jest kod zabezpieczający przed zagłuszaniem (sekcja krytyczna lub coś w tym stylu), który spowalnia działanie. – Johan

+0

Sekcja krytyczna nie spowalnia Cię w pojedynczej aplikacji z gwintami. 70 klatek na sekundę wydaje się trochę za niska, aby aplikacja nie mogła narysować nic. –

-2

można zoptymalizować kod tak:

procedure TForm15.Button1Click(Sender: TObject); 
var 
    Bitmap1: TBitmap; 
    im: TImageControl; 
    Color: TColor; 
    ScanLine: PAlphaColorArray; 
    x,y,i: Integer; 
begin 
    Bitmap1:= TBitmap.Create(100,100); 
    try 
    for i:= 1 to 100 do begin 
     im:= ImageControl1; 
     Scanline := PAlphaColorArray(Bitmap1.StartLine); 
     for x := 0 to Bitmap1.Width * Bitmap1.Height do 
     ScanLine[x] := Random(MaxInt); 
     ImageControl1.Canvas.BeginScene; 
     ImageControl1.Canvas.DrawBitmap(Bitmap1, RectF(0,0,Bitmap1.Width, Bitmap1.Height) 
            ,im.ParentedRect,1,true); 
     ImageControl1.Canvas.EndScene; 
    end; 
finally 
    Bitmap1.Free; 
end; 
end; 

Usunięto:

  • nazywając tryfinally w pętli

  • tworzenia TBitmap w pętli

  • nazywając TBitmap.ScanLine metoda

+1

Naprawiłem oczywiste błędy, ale płótno nie jest aktualizowane za każdym razem przez 'i'. Czy nie musimy martwić się dopełnieniem bitmap FireMonkey? Możesz także wziąć 'im: = ImageControl1;' z pętli. Spróbuj dodać 'Bitmap1.UpdateHandles;', aby zaktualizować bitmapę. –

+0

dziękuję, nie mam teraz XE2. Następną opcją jest próba umieszczenia 'TImage' na formularzu i' Image1.Bitmap: = Bitmap1; 'dla operacji kopiowania bufora. –

+1

To zajmuje dokładnie tyle samo czasu, ale tak naprawdę nie działa. Nie działa tak samo, jak kod w pytaniu. –

-1

Oto szybszy sposób, aby to zrobić:

 procedure TForm2.Button1Click(Sender: TObject); 
    var i,j: integer; 
    begin 
     for i := 0 to 200 do 
     for j := 0 to 200 do ImageControl1.Bitmap.ScanLine[i][j]:=Random(Maxlongint); 
     ImageControl1.Bitmap.BitmapChanged; 
    end; 

Szybkie i zoptymalizowane ...

+0

Czym to się różni od kodu, który już napisałem powyżej? – Johan

Powiązane problemy