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