AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Bitmap mit Zlib speichern und laden
Thema durchsuchen
Ansicht
Themen-Optionen

Bitmap mit Zlib speichern und laden

Ein Thema von heiopei · begonnen am 21. Jun 2006 · letzter Beitrag vom 23. Jun 2006
Antwort Antwort
heiopei
(Gast)

n/a Beiträge
 
#1

Bitmap mit Zlib speichern und laden

  Alt 21. Jun 2006, 11:37
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:
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.
ps: ich hab den code auf das Wesentliche reduziert, das sollte auch die case-schleife und die
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
  Mit Zitat antworten Zitat
Benutzerbild von H4ndy
H4ndy

Registriert seit: 28. Jun 2003
Ort: Chemnitz
515 Beiträge
 
Delphi XE3 Professional
 
#2

Re: Bitmap mit Zlib speichern und laden

  Alt 21. Jun 2006, 11:49
Zitat von heiopei:
[...]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 ...

ps: ich hab den code auf das Wesentliche reduziert, das sollte auch die case-schleife und die
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
Du hast dein Problem schon selbst gelöst
Du musst dir zum Bitmap noch irgendwie die Größe merken und gesondert laden.
Grob umrissen:
Delphi-Quellcode:
var
MemStream: TMemoryStream;
Groese: integer;
begin

Entzipper.Read(Groese, sizeof(Groese));
MemStream := TMemoryStream.Create;
MemStream.LoadFromStream(EntZipper, Groese);

MemStream.Position := 0;
Bitmap.LoadFromStream(MemStream);
Also da muss noch try-finally rein, etc dürfte aber das grobe System erklären.
Manuel
  Mit Zitat antworten Zitat
heiopei
(Gast)

n/a Beiträge
 
#3

Re: Bitmap mit Zlib speichern und laden

  Alt 21. Jun 2006, 11:54
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

danke für die schnelle Hilfe,
heiopei
  Mit Zitat antworten Zitat
heiopei
(Gast)

n/a Beiträge
 
#4

Re: Bitmap mit Zlib speichern und laden

  Alt 21. Jun 2006, 12:08
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
  Mit Zitat antworten Zitat
heiopei
(Gast)

n/a Beiträge
 
#5

Re: Bitmap mit Zlib speichern und laden

  Alt 21. Jun 2006, 15:31
hallo,
funktioniert doch nicht wie ichs mir gedacht hab.

mir ist ein Fehler im Code von H4ndy aufgefallen:
Delphi-Quellcode:
  begin
    Entzipper.Read(Groese, sizeof(Groese));
    MemStream := TMemoryStream.Create;
    [color=#ff001f]MemStream.LoadFromStream(EntZipper, Groese);[/color]

    MemStream.Position := 0;
    Bitmap.LoadFromStream(MemStream);
es gibt kein LoadFromStream, bei dem ein weiterer Größenparameter angegeben werden kann


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:
  ...
  MemStream := TMemoryStream.Create;
  ...
  Bild.SaveToStream(MemStream);
  TempI64 := MemStream.Size;
  Zipper.Write(TempI64, SizeOf(TempI64);
  MemStream.SaveToStream(Zipper);
  ...
  FreeAndNil(MemStream);
Das funktioniert auch, nur ob es wirklich richtig ist, bezweifle ich da ich beim Auslesen die Fehlermeldung "invalid Bitmap..." erhalte.

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:
  ...
  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);
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!!

danke für hilfe,
heiopei
  Mit Zitat antworten Zitat
Benutzerbild von H4ndy
H4ndy

Registriert seit: 28. Jun 2003
Ort: Chemnitz
515 Beiträge
 
Delphi XE3 Professional
 
#6

Re: Bitmap mit Zlib speichern und laden

  Alt 23. Jun 2006, 08:34
Sorry, dass ich mich erst so spät zurück melde

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;
Manuel
  Mit Zitat antworten Zitat
heiopei
(Gast)

n/a Beiträge
 
#7

Re: Bitmap mit Zlib speichern und laden

  Alt 23. Jun 2006, 13:40
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...
  Mit Zitat antworten Zitat
Benutzerbild von H4ndy
H4ndy

Registriert seit: 28. Jun 2003
Ort: Chemnitz
515 Beiträge
 
Delphi XE3 Professional
 
#8

Re: Bitmap mit Zlib speichern und laden

  Alt 23. Jun 2006, 13:48
Zitat von 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...
Soweit ich weiss ist ein DecompressionStream größer als er nach außen hin angibt.
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.
Manuel
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz