Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Bitmaps archivieren und laden? (https://www.delphipraxis.net/100350-bitmaps-archivieren-und-laden.html)

Sunlight7 27. Sep 2007 01:09

Re: Bitmaps archivieren und laden?
 
Moin!

Kannst Du wirklich nicht direkt auf das Zielbitmap zugreifen?

Also ich hatte eine ähnliche Situation beim Programmieren eines großen Spieles.
Dazu hab ich "einfach" ein Dateiformat entwickelt, so das die Bitmaps auch gleich komprimiert in eine Datei gespeichert werden.
Dazu wurden gleichen nach dem Dateikopf eine Liste mit den Namen und eine Liste mit den Addresen und Größen in die Datei gespeichert.
Um die Datei aber net immer gleich machen zu müssen guckt der Loader nach, ob eine Datei mit dem gleichen Namen in einem Unterordner gleichen Namens wie die das Archiv heißt existiert und lädt diese falls vorhanden.

Wenn Du tatsächlich nur von Dateien laden kannst, könntest Du ja noch immer die Daten in eine temporäre Datei schreiben und Dir Delphi-Referenz durchsuchenFILE_ATTRIBUTE_TEMPORARY von MSDN-Library durchsuchenCreateFile ansehen.

Grüße, Sunlight7

Rastaman 27. Sep 2007 12:44

Re: Bitmaps archivieren und laden?
 
Hi Sunlight. Das hört sich ja schonmal echt gut an :thumb:
Allerdings scheint das nicht zu klappen :(
Ich hab mal versucht das anzuwenden am Beispiel einer einzigen Bitmap die einfach im Ordner liegt und 3128 Bytes groß ist. Allerdings geht das Programm einfach wieder ohne Meldung aus.
Hier mal nach Delphi übersetzt was ich probiert hab.

Delphi-Quellcode:
var
  hTmp, hBitmap: THandle;
  Buf: Array [0..3127] of Byte;
  Dummy: DWORD;
begin
  // Die Bitmap öffnen
  hBitmap := CreateFile("bitmap2.bmp", FILE_READ_DATA, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nil);
  // Temporäre Datei erstellen
  hTmp := CreateFile("bitmap_tmp.bmp", FILE_READ_DATA or FILE_WRITE_DATA, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, nil);

  ReadFile(hBitmap, Buf, SizeOf(buf), @Dummy, nil);
  WriteFile(hTmp, Buf, Dummy, @Dummy, nil);

  Player (* SDL_Surface *) := SDL_LoadBMP('bitmap_tmp.bmp');
  CloseHandle(hTmp);
  CloseHandle(hBitmap);
Bei dem @ vor den "Dummys" bin ich mir jetzt nicht so sicher.
Was mach ich falsch?

Edit:
Wenn ich anstatt FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE einfach FILE_ATTRIBUTE_NORMAL nehme wird die Bitmap im Projektverzeichnis erstellt
und sieht einwandfrei aus :gruebel:

Edit2 und 3: Übersetzungsfehler beseitigt.

guidok 27. Sep 2007 13:02

Re: Bitmaps archivieren und laden?
 
Hast du schon mal über einen Filestream nachgedacht?

Da könntest du deine Daten hintereinander rein schreiben und auch wieder lesen.

Nachteil ist, da du ja kein "Inhaltsverzeichnis" hast, musst du alle Bitmaps durchgehen bis du das gefunden hast, welches du möchtest.

Also beim Speichern:

1. zuerst einen String mit dem Namen des Bitmap speichern
2. danach das Bitmap selbst abspeichern
3. wieder einen Namen, usw.

Ich habe sowas mal gemacht, weil ich gemischte Daten (u.a. auch Bitmaps) in einer Datei halten wollte. Im Unterschied zu deiner Anforderung lade ich allerdings die gesamte Datei wieder zurück.

Delphi-Quellcode:
procedure TCardset.ReadFromFile(Filename: string);
var
  lFs: TFileStream;
  lMs: TMemoryStream;
  lLen: Longint;
  lI: Integer;
begin
  Free;
  lFs:=TFileStream.Create(Filename,fmOpenRead);
  lMs:=TMemoryStream.Create;
  try
    //Länge des Cardset
    lFS.Read(lLen,SizeOf(lLen));
    SetLength(Cards,lLen);
    //Die Daten des Cardset speichern
    for lI := 0 to Length(Cards) - 1 do begin
      //Bitmap
      lMs.Clear;
      lFs.Read(lLen,SizeOf(lLen));
      lMs.CopyFrom(lFs,lLen);
      Cards[lI].Bitmap:=TBitmap.Create;
      lMs.Position:=0;
      Cards[lI].Bitmap.LoadFromStream(lMs);
      //Strings
      lFs.Read(lLen,SizeOf(lLen));
      SetLength(Cards[lI].Name,lLen);
      lFs.Read(PChar(Cards[lI].Name)^,lLen);
      lFs.Read(lLen,SizeOf(lLen));
      SetLength(Cards[lI].Kind,lLen);
      lFs.Read(PChar(Cards[lI].Kind)^,lLen);
      lFs.Read(lLen,SizeOf(lLen));
      SetLength(Cards[lI].Description,lLen);
      lFs.Read(PChar(Cards[lI].Description)^,lLen);
      lFs.Read(lLen,SizeOf(lLen));
      SetLength(Cards[lI].Action,lLen);
      lFs.Read(PChar(Cards[lI].Action)^,lLen);
    end;
  finally
    lFS.Free;
    lMs.Free;
  end;
end;

procedure TCardset.SaveToFile(Filename: string);
var
  lFs: TFileStream;
  lMs: TMemoryStream;
  lLen: Longint;
  lI: Integer;
begin
  lFs:=TFileStream.Create(Filename,fmCreate);
  lMs:=TMemoryStream.Create;
  try
    //Länge des Cardset
    lLen:=Length(Cards);
    lFs.Write(lLen,SizeOf(lLen));
    //Die Daten des Cardset speichern
    for lI := 0 to Length(Cards) - 1 do begin
      //Bitmap
      lMs.Clear;
      Cards[lI].Bitmap.SaveToStream(lMs);
      lMs.Position:=0;
      lLen:=lMs.Size;
      lFs.Write(lLen,SizeOf(lLen));
      lFs.CopyFrom(lMs,lLen);
      //Strings
      lLen:=Length(Cards[lI].Name);
      lFs.Write(lLen,SizeOf(lLen));
      lFs.Write(PChar(Cards[lI].Name)^,lLen);
      lLen:=Length(Cards[lI].Kind);
      lFs.Write(lLen,SizeOf(lLen));
      lFs.Write(PChar(Cards[lI].Kind)^,lLen);
      lLen:=Length(Cards[lI].Description);
      lFs.Write(lLen,SizeOf(lLen));
      lFs.Write(PChar(Cards[lI].Description)^,lLen);
      lLen:=Length(Cards[lI].Action);
      lFs.Write(lLen,SizeOf(lLen));
      lFs.Write(PChar(Cards[lI].Action)^,lLen);
    end;
  finally
    lFs.Free;
    lMs.Free;
  end;
end;

DP-Maintenance 27. Sep 2007 13:04

DP-Maintenance
 
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Multimedia" verschoben.
Laut Profil nutzt du zwar Turbo C++, doch da hier Delphi-Codes gezeigt werden, verschiebe ich das Thema in eine Delphi-Sparte.

Luckie 27. Sep 2007 13:12

Re: Bitmaps archivieren und laden?
 
Zitat:

Zitat von Rastaman
Zitat:

Zitat von Luckie
Lad das große Bitmap in ein TBitmap und kopier dir dann den Teil, den brauchst, aus dem Canvas des gro0en Bitmaps raus.

Roter Kasten :roll:

Nene so gehts ja nicht. Ist wie bei deinem SFX-Archiven. Die Dateien sind einfach hintereinander weg
gespeichert.

Dann benutz doch mein SFX Archiv, nur eben mit dem Unterschied, dass du die Daten an keine Exe anhängst eben. Meine Klassen solltest du so ohne großartige Änderungen verwenden können.

Rastaman 27. Sep 2007 13:15

Re: Bitmaps archivieren und laden?
 
Hallo guidok.
Ich steig jetz so auf die Schnelle nicht da durch, aber es scheint auch so als würdest du die Datei auf der Platte speichern.
Genau das will ich ja nicht.
Ich habe übringts auch grad rausgefunden, dass FILE_ATTRIBUTE_TEMPORARY genau das Gleiche bewirkt wie FILE_ATTRIBUTE_NORMAL :gruebel:
Ich dachte TEMPORARY legt das irgendwie im Speicher an oder was weiß ich, aber so bringt es mich ja wieder nicht weiter.
Es scheint wirklich keine Möglichkeit zu geben ausser mit temporären Dateien auf der HD :?

Luckie 27. Sep 2007 13:23

Re: Bitmaps archivieren und laden?
 
Zitat:

Zitat von Rastaman
ausser mit temporären Dateien auf der HD :?

Lad das ganze doch in einen Stream, dann kannst du damit machen was du willst.

guidok 27. Sep 2007 13:29

Re: Bitmaps archivieren und laden?
 
Äh, wie? Wo willst du denn deine Datei speichern, wenn nicht auf der Platten?

Ich beschreib mal kurz was ich mache:

In der Datei sollen die Daten für Spielkarten (war mal ne Spielidee) gespeichert werden. Die bestehen aus einem Bitmap und aus diversen Strings. Mein Wunsch war dabei, dass ALLE Karten in EINER Datei gespeichert sind.

Also zum Speichern:

1. Zuerst die Anzahl der Karten abspeichern
2. Die Datenlänge des ersten Bitmap abspeichern (notwendig zum Lesen)
3. Die Daten des Bitmap speichern
4. Die Datenlänge des ersten String abspeichern
5. Die Daten des ersten String abspeichern
6. Alle weiteren Daten einer Karte nach dem gleichen Verfahren abspeichern
7. Bei 2. beginnen, bis alle Karten gespeichert sind

Beim Lesen:

1. Die Anzahl der Karten lesen
2. Die Datenlänge der ersten Bitmap lesen
3. Die Daten des ersten Bitmap mit Hilfe der Datenlänge lesen
4. Die Datenlänge des ersten Strings lesen
5. Die Daten des ersten Strings lesen
6. Alle weiteren Daten einer Karten nach dem gleichen Verfahren lesen
7. Bei 2. beginnen, bis alle Karten gelesen sind

Zum Speichern verwende ich einen FileStream (Datei auf der Platte)
Intern verwende ich einen Memorystream als Puffer für EIN Bitmap, damit ich auf einfach Weise die Länge des Bitmap rauskriege. Das Bitmap bringt nämlich eine Methode "SaveToStream" schon mit. Danach schreibe ich die Daten aus dem Memorystream in den Filestream.

Wenn ich deine Intention richtig verstanden habe, dann möchtest du viele Bitmap in einer Datei speichern, also:

1. Anzahl der Bitmaps in den Stream schreiben
2. Länge des ersten Bitmapnamens schreiben
3. Daten des Bitmapnamens schreiben
4. Länge des ersten Bitmaps schreiben
5. Daten des Bitmaps schreiben
6. Bei 2. beginnen bis alle Bitmaps geschrieben sind

Zum Lesen:

1. Anzahl der Bitmaps im Stream lesen
2. Länge der ersten Namens lesen
3. Namen des ersten Bitmap lesen
4. Vergleichen, ob es der Name des gesuchten Bitmap ist, falls nein:
5. Länge des ersten Bitmap lesen
6. Zeiger des Stream um diese Länge auf den Namen des nächsten Bitmap setzen.
7. usw. usw.

Rastaman 27. Sep 2007 13:31

Re: Bitmaps archivieren und laden?
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von Rastaman
ausser mit temporären Dateien auf der HD :?

Lad das ganze doch in einen Stream, dann kannst du damit machen was du willst.

Ja gut, ich benutz C++ und da geht das schonmal nicht, aber es würd eh nicht klappen,
denn die Funktion SDL_LoadBMP erwartet einen Dateinamen und keinen Stream oder Ähnliches.
Da lag ja meine Hoffnung in CreateFile mit FILE_ATTRIBUTE_TEMPORARY, weil es sich so anhörte als würde
die Datei wie eine normale behandelt, aber existiert in Wahrheit nur im Speicher.

Luckie 27. Sep 2007 13:36

Re: Bitmaps archivieren und laden?
 
Ich würde da mit einem Inhaltsverzeichnis arbeiten, wie ich es bei meinem SFX-Builder gemacht habe.

Auch in C++ gibt es Streams. Und wenn du die Funktion SDL_LoadBMP nuicht nutzen kannst, musst du mal gucken, ob es nicht eine gibt, der du einen Stream übergeben kannst. Ansonsten ginge noch MSDN-Library durchsuchenCreateFile mit dem Attribut FILE_ATTRIBUTE_TEMPORARY:
Zitat:

A file is being used for temporary storage. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:29 Uhr.
Seite 2 von 3     12 3      

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