2012-01-24 32 views
7

he hecho el siguiente código:La forma más rápida para dibujar píxeles en 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; 

¿Hay una manera más rápida para dibujar píxeles en FireMonkey?
Mi objetivo es hacer un programa de demostración utilizando el juego de la vida de Conway.

+0

¿Cuál es su versión de FireMonkey? En Berlín 10.1, el código no funciona. –

Respuesta

6

Todo el tiempo se dedica a la realización de estas dos líneas de código:

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

Puede eliminar todo el código que funciona con el mapa de bits y el código que realmente dibuja el mapa de bits y no hace ni un ápice de diferencia en el tiempo de ejecución. En otras palabras, el cuello de botella es el código de escena, no el código de mapa de bits. Y no veo forma de que optimices eso.

Mi código de prueba veía así:

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

Esto tiene el mismo tiempo transcurrido como su código, 1600ms en mi máquina. Si elimina las llamadas BeginScene, DrawBitmap y EndScene, su código se ejecutará en 3ms en mi máquina.

+0

Después de la prueba, resulta que el par 'startscene-endscene' es esencial. Si ** eso ** ocupa todo el tiempo de ejecución, estoy atascado.Echaré un vistazo al código fuente de begin- y endingcene y veré qué está consumiendo todo ese tiempo de ejecución, creo que hay algún código de protección de threading allí (sección crítica o cosas por el estilo) que está ralentizando las cosas. – Johan

+0

Una sección crítica no te ralentizará en una sola aplicación con subprocesos. 70fps parece un poco malo para una aplicación de robar nada. –

-2

Usted puede optimizar su código como este:

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; 

Eliminado:

  • llamando tryfinally en bucle

  • crear TBitmap en bucle

  • llamando TBitmap.ScanLine método

+1

He reparado algunos errores obvios, pero el lienzo no se actualiza cada vez a través de 'i'. ¿No tenemos que preocuparnos por el relleno de los mapas de bits de FireMonkey? También podría tomar 'im: = ImageControl1;' fuera del ciclo. Intente agregar 'Bitmap1.UpdateHandles;' para actualizar el mapa de bits. –

+0

gracias, no tengo XE2 ahora. La siguiente opción es tratar de poner 'TImage' en la forma y' Image1.Bitmap: = Bitmap1; 'para la operación de copia de búfer. –

+1

Eso lleva exactamente la misma cantidad de tiempo pero en realidad no funciona. No hace lo mismo que el código en la pregunta. –

-1

Aquí es una forma más rápida de hacerlo:

 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; 

rápida y optimizada ...

+0

¿En qué se diferencia esto del código que ya publiqué anteriormente? – Johan

Cuestiones relacionadas