![]() |
Bitmap mit Zlib speichern und laden
hallo,
ich möchte in einen Filestream meine Daten schreiben, darunter wie der Titel schon sagt auch Bilder. Um die Größe der Datei zu verringern verwende ich die ZLibEx-Unit (Zlib 1.2.3). Wenn ich meine Daten ohne Bilder speichere und dann lade, funktioniert das ganze. Wenn ich jetzt aber auch Bilder speichere, dann kommt beim Laden immer eine AV! Ich hab hier im Forum nur den Hinweis gelesen, dass angeblich LoadFromStream bis zum Ende des Streams ließt. Wenn dem so wäre, ist natürlich klar worans liegt ;-)... hier mal mein Code:
Delphi-Quellcode:
ps: ich hab den code auf das Wesentliche reduziert, das sollte auch die case-schleife und die
procedure Speichere(const DateiName: string);
var Datei: TFileStream; Zipper: TZCompressionStream; Grafik: TGraphic; begin //... Fehlerüberprüfungen try //Datei erzeugen, bzw. leeren Datei := TFileStream.Create(Dateiname, fmCreate, fmShareExclusive) //Zipper erzeugen und mit "Datei" verknüpfen Zipper := TZCompressionStream.Create(Datei, zcMax); try //... Infos und Anzahl der gespeicherten Bilder schreiben for b := 1 to AnzahlBilder do try Grafik := TBitmap.Create; with Grafik as TBitmap do begin LoadFromFile(GrafikPfad[b - 1]); SaveToStream(Zipper); end; finally FreeAndNil(Grafik); end; except //... Fehlerbehandlung end; finally //Zipper wieder freigeben FreeAndNil(Zipper); //Datei wieder freigeben FreeAndNil(Datei); end; end; procedure Lade(const DateiName: string); var Datei: TFileStream; EntZipper: TZDecompressionStream; begin try //Datei zum Lesen öffnen Datei := TFileStream.Create(Dateiname, fmOpenRead, fmShareExclusive) //EntZipper erzeugen und mit "Datei" verknüpfen EntZipper := TZDecompressionStream.Create(Datei); try //... Infos und Anzahl der gespeicherten Bilder auslesen for b := 1 to AnzahlBilder do begin Grafiken[b - 1] := TBitmap.Create; with (Grafiken[b - 1] as TBitmap) do LoadFromStream(EntZipper); //<--- HIER DER FEHLER!!! end; except //... Fehlerbehandlung end; finally //EntZipper wieder freigeben FreeAndNil(EntZipper); //Datei wieder freigeben FreeAndNil(Datei); end; end; end. Verwendung von TGraphic statt TBitmap erklären... pps: die anderen Werte schreibe ich mit Zipper.Read(Variable, SizeOf(Variable)) und lese sie so auch wieder |
Re: Bitmap mit Zlib speichern und laden
Zitat:
Du musst dir zum Bitmap noch irgendwie die Größe merken und gesondert laden. Grob umrissen:
Delphi-Quellcode:
Also da muss noch try-finally rein, etc dürfte aber das grobe System erklären.
var
MemStream: TMemoryStream; Groese: integer; begin Entzipper.Read(Groese, sizeof(Groese)); MemStream := TMemoryStream.Create; MemStream.LoadFromStream(EntZipper, Groese); MemStream.Position := 0; Bitmap.LoadFromStream(MemStream); |
Re: Bitmap mit Zlib speichern und laden
tja, wenn so einfach is...
is natürlich naheliegend - ich hatte auch schon mal die größe des Bildes mitgespeichert, dann aber aus irgendeinem Grund gedacht, sie sei überflüssig - nicht denken :mrgreen: danke für die schnelle Hilfe, heiopei |
Re: Bitmap mit Zlib speichern und laden
eine Frage dazu hätte ich noch:
wie kann ich die richtige Größe des TGraphic-Objekts ermitteln? Mit SizeOf wohl kaum. mfg, heiopei EDIT: mir ist grad eingefallen, dass ich ja auch mit nem MemoryStream das Bild speichere... Da brauch ich ja dann nur die Größe des Stream :wall: :wall: :wall: :!: |
Re: Bitmap mit Zlib speichern und laden
hallo,
funktioniert doch nicht wie ichs mir gedacht hab. mir ist ein Fehler im Code von H4ndy aufgefallen:
Delphi-Quellcode:
es gibt kein LoadFromStream, bei dem ein weiterer Größenparameter angegeben werden kann
begin
Entzipper.Read(Groese, sizeof(Groese)); MemStream := TMemoryStream.Create; [color=#ff001f]MemStream.LoadFromStream(EntZipper, Groese);[/color] MemStream.Position := 0; Bitmap.LoadFromStream(MemStream); ich hab das Bild in einen MemoryStream geladen, dann die Größe des Streams mit MemStream.Size ermittelt und in den Zipper geschrieben und danach mit MemStream.SaveToStream(Zipper) das "Bild" gespeichert.
Delphi-Quellcode:
Das funktioniert auch, nur ob es wirklich richtig ist, bezweifle ich da ich beim Auslesen die Fehlermeldung "invalid Bitmap..." erhalte.
...
MemStream := TMemoryStream.Create; ... Bild.SaveToStream(MemStream); TempI64 := MemStream.Size; Zipper.Write(TempI64, SizeOf(TempI64); MemStream.SaveToStream(Zipper); ... FreeAndNil(MemStream); Beim Lesen ermittle ich erstmal die Größe des MemStreams. Dann Lade ich den Stream. Allerdings weis ich nicht, welche die richtigere Methode zum Laden wäre:
Delphi-Quellcode:
geht es nicht doch irgendwie das ganze auch ohne den umständlichen MemoryStream-Weg zu lösen. Bei einem TFileStream funktioniert das ganze - erst bei der Verwendung von der ZLibEx / Zlib tritt der Fehler auf!!
...
MemStream := TMemoryStream.Create; ... EntZipper.Read(TempI64, SizeOf(TempI64)); //welche Methode ist die richtige? MemStream.LoadFromStream(EntZipper); // Dann bräuchte ich aber die Größenangabe nicht, oder muss // ich erst mit SetSize die Größe bestimmen??? MemStream.CopyFrom(EntZipper, TempI64); ... Bild.LoadFromStream(MemStream); ... FreeAndNil(MemStream); danke für hilfe, heiopei |
Re: Bitmap mit Zlib speichern und laden
Sorry, dass ich mich erst so spät zurück melde :oops:
Beim ersten Post ist mir leider ein Flüchtigkeitsfehler unterlaufen. Wie du schon bemerkt hast, musst du MemoryStream.CopyFrom(Entzipper, Groeße); nehmen. Soweit ich das beurteilen kann müsste es theoretisch gehen. Der Umweg über einen temporären Stream (MemoryStream) musst leider bei Verwendung einen ZStreams gehen, da du eben nur immer kleine Stückchen aus dem gesammten liest. Ich versuche nachher nochmal dein Problem bei mir im Delphi zu lösen, wenn ich das weiterhin aus dem Kopf heraus versuche, könnte es kompliziert werden ;) [EDIT] OK, das hat mich jetzt nicht losgelassen ^^ Ich hatte jetzt leider nur die Borland zLib, du musst also ab und zu die Parameter etwas angleichen. Folgender Code funktioniert bei mir.
Delphi-Quellcode:
var MemStream: TMemoryStream; // oder FileStream, etc - zum Speichern & Lesen
tmpMemStream: TMemoryStream; // zum arbeiten comStream: TCompressionStream; decomStream: TDecompressionStream; bmp: TBitmap; // Test-Bitmap Groesse: integer; begin MemStream := TMemoryStream.Create; try bmp := TBitmap.Create; try bmp.Width := 250; bmp.Height := 250; // packen tmpMemStream := TMemoryStream.Create; try bmp.SaveToStream(tmpMemStream); Groesse := tmpMemStream.Size; comStream := TCompressionStream.Create(clDefault, MemStream); try comStream.Write(Groesse,sizeof(Groesse)); // Größe speichern comStream.CopyFrom(tmpMemStream,0); // Bitmap speichern finally comStream.Free; // Unbedingt nötig, bevor man weiterarbeitet! (Damit der Puffer des Streams 100%ig gespeichert) end; finally tmpMemStream.Free; end; finally bmp.Free; end; bmp := TBitmap.Create; try // entpacken MemStream.Position := 0; tmpMemStream := TMemoryStream.Create; try decomStream := TDecompressionStream.Create(MemStream); try decomStream.Read(Groesse,sizeof(Groesse)); // Größe lesen tmpMemStream.CopyFrom(decomStream,Groesse); // Bitmap entpacken tmpMemStream.Position := 0; bmp.LoadFromStream(tmpMemStream); // Bitmap laden finally decomStream.Free; end; finally tmpMemStream.Free; end; finally bmp.Free; end; finally MemStream.Free; end; |
Re: Bitmap mit Zlib speichern und laden
mittach,
vielen Dank für die Hilfe H4ndy!!! Super... ich werds jetzt bei mir ausprobieren- wenns Fehler gibt, meld ich mich ;-) mfg, heiopei ps: warum ließt LoadFromStream die Daten aus einem TFileStream/TMemoryStream richtig aus, aber aus einem TDecompressionStream nicht. Erhält man nur die dekodierten (entpackten) Werte, wenn man mit Read, etc. arbeitet?!? anscheinend... |
Re: Bitmap mit Zlib speichern und laden
Zitat:
Ok eigentlich nicht, dann er gibt die Größe der gezippten Daten an. Wenn du was von dieem Stream liest, dann entpackt er die Daten erst zu diesem Zeitpunkt weshalb man wissen muss viele Daten man jetzt auszulesen hat. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz