Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Mehrere Bilder in einer Datei Speichern (https://www.delphipraxis.net/73067-mehrere-bilder-einer-datei-speichern.html)

Christian.Ossi 11. Jul 2006 23:10


Mehrere Bilder in einer Datei Speichern
 
Ich wollte mal wissen, ob es möglich ist, mehrere kleine jpg-Bilder in einer einzigen Datei - sozusagen als Datenbank - zu speichern!?

Ich hab ein Programm geschrieben wo nun kleine Bildchen noch aus einer Datei heraus gelesen werden sollen, die dann dort angezeigt werden sollen. Also muss man die auch z.B. per Nummer ansprechen können und dann eben aus einer einzigen Datei auslesen können.

Ist sowas möglich? Oder muss man dann alle einzeln abspeichern - ich wollte der Ordnung wegen nur eine einzige Datenbankdatei.


Danke schonmal!

ferby 11. Jul 2006 23:12

Re: Mehrere Bilder in einer Datei Speichern
 
Hallo,

du kannst einfach deine Bilder in ein Archiv packen (z.B.: In ein Zip Archiv)
Es gibt Komponenten die mit Zip Archiven umgehen können.

Gruß,
Ferby

arbu man 11. Jul 2006 23:15

Re: Mehrere Bilder in einer Datei Speichern
 
Eine Lösung wäre XML:

Du speicherst die jpegs in jewils einen Stream. Dann kanst du die einzelnen Streams in xml Speichern. Nachteil diese Datei wird etwas größer da die daten anderes gespeichert werden.

Hier noch eine Unit an der ich grade arbeite die streams in xml speichern soll (benötigt die JEDI Komponetenten):
Delphi-Quellcode:
{******************************************************************************}
{*                                                                            *}
{* Project:       CrashPoint                                                *}
{* Unit:          uCP_MapFile                                               *}
{* Version:       1.0                                                        *}
{*                                                                            *}
{* Description:                                                              *}
{*                 Klasse um eine Liste von Streams in eine Datei zu         *}
{*                 speichern und zu lesen                                    *}
{*                                                                            *}
{* Log:                                                                      *}
{*               # First Version                                             *}
{*                                                                            *}
{*                                                                            *}
{* Author:        Björn R. Salgert (bjoern@bsnx.net)                        *}
{* URL:           N/A - [url]http://bsnx.net[/url]                                     *}
{*                                                                            *}
{******************************************************************************}
unit uCP_MapFile;

interface

uses SysUtils, Classes, JvSimpleXml, Dialogs;

type
  TMapFile = class (TJvSimpleXML)
  protected

  public
    procedure AddStream(Name: String; Stream: TStringStream);
    procedure GetStream(Name: String; Stream: TStream);
    procedure AddString(Name, Text: String);
    function GetString(Name: String): String;
    procedure AddInt(Name: String; I: Integer);
    function GetInt(Name: String): Integer;
    constructor Create(AOwner: TComponent); override;
  end;

implementation

function streamtostr(S: TStream): string;
var
  str: string;
  lStringStream: TStringStream;
begin
  lStringStream := TStringStream.Create;
  Try
    lStringStream.CopyFrom(S, 0);
    Result := lStringStream.DataString;
  Finally
    lStringStream.Free;
  End;
end;

function strtohex(Text: String): String;
var
  i: integer;
  s: string;
begin
  for i:=1 to length(Text) do begin
    s:= s+IntToHex(Byte(Text[i]), 2);
  end;
  result:=s
end;

{ TMapFile }

procedure TMapFile.AddInt(Name: String; I: Integer);
begin
  Self.Root.Items.Add(Name, i);
end;

procedure TMapFile.AddStream(Name: String; Stream: TStringStream);
begin
//  Self.Root.Items.Add(Name, strtohex(Stream.DataString));
  Stream.Position:=0;
  Self.Root.Items.Add(Name, Stream);
end;

procedure TMapFile.AddString(Name, Text: String);
begin
  Self.Root.Items.Add(Name, Text);
end;

constructor TMapFile.Create(AOwner: TComponent);
begin
  inherited;
  Self.Root.Name:= 'map';
end;

function TMapFile.GetInt(Name: String): Integer;
begin
  if Self.Root.Items.ItemNamed[Name]<>nil then begin
     result:=Self.Root.Items.ItemNamed[Name].IntValue;
  end;
end;

procedure TMapFile.GetStream(Name: String; Stream: TStream);
var
  b: Byte;
  i: integer;
begin
  if Self.Root.Items.ItemNamed[Name]<>nil then begin
     Stream.Position:=0;
     Self.Root.Items.ItemNamed[Name].GetBinaryValue(Stream);
     {
     for i:=1 to Length(Self.Root.Items.ItemNamed[Name].Value) do begin
       B:= Byte(Self.Root.Items.ItemNamed[Name].Value[i]);
       Stream.Write(B, sizeof(B));
     end; }
  end;
end;

function TMapFile.GetString(Name: String): String;
begin
  if Self.Root.Items.ItemNamed[Name]<>nil then begin
    result:= Self.Root.Items.ItemNamed[Name].Value;
  end;
end;

end.

mr.winkle 11. Jul 2006 23:18

Re: Mehrere Bilder in einer Datei Speichern
 
Du kannst auch mehrere Bilder in einer großen Bilddatei zusammenfassen, das lohnt sich aber nur bei recht kleinen bildern

wenn alle bilder die selbe größe haben gibt es in der delphix imagelist die möglichkeit eine patternwidth und patternheight festzulegen.
Du kannst dann über eine zahl auf ein bestimmtes Bild zugreifen - was z.b bei animationen sehr nützlich ist da man nicht 123 bilder verwalten muss.

Bei verschiedenen Größen müsste man mit einer Trennfarbe oä arbeiten, was allerdings recht rechenintensiv wäre.

Von anderen Lösungen habe ich noch nichts gehört, würde mich aber auch mal interessieren! :stupid:

Christian.Ossi 12. Jul 2006 00:32

Re: Mehrere Bilder in einer Datei Speichern
 
Also die Bilder wären alle max. 90x90 Pixel groß - eben im jpg-Format.
Das ist ja noch recht klein....denk ich.

Wie geht das mit DelphiX - davon habe ich schonmal was gehört.
Die Sache ist nur die - ich will ja online auf meinem Free-Webspace die einzelnen kleinen durchnummerierten Bildchen verfügbar machen und das Programm holt sich die und legt sie auf der eigenen Festplatte ab - aber nicht wie online mehrere, sondern als eine Datei.

Von dieser aus sollen die Bilder im Programm eingebunden werden.
Also sozusagen kann man online ein Bild austauschen und das Programm holt sich das Bild oder die Bilder und speichert diese dann als Art Datenbank lokal zum Öffnen im eigenen Programm.

mkinzler 12. Jul 2006 05:46

Re: Mehrere Bilder in einer Datei Speichern
 
Dann würde sich, wie schon geschrieben ein Archiv anbieten oder du speicherst die Bilder wirklich in einer Datenbank.

Der_Unwissende 12. Jul 2006 07:16

Re: Mehrere Bilder in einer Datei Speichern
 
Hi,
ich würde dir auch von einer großen Datei abraten. Hat eher eine Menge Nachteile. Gerade bei XML (hier imho völlig ungeeignet) müsstest du dann tunlichst darauf achten, dass du nicht immer die ganze Datei im Speicher hälst. Damit ist die Wahl deines XML Parsers evtl. schon eingeschränkt. Ein Archiv bietet da schon deutlich mehr Flexibilität. Am einfachsten legst du darin noch (etwas an eine DB angelehnt) eine Indexdatei an und dann kannst du über diese schnell nach bestimmten Eigenschaften suchen ohne alle Bilder ständig entpacken zu müssen. Damit solltest du also ohne Probleme nur noch gezielt auf einzelne Elemente zugreifen können.
Ich würde dir hier Abbrevia empfehlen (sorry, zu faul den Link zu suchen).

Gruß Der Unwissende

cruiser 12. Jul 2006 07:49

Re: Mehrere Bilder in einer Datei Speichern
 
Ich hätt noch Compound Documents anzubieten. Quasi ein virtuelles Dateisystem innerhalb einer Datei, leider unkomprimiert, aber ich denke, da liese sich noch was dran feilen. Vorteil dabei: du kannst auf jedes File wie vom richtigen Dateisystem auch, per Stream zugreifen ohne ein File entpacken zu müssen. Der Link in der Doku ist leider tot, aber ich kann die Files hochstellen, wenn bedarf ist.

franktron 12. Jul 2006 08:24

Re: Mehrere Bilder in einer Datei Speichern
 
Schau mal in die Code Lib da habe ich vor kurzem ein Virtuelles Dateisystem reingepackt

Der_Unwissende 12. Jul 2006 09:01

Re: Mehrere Bilder in einer Datei Speichern
 
Zitat:

Zitat von cruiser
Ich hätt noch Compound Documents anzubieten. Quasi ein virtuelles Dateisystem innerhalb einer Datei, leider unkomprimiert

Also auf Kompression denke ich sollte man bei JPEGs nicht mehr achten müssen. Die haben ja gerade schon die Eigenschaft ziemlich kompakt zu sein. Ich weiß nicht wieviel Prozent man da noch rausholt, dürfte sich aber kaum lohnen. Daran sollte es also nicht scheitern!

Mavarik 12. Jul 2006 09:10

Re: Mehrere Bilder in einer Datei Speichern
 
Hi!

Macht es doch nicht so kompliziert...

Speicher die Bilder doch einfach hintereinander in eine Datei...

Erst ein Word oder Longint der Größe und dann das JPG... usw..
Dann kannst Du Dich einfach durch seeken...

Oder Speichere eine zusätzliche Indextabelle mit den Seeknummer auf die Bilderstarts und die Länge...

Fertig... Programmieraufwand keine 3 Minuten...

(Fast kürzer als die Antwort hier zu tippen) :stupid:

Frank :coder:

Christian.Ossi 12. Jul 2006 16:26

Re: Mehrere Bilder in einer Datei Speichern
 
Wie das genau funktioniert mit den Seek-Nummern und hintereinander speichern würde mich mal interessieren :wink:

himitsu 12. Jul 2006 16:50

Re: Mehrere Bilder in einer Datei Speichern
 
schau mal in die OH ... stichwort seek :zwinker:

im Prinzip gibt es da 2 Möglichkeiten.

entweder alle bilder hintereinander und vor jedes Bild dessen Größe
Größe1, Bild1,
Größe2, Bild2,
Größe3, Bild3

oder erst ein "Array" mit den ganzen Positionen und Größen und dahinter die Bilder.
Position1, Größe1,
Position2, Größe2,
Position3, Größe3,
EndMarker,
Bild1,
Bild2,
Bild3

Anzahl,
Position1, Größe1,
Position2, Größe2,
Position3, Größe3,
Bild1,
Bild2,
Bild3

Letzere wären wohl besser, wenn man ein bestimmtes Bild will
und Ersteres macht sich besser, wenn man alle Bilder der Reihe nach auslesen will und nich erst die gesammte "Tabelle" zwischenspeichern will

Größe = Größe in Byte, damit man weiß wieviel man rausladen muß, wenn man das Bild will
Position = Position in der Datei, also an welcher Stelle das Bild beginnt.

Möglich wären och noch sowas
Anzahl,
Position1,
Position2,
Position3,
Größe1, Bild1,
Größe2, Bild2,
Größe3, Bild3

Position1,
Position2,
Position3,
EndMarker,
Größe1, Bild1,
Größe2, Bild2,
Größe3, Bild3


Bei den Varianten mit einr Tabelle am Anfang kann man halt ganz einfach mit
Seek(DateiHandle, Index * GrößeDerEinträge);
Read(DateiHandle, VariableFürEinenEintrag); // PS: PseudoCode, also nicht direkt so verwenden
die Werte für ein bestimmtes Bild besorgen.

Und dann direkt zu dem gewünschten Bild springen und dieses auslesen
Seek(DateiHandle, VariableFürEinenEintrag.Position);
Read(DateiHandle, Bild, VariableFürEinenEintrag.Größe);

Oder halt (wenn die Größe vorm Bild ist);
Seek(DateiHandle, VariableFürEinenEintrag.Position);
Read(DateiHandle, Größe);
Read(DateiHandle, Bild, Größe);


Wenn du ohne Tabelle arbeitest, dann müstest du dich ja jedesmal vom ersten Bild aus, über jedes einzelne Bild hinweg, bis zum entsprechenden Bild durchhangeln.

Der_Unwissende 12. Jul 2006 17:06

Re: Mehrere Bilder in einer Datei Speichern
 
Zitat:

Zitat von Christian.Ossi
Wie das genau funktioniert mit den Seek-Nummern und hintereinander speichern würde mich mal interessieren :wink:

Also eigentlich sind das nur die Grundlagen eines TStream Objekts. Wenn dir hier die OH anschaust Delphi-Referenz durchsuchenTStream wirst du schon so ziemlich alles finden was es zu wissen gibt. Die Idee ist einfach, du hast einen Stream ich bezeichne ihn einfach mal als ein völlig dynamisches Array von Bytes. Und du kennst die aktuelle Position auf der du dich befindest. Jede Aktion, die du ausführst ist immer relativ zu dieser Position. Schreibst du etwas, so wird es nicht automatisch hinten rangehangen, du schreibst einfach die Anzahl der angegebenen Bytes an die aktuelle Position (und ff). Gleiches gilt für das Lesen. Auch hier darfst du nicht davon ausgehen, dass du deine aktuelle Position bei 0 beginnt. Insbesondere gilt dies, wenn du die Position auf 0 setzt, einen Wert einliest und diesen nun überschreiben möchtest. Zum Überschreiben müsstest du nun erst zurück zur 0!

Da du als kleinste Einheit, die du speichern kannst ein Byte hast, wird die Anzahl der zu lesenden bzw. zu schreibenden Bytes angegeben. Ein Stream speichert alle Bytes die man ihm gibt (typ ist const, also beliebig), hat aber deshalb keine Größeninformationen. Möchtest du etwas speichern und wieder einlesen, so wird häufig der Trick angewendet, dass man erst die Anzahl der Bytes angibt, gefolgt von dem Datensatz. Die Anzahl der Bytes muss dann dabei in einer festen Größe (z.B. 4 Byte = Cardinal/Integer) abgelegt werden:

Delphi-Quellcode:
var stream : TStream;
    data : TByteDynArray;
begin
  // data füllen
  ...
 
  stream := TMemoryStream.Create;
  // wichtig, verwende einen Ressourcenschutzblock
  try
    stream.Position := 0;
    stream.write(length(data), sizeOf(Integer));
    stream.write(data[0], length(data));

    // weitere Daten hinzufügen und speichern des Streams
    ...
  finally
    stream.Free
  end;

  finalize(data);
  setLength(data, 0);
end;
Hier soll nur einfach gezeigt werden, wie du das speichern würdest. Du weißt nun, dass deine Datei mit 4 Byte beginnt (die Länge des Arrays). Hast du die Länge x ausgelesen, sind die nächsten x Byte also das hier gespeicherte Array. Dahinter kommt dann die nächste Länge und das nächste Array.

Natürlich wäre es jetzt sehr nervig, wenn du jedesmal über die gesamte Datei laufen müsstest, um all diese Informationen zu holen. Ein weiteres Problem, du hast wenig Flexibilität. Wenn du mehr Meta-Infos benötigst als die Größe, so kannst du die nicht einfach einfügen, du kannst sie ja nicht von den Daten einer alten Datei unterscheiden. Also müsstest du die alten Dateien komplett neu anlegen.
Deshalb gibt es verschiedene Alternative Möglichkeiten. Da sich unabhängig von den Metadaten die Nutzdaten nicht ändern, kannst du einfach zwei Dateien verwalten. Die eine ist dann nur ein Stream, in dem die Nutzdaten einfach nur hintereinander stehen. Damit du nun weißt an welcher Stelle was steht und wie viel Bytes es einnimmt, speicherst du diese Informationen seperat in einer zweiten Datei.
Weitere Alternativen sind Dateiheader. Hier schreibst du die Metadaten an den Anfang (oder unüblicher an das Ende) der Datei. Wenn du diesen Bereich (beliebiger Größe) als solchen Kennzeichnest (spezielle Bytefolgen), so weißt du wo der Header anfängt und wo er endet. Die Erreichte Flexibilität hängt dann nur noch davon ab, wie geschickt der Header implementiert ist. Tiffs zum Beispiel haben ein sehr flexibles Containerformat, dass einem so ziemlich alles ermöglicht (man kann Multipage-Tiffs erstellen, die dann wirklich mehr als ein Bild enthalten, man könnte aber auch noch zusätzlich eine Zip Datei, ein Avi und ein Windowsimage in die Datei packen. Die letzteren Fälle müssten nur nicht von einem Standardkonformen Programm verstanden werden, doch das Tiff wäre valide).

Natürlich hast du die volle Flexibilität wenn du ein Stream verwendest. Aber ein Virtuelles Dateisystem und ein Archiv sind letztlich auch nur Kapselungen vom Selbigen. Ich bleib hier einfach mal bei einem Zip-Archiv. Hier wird intern auch nur ein Stream mit sehr speziellen Headern erzeugt, aber du musst dich nicht darum kümmern. Wo genau ein abgelegtes File anfängt und wo es endet weiß das Archiv, du sagst nur, leg die Datei ab und hol mir die Datei wieder. Natürlich kann ein Archiv noch etwas mehr, du hast automatisch eine Verschlüsselung (Zip-Passwort) oder eben nicht (kein Passwort), du hast eine Checksumme für die Konsistenzprüfung und natürlich wenn du möchtest Kompression. Was du davon verwendest ist dann deine Sache.
Ich will dir hier gar nicht von Streams abraten, nur braucht man von Zeit zu Zeit nicht das Rad neu erfinden...

gintasdx 7. Dez 2011 21:51

AW: Mehrere Bilder in einer Datei Speichern
 
Finally found info how to store image data in XML node. :-D
Stream position always must be set manually to zero it seems,else no data is saved.

Iwo Asnet 8. Dez 2011 03:46

AW: Re: Mehrere Bilder in einer Datei Speichern
 
Zitat:

Zitat von Mavarik (Beitrag 494240)
Macht es doch nicht so kompliziert...
Speicher die Bilder doch einfach hintereinander in eine Datei...

Mach es doch nicht so kompliziert ...
Speicher die Bilder doch einfach in einer DB.. ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:26 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