Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Bitmap speichern mit File of MyRecord (https://www.delphipraxis.net/100119-bitmap-speichern-mit-file-myrecord.html)

Jackie1983 22. Sep 2007 15:32


Bitmap speichern mit File of MyRecord
 
hi,

versuche ein Bitmap zu speichern, nur leider funktioniert das irgend wie nicht.
Hier mal mein Code
Delphi-Quellcode:
Type
  rNetDevice = record
    Typ,
    PositionX,
    PositionY : integer;
    Bitmap : TBitmap;
  end;
...

Procedure Save;
var
  Datei : File of rNetDevice;
  Datensatz : rNetDevice;
begin
  AssignFile(Datei,fName);
  Reset(Datei);
  Seek(Datei, 0);
  // zum Dateianfang
  for i:=0 to fObjList.Count-1 do begin
    device := TNetDevice(fObjList.Objects[i]);
    Datensatz.Typ := 0;
    Datensatz.PositionX := device.Position.x;
    Datensatz.PositionY := device.Position.y;
    Datensatz.Bitmap := TBitmap.Create;
    Datensatz.Bitmap.Width := device.Bitmap.Width;
    Datensatz.Bitmap.Height := device.Bitmap.Height;
    Datensatz.Bitmap.canvas.Draw(0,0,device.Bitmap);
    Write(Datei, Datensatz);
  end;

  CloseFile(Datei);
end;
Hat jemand eine idee?

jfheins 22. Sep 2007 16:14

Re: Bitmap speichern mit File of MyRecord
 
Ja: dein Record hat keine Feste Länge (wenn man das Bitmap einbezieht) bzw. es wird nur ein Zeiger auf das Bitmap gespeichert, der nachher nicht mehr gültig ist.

Lösung: eine ordentliche Dateistruktur verwenden:

Wenn du viele Klassen hast, empfehle ich dir die Hier im Forum suchendpcollection, sonst eben ne Binärdatei mit eigenem Dateiformat, oder ne xml (ini) datei ;)

turboPASCAL 22. Sep 2007 16:54

Re: Bitmap speichern mit File of MyRecord
 
Dein Bitmap was du versuchst zu speichern ist im eigentlichem Sinn sur ein Zeiger auf einen
bestimten Punkt im Speicher.
Wenn du nun dein Bitmap in die Datei schreiben möchtest busst du wohl oder übel die realen
RGB-Daten deines Bitmaps speichern. Baue dir dazu ein Array, lies die RGB-Daten über Scanline ein
und speicher dann das Array. Die Grösse des must du nun auch speichern.

Du kannst natürlich auch einen anderen Weg nutzen, TBitmap unterstützt das speichen in Streams.
Das ist etwas eleganter und einfacher.

Das sähe in etwa so aus:
Delphi-Quellcode:
procedure ...
var
  nd: rNetDevice;
  Temp: TMemoryStream;
  i: integer;
  B: Byte;
begin
  nd.Typ := 1;
  nd.PositionX := 2;
  nd.PositionY := 3;

  Temp := TMemoryStream.Create;
  Image1.Picture.Bitmap.SaveToStream(Temp);

  nd.BitmapLength := Temp.Size;
  SetLength(nd.Bitmap, nd.BitmapLength + 1);

  Temp.Position := 0;
  for i := 0 to nd.BitmapLength -1  do
  begin
    Temp.Read(B, 1);
    nd.Bitmap[i] := B;
  end;

  Temp.Free;
end;

Jackie1983 22. Sep 2007 18:13

Re: Bitmap speichern mit File of MyRecord
 
Zitat:

Zitat von turboPASCAL
Delphi-Quellcode:
procedure ...
var
  nd: rNetDevice;
  Temp: TMemoryStream;
  i: integer;
  B: Byte;
begin
  nd.Typ := 1;
  nd.PositionX := 2;
  nd.PositionY := 3;

  Temp := TMemoryStream.Create;
  Image1.Picture.Bitmap.SaveToStream(Temp);

  nd.BitmapLength := Temp.Size;
  SetLength(nd.Bitmap, nd.BitmapLength + 1);

  Temp.Position := 0;
  for i := 0 to nd.BitmapLength -1  do
  begin
    Temp.Read(B, 1);
    nd.Bitmap[i] := B;
  end;

  Temp.Free;
end;

was ist nd.Bitmap für ein Typ?

turboPASCAL 22. Sep 2007 18:59

Re: Bitmap speichern mit File of MyRecord
 
Asso, ja...

Delphi-Quellcode:
Type
  rNetDevice = record
    Typ,
    PositionX,
    PositionY : integer;
    Bitmap : Array of Byte;
    BitmapLength; Cardinal;
  end;

Jackie1983 22. Sep 2007 19:46

Re: Bitmap speichern mit File of MyRecord
 
thx

Jackie1983 12. Okt 2007 00:23

Re: Bitmap speichern mit File of MyRecord
 
habe es jetzt so gemacht wie oben

speichern
Delphi-Quellcode:
var
  i,m : integer;
  file_device_info : File of TNetDeviceInfo;
  s : TMemoryStream;
  b : byte;
