Einzelnen Beitrag anzeigen

Rollo62

Registriert seit: 15. Mär 2007
3.914 Beiträge
 
Delphi 12 Athens
 
#8

AW: [Fmx, Vcl] Verhalten von TBitmap in Threads

  Alt 13. Apr 2016, 14:52
Hier ist mal ein kleiner Test.

@Sir Rufo
Als Basis habe ich deinen TBitmapProducerThread gefunden und ich habe versucht das zusammen mit einer ImageList auszuprobieren.
Der TBitmapProducerThread war wohl nur für VCL gedacht, aber auch mit FMX könnte das ja Laufen ?!

Ich erzeuge im Thread neue Bitmaps, die ich dann in die ImageList speichere
- Thread Erzeugen eines leeren Bitmaps
- UI-Thread per Syncronize Ändern der Größe (das wird mit dem Canvas in Berührung kommen)
- UI-Thread Übergabe des neuen Bitmaps

Im DoProduce rufe ich das ändernde SetSize mit Synchronize auf, und ändere dann mit Map/Unmap.
Anders komme ich doch an die Pixel nicht heran, ich könnte es noch mit Scanline probieren aber
Map/Unmap brauche ich womöglich trotzdem.

Delphi-Quellcode:
procedure TBitmapProducerThread.DoProduce(const LBitmap : TBitmap; LParams : TBitmapParameters);
var
  Data: TBitmapData;
  I: Integer;
  col: TAlphaColor;
begin

  TThread.Synchronize(nil,
                      procedure
                      begin
                        // This must be in Main Thread, to be treadsafe
                        LBitmap.Width := LParams.Width;
                        LBitmap.Height := LParams.Height;
                      end
                     );

  // Bitmap erstellen
  if LBitmap.Map(TMapAccess.ReadWrite, Data) then
  begin

    col := TAlphaColorF.Create(128+Random(127), 128+Random(127), 128+Random(127)).ToAlphacolor;

    // // 5000 xxx Pixel auf ein Bitmap malen
    for I := 1 to 5000 do
    begin
      Data.SetPixel(Random( LBitmap.Width ), //Muss noch Scanline probieren, als Alternative
                    Random( LBitmap.Height ),
                    col //TAlphaColorRec.Red
                   );
    end;

    LBitmap.Unmap(Data);
  end;

end;
Unter Windows läuft alles gut bis jetzt,
unter OSX gab es schon Exception, geht aber auch meistens
und unter Android geht es gar nicht.
Unter iOS habe ichs noch garnicht versucht ...

Aber zumindest habe ich mal getestet wie man Bitmaps einer ImageList zuordnen kann, über den Namen:
Delphi-Quellcode:
//
// wird von TBitmapProducerThread aufgerufen, im UI-Thread
//
procedure TForm1.EvOnBmpProdOutputChanged(Sender: TObject);
var
  isi: TSourceItem;
  mbi: TBitmapItem;
  idi: TDestinationItem;
  di: TDestinationItem;
  lay: TLayer;
  sX: string;
  bmi: TBitmapItem;
  ms: TMemoryStream;
  bmp: TBitmap;

begin

  bmp := TBitmap.Create;

  try
    FBmpProd.Get( bmp ); // Hier wird die Bitmap aus dem Thread geholt

    // Und hier wird ein Neuer ImageList-Eintrag angelegt
    isi := ImageList1.Source. Add as TSourceItem;
    if isi.MultiResBitmap.Count = 0 then
    begin
      bmi := isi.MultiResBitmap.Add as TBitmapItem;

      ms := TMemoryStream.Create;

      try
        bmp.SaveToStream( ms );
        ms.Position := 0;

        bmi.Bitmap.CreateFromStream( ms );

      finally
        ms.Free;
      end;

    end;

    sX := isi.Name;
    idi := ImageList1.Destination.Add as TDestinationItem;
    lay := idi.Layers.Add;
    lay.Name := sX; // Setup the link the the Source Bitmap here
    sX := lay.Name;
    lay.SourceRect.Rect := RectF(0, 0, 256, 256); // Region within the soure-Rect

  finally
    bmp.Free;
  end;

  ScrollBar1.Max := ImageList1.Destination.Count-1;
end;

Benutzung:
Append/Insert/Delete/Clear - Legt Items im Listview an, und benutzt ImageList als Basis.
Das geht recht fix, so das man keinen Thread braucht (ich zumindest noch nicht)).

Produce erzeugt neue Bitmaps in dem ImageView, die ich dann s.o. zum Erzeugen benutzen kann.


Rollo
Angehängte Dateien
Dateityp: zip S002_ImageListMag.zip (629,6 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat