How can i save and load an 'Array[0..9] of TJpegImage' to a MemoryStream. There are many samples to save one Image to a Stream but no one save an Array. I need it to save the Stream to a Database Blob field and later load the BlobField back to my Array. All Images in the Array has the same Size. Maybe a Stream of TByte can do this ? But how to convert a TByte-Stream back to an Array?
CodePudding user response:
All Images in the Array has the same Size
- perhaps dimensions (width/height) are the same, but size of jpeg image in bytes varies depending on picture and compression. So I assume you need to store both image data and data size.
Possible approach:
- write integer value - length of array - to memory stream
ms
- for every array element save it to temporary memory stream
temp_ms
- write integer value
sz = ms.size
to main memory streamms
- reset
temp_ms.Position
to 0 - copy (
CopyFrom
)sz
bytes fromtemp_ms
toms
- clear
temp_ms
- repeat for all array elements
Now ms
contents looks like:
10 14212 FFD8....D9 31234 FFD8....D9
10 images
1st image size
1st image contents
2nd image size
2nd image contents
To retrieve image, perform reverse actions:
- reset
ms
position (if needed) - read number of images
n
fromms
- set arrray size (if array is dynamic)
n
times:- read size of image
sz
- copy
sz
bytes totemp_ms
- reset
temp_ms.Position
- load
array[i]
fromtemp_ms
working example:
var
ms, temp: TMemoryStream;
jps: array of TJpegImage;
i, n, sz: Integer;
begin
n := 3;
SetLength(jps, n);
ms := TMemoryStream.Create;
temp := TMemoryStream.Create;
for i := 0 to n - 1 do begin
jps[i] := TJpegImage.Create;
jps[i].LoadFromFile(Format('h:\%s.jpg', [Chr(Ord('a') i)]));
//in my case loads files a.jpg, b.jpg, c.jpg
end;
try
ms.Write(n, SizeOf(n));
for i :=0 to n - 1 do begin
temp.Clear;
jps[i].SaveToStream(temp); //jpeg data here
sz := temp.Size;
ms.Write(sz, SizeOf(sz)); //size of image
temp.Position := 0;
ms.CopyFrom(temp, sz); //image data to final destination
end;
ms.SaveToFile('h:\base.dat'); //for control
//revert to empty stream
ms.Clear;
ms.LoadFromFile('h:\base.dat'); //load from "base"
ms.Read(n, SizeOf(n));
//here some actions to setup array
for i :=0 to n - 1 do begin
ms.Read(sz, SizeOf(sz));
temp.Clear;
temp.CopyFrom(ms, sz);
temp.Position := 0;
jps[i].LoadFromStream(temp);
Canvas.Draw(i * 200, 0, jps[i]); //control shot
end;
finally
ms.Free;
temp.Free;
for i := 0 to n - 1 do
jps[i].Free;
end;
CodePudding user response:
Why don't you use a TFDMemTable?
Another option can be, TStringList using System.NetEncoding.TNetEncoding.Base64 encoding since TStringList is very much like a superpowered vector