Chcę wyodrębnić ramki obrazu GIF. Poniższy kod działa, ale to nie jest to, czego potrzebuję. Muszę zachować wyodrębnione ramki w serii bitmap.Nie można narysować GIF na dynamicznie utworzonym TBitmap (ach)
procedure TForm1.Button2Click(Sender: TObject);
var
GIF: TGIFImage;
Bitmap: TBitmap;
I: Integer;
GR: TGIFRenderer;
R: TRect;
begin
GIF := TGIFImage.Create;
TRY
GIF.LoadFromFile('c:\1.gif');
Bitmap := TBitmap.Create; <------------ one single object, reused
Bitmap.SetSize(GIF.Width, GIF.Height);
GR := TGIFRenderer.Create(GIF);
try
for I := 0 to GIF.Images.Count - 1 do
begin
GR.Draw(Bitmap.Canvas, Bitmap.Canvas.ClipRect);
Self.Canvas.Draw(0, 0, Bitmap);
GR.NextFrame;
end;
finally
GR.Free;
end;
finally
GIF.Free;
//Bitmap.Free;
end;
end;
Dlatego dynamicznie tworzę mapę bitową dla każdej ramki. Ale to nie zadziała. Wyświetli tylko tę samą/pierwszą klatkę we wszystkich bitmapach!
procedure TForm1.Button2Click(Sender: TObject);
var
GIF: TGIFImage;
Bitmap: TBitmap;
I: Integer;
GR: TGIFRenderer;
R: TRect;
begin
GIF := TGIFImage.Create;
TRY
GIF.LoadFromFile('c:\1.gif');
GR := TGIFRenderer.Create(GIF);
try
for I := 0 to GIF.Images.Count - 1 do
begin
Bitmap := TBitmap.Create; <----- multiple bitmaps, one for each frame
Bitmap.SetSize(GIF.Width, GIF.Height);
GR.Draw(Bitmap.Canvas, Bitmap.Canvas.ClipRect);
Self.Canvas.Draw(0, 0, Bitmap);
GR.NextFrame;
end;
finally
GR.Free;
end;
{TODO: store bitmaps in a TObjectList for later use
List.Add(Bitmap); }
finally
GIF.Free;
end;
end;
Co jest nie tak z powyższym kodem? Może TGIFRenderer rysuje TYLKO różnice między ramkami?
UPDATE dla TLama/jachguate:
TLama mówi, że kod nie działa, bo nie uwolnić bitmap. Nie chcę zwolnić bitmap. Potrzebuję ich później. Oto kilka (klasy demo) kodu.
VAR List: TObjectList; {used and freed somwhere else}
procedure TForm1.Button2Click(Sender: TObject);
var
GIF: TGIFImage;
UniqueBMP: TBitmap;
I: Integer;
GR: TGIFRenderer;
R: TRect;
begin
List:= TObjectList.Create;
GIF := TGIFImage.Create;
TRY
GIF.LoadFromFile('c:\1.gif');
GR := TGIFRenderer.Create(GIF);
try
for I := 0 to GIF.Images.Count - 1 do
begin
UniqueBMP := TBitmap.Create;
UniqueBMP.SetSize(GIF.Width, GIF.Height);
if GIF.Images[I].Empty then Break;
GR.Draw(UniqueBMP.Canvas, UniqueBMP.Canvas.ClipRect);
Self.Canvas.Draw(0, 0, UniqueBMP);
Sleep(50);
List.Add(UniqueBMP);
GR.NextFrame;
end;
finally
GR.Free;
end;
finally
GIF.Free;
end;
end;
procedure TForm1.btnFreeClick(Sender: TObject);
begin
FreeAndNil(List);
end;
WIEM! Zignoruj to! To tylko wersja demo. Nie ma to związku z naszym aktualnym problemem :) – Ampere
Nic nie wyjaśnia, ale podejrzewam, że przeplatałam klatkę. Domyślam się, że renderer rysuje ramkę dokładnie tak, jak jest (dlaczego by tak nie było, a ponieważ zawsze używasz nowej mapy bitowej dla każdej ramki, możesz uzyskać (wizualnie) prawie pustą bitmapę, ponieważ (wzrokowo) reszta musi być renderowana przez leżące poniżej ramy. Innymi słowy, musisz użyć jednej bitmapy i pozwolić rendererowi narysować dla ciebie warstwy. Ale to tylko moje przypuszczenie. – TLama
@TLama - Myślałem o tym samym, ale obraz GIF, którego używam, jest dość animowany. Istnieje wiele różnic między ramkami. Powinienem móc zobaczyć coś w następnych klatkach ... – Ampere