begin
  AssignFile(file_device_info,'test.dat');
  for i:=0 to NetStruktur.Devices.Count-1 do begin
    s := TMemoryStream.Create;
    device_info := pNetDeviceInfo(NetStruktur.Devices.Objects[i]);
    device_info.fDesigner.fBitmap.SaveToStream(s);
    for m:=0 to device_info.fDesigner.fBitmapLength -1 do
    begin
      s.Read(b,1);
      device_info.fDesigner.fBitmapArray[m] := b;
    end;
    Write(file_device_info,device_info);
    s.free;
  end;
  CloseFile(file_device_info);
end;
das laden
Delphi-Quellcode:
var
  file_device_info : File of TNetDeviceInfo;
  b : Byte;
  m : TMemoryStream;
begin
  AssignFile(file_device_info,'test.dat');
  Reset(file_device_info);
  while not eof(file_device_info) do
  begin
    device_info := NetStruktur.CreateNewDevice;
    m := TMemoryStream.Create;
    Read(file_device_info,device_info);
    for i:=0 to device_info.fDesigner.fBitmapLength - 1 do
    begin
      b := device_info.fDesigner.fBitmapArray[i];
      m.Write(b,1);
    end;
    device_info.fDesigner.fBitmap.LoadFromStream(m);
    m.Free;
  end;
  CloseFile(file_device_info);
end;
nur wenn ich das bild speicher ist das bild leer.
Aber in fBitmapArray stehen zahlen
Habe ich was falsch gemacht?

Jackie1983 12. Okt 2007 02:16

Re: Bitmap speichern mit File of MyRecord
 
na super habe nur
m.Position :=0;
vergessen :wall:

Lossy eX 12. Okt 2007 08:35

Re: Bitmap speichern mit File of MyRecord
 
Also mich wundert da gerade etwas. Ein dynamisches Array ist doch eigentlich auch nichts anderes als ein Pointer. Somit hast du lediglich den Pointer des Bitmaps gegen einen Anderen ausgetauscht. Und eigentlich müssen die Records auch immer die gleiche Größe haben wenn ich mich recht entsinne. Und wenn du variable Speicherbereiche (Bitmaps) hast lässt sich so etwas nur schwer realisieren.

Ich würde dir da besser empfehlen, dass du es eher folgendermaßen erledigst. Lass das File of und benutzt die Klasse TStream. Für Dateien dann die Ableitung TFileStream. Zu mal du dann auch das Bitmap direkt laden kannst. Bzw könnte der Stream dann auch woanders herkommen. Zum Beispiel Indy, Memorystream etc.
Delphi-Quellcode:
Type
  TNetDeviceInfo = packed record
    Typ,
    PositionX,
    PositionY : integer;
    BitmapLength: Cardinal;
    Bitmap: TBitmap;
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  ND: TNetDeviceInfo;
  FS: TFileStream;
begin
  FS := TFileStream.Create('test.dat', fmOpenRead);
  try
    // Hier wichtig. Beschreibung siehe unten.
    FS.Read(ND, SizeOf(ND) - SizeOf(TBitmap));

    ND.Bitmap := TBitmap.Create;
    ND.Bitmap.LoadFromStream(FS);
  finally
    FS.Free;
  end;
end;
Das Bitmap hängt nur im Record, da es mit dazu gehört. Es soll aber nicht in die Datei geschrieben oder aus ihr gelesen werden. Evtl. würde ich da überlegen das TNetDeviceInfo noch mal zu kappseln und das record jetzt als Header zu sehen. Sonst kann es schnell mal passieren, dass du den Pointer des Bitmaps doch mal mit schreibst. Ist nur für die Sicherheit.

Beim Schreiben solltest du das Bitmap aber trotzdem noch in einen MemoryStream packen, da du die Größe wahrscheinlich benötigen wirst. Ansonsten weißt du nicht an welche Stelle du hingehen müsstest um das nächste Record zu lesen ohne, dass du das Bitmap komplett einlesen lässt. So kannst du es einfach überspringen.

Bei Records die mit Dateien oder Speicherblöcken zu tun haben solltest du immer packed benutzen. Das sorgt dafür, dass Delphi das Record nicht automatisch erweitert. Sonst kann es passieren, dass du nicht benutzten Speicher in der Datei hast der so nicht beabsichtig ist. Wenn sich dann jemand anderes ausversehen genau an die Spezifikation hält geht es nicht mehr.

Muetze1 12. Okt 2007 10:30

Re: Bitmap speichern mit File of MyRecord
 
Zitat:

Zitat von Lossy eX
Also mich wundert da gerade etwas. Ein dynamisches Array ist doch eigentlich auch nichts anderes als ein Pointer. Somit hast du lediglich den Pointer des Bitmaps gegen einen Anderen ausgetauscht. Und eigentlich müssen die Records auch immer die gleiche Größe haben wenn ich mich recht entsinne. Und wenn du variable Speicherbereiche (Bitmaps) hast lässt sich so etwas nur schwer realisieren.

1. Speichert er die Bilddatenlänge in dem File (fDesigner.fBitmapLength)
2. Speichert er die Bilddaten direkt byteweise aus dem MemoryStream, in dem das Bitmap gespeichert wurde (SaveToStream)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:51 Uhr.
Seite 1 von 2  1 2      

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