habe ich Dich richtig verstanden, Du bindest alle Bilder (png, jepeg ua) in eine Zip-Datei und holst sie dann bei Bedarf aus der Datei?
Als Beispiel habe ich dir eine Umsetzung mit mORMot geschrieben.
Disclaimer: Das Beispiel ist ein Proof of Concept, der Sourcecode ist weder getestet noch optimiert.
Delphi-Quellcode:
uses
mormot.core.base,
mormot.core.data,
mormot.core.text,
mormot.core.os,
mormot.core.zip,
mormot.core.perf,
mormot.crypt.core;
type
TImageResourceFile = class(TObject)
private
FPassword: RawUtf8;
FFileName: TFileName;
FIsWritable: Boolean;
protected
function LoadStream(pmStream: TCustomMemoryStream; const pmcResName: TFileName; const pmcPassword: RawUtf8): Boolean;
procedure SaveStream(pmStream: TCustomMemoryStream; const pmcResName: TFileName; const pmcPassword: RawUtf8; pmIsCompressed: Boolean = True);
public
constructor Create(const pmcFileName: TFileName; const pmcPassword: RawUtf8);
destructor Destroy; override;
function LoadImage(pmImage: TImage; const pmcImageName: String): Boolean;
procedure SaveImage(pmImage: TImage; const pmcImageName: String); overload;
procedure SaveImage(pmImageData: TCustomMemoryStream; const pmcImageName: String); overload;
end;
constructor TImageResourceFile.Create(const pmcFileName: TFileName; const pmcPassword: RawUtf8);
begin
inherited Create;
FFileName := pmcFileName;
FPassword := pmcPassword;
FIsWritable := IsDirectoryWritable(ExtractFilePath(FFileName));
end;
destructor TImageResourceFile.Destroy;
begin
FillZero(FPassword);
inherited Destroy;
end;
function TImageResourceFile.LoadStream(pmStream: TCustomMemoryStream; const pmcResName: TFileName; const pmcPassword: RawUtf8): Boolean;
var
idx: Integer;
zipRead: TZipRead;
encStream: TMemoryStream;
aesReader: TAesPkcs7Reader;
begin
Result := False;
if pmStream = Nil then Exit; //=>
if pmcResName = '' then Exit; //=>
if not FileExists(FFileName) then Exit; //=>
zipRead := TZipRead.Create(FFileName);
try
idx := zipRead.NameToIndex(pmcResName);
if idx < 0 then Exit; //=>
if pmcPassword = '' then
Result := zipRead.UnZip(idx, pmStream)
else
begin
encStream := TMemoryStream.Create;
try
if zipRead.UnZip(idx, encStream) then
begin
encStream.Position := 0;
aesReader := TAesPkcs7Reader.Create(encStream, pmcPassword);
try
Result := (StreamCopyUntilEnd(aesReader, pmStream) > 0);
finally
aesReader.Free;
end;
end;
finally
encStream.Free;
end;
end;
finally
zipRead.Free;
end;
end;
procedure TImageResourceFile.SaveStream(pmStream: TCustomMemoryStream; const pmcResName: TFileName; const pmcPassword: RawUtf8; pmIsCompressed: Boolean);
const
IS_COMPRESSED: array[Boolean] of Integer = (0, 6);
var
zipWrite: TZipWrite;
encStream: TMemoryStream;
aesWriter: TAesPkcs7Writer;
begin
if pmStream = Nil then Exit; //=>
if pmcResName = '' then Exit; //=>
if not FIsWritable then Exit; //=>
if FileExists(FFileName) then
zipWrite := TZipWrite.CreateFromIgnore(FFileName, [pmcResName])
else
zipWrite := TZipWrite.Create(FFileName);
try
if pmcPassword = '' then
zipWrite.AddDeflated(pmcResName, pmStream.Memory, pmStream.Size, IS_COMPRESSED[pmIsCompressed], DateTimeToFileDate(Now))
else
begin
encStream := TMemoryStream.Create;
try
aesWriter := TAesPkcs7Writer.Create(encStream, pmcPassword);
try
pmStream.Position := 0;
StreamCopyUntilEnd(pmStream, aesWriter);
aesWriter.Finish;
finally
aesWriter.Free;
end;
zipWrite.AddDeflated(pmcResName, encStream.Memory, encStream.Position, IS_COMPRESSED[pmIsCompressed], DateTimeToFileDate(Now));
finally
encStream.Free;
end;
end;
finally
zipWrite.Free;
end;
end;
function TImageResourceFile.LoadImage(pmImage: TImage; const pmcImageName: String): Boolean;
var
tmpStream: TMemoryStream;
begin
Result := False;
if pmImage = Nil then Exit; //=>
if pmcImageName = '' then Exit; //=>
tmpStream := TMemoryStream.Create;
try
if LoadStream(tmpStream, pmcImageName, FPassword) then
begin
tmpStream.Position := 0;
try
pmImage.Picture.LoadFromStream(tmpStream);
Result := True;
except
end;
end;
finally
tmpStream.Free;
end;
end;
procedure TImageResourceFile.SaveImage(pmImage: TImage; const pmcImageName: String);
var
tmpStream: TMemoryStream;
begin
if pmImage = Nil then Exit; //=>
if pmcImageName = '' then Exit; //=>
tmpStream := TMemoryStream.Create;
try
pmImage.Picture.SaveToStream(tmpStream);
SaveImage(tmpStream, pmcImageName);
finally
tmpStream.Free;
end;
end;
procedure TImageResourceFile.SaveImage(pmImageData: TCustomMemoryStream; const pmcImageName: String);
begin
if pmImageData = Nil then Exit; //=>
if pmcImageName = '' then Exit; //=>
SaveStream(pmImageData, pmcImageName, FPassword, False);
end;
Anwenden kannst du es so:
Delphi-Quellcode:
var
timer: TPrecisionTimer;
imgResFile: TImageResourceFile;
begin
Image.Picture.Assign(Nil);
timer.Start;
imgResFile := TImageResourceFile.Create(ChangeFileExt(Application.ExeName, '.dat'), 'Thomas');
try
imgResFile.LoadImage(Image, 'ImageName');
ShowMessage(Format('Total time: %s', [timer.Stop]));
finally
imgResFile.Free;
end;
end;
Eine 2MB große AES verschlüsselte PNG Bilddatei aus einer Zip-Datei in ein Image laden, benötigt im Beispiele eine Gesamtladezeit von ca. 60 ms. Das ist ein brauchbarer Wert. Davon dauert die Entschlüsselung ca. 5 ms. Wenn du viele Bilder auf einmal schreiben willst, solltest du dir eine BatchAdd Funktion schreiben.
mORMot musst du nicht installierten. Es reicht aus, die entsprechenden Bibliothekspfade einzufügen. Es steht eine ausführliche
Hilfe, viele Beispiele (für mORMot1) und ein freundliches
Forum zur Verfügung.
Bei einer neuen Anwendung würde ich mORMot2 empfehlen. Dazu gibt es zur Zeit noch keine Hilfe. Trotzdem hier der Link zum
GitHub Repro.
Bis bald...
Thomas