Home > Mobile >  Array to Stream in Delphi 10.4
Array to Stream in Delphi 10.4

Time:05-29

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 stream ms
  • reset temp_ms.Position to 0
  • copy (CopyFrom) sz bytes from temp_ms to ms
  • 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 from ms
  • set arrray size (if array is dynamic)
  • n times:
  • read size of image sz
  • copy sz bytes to temp_ms
  • reset temp_ms.Position
  • load array[i] from temp_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

  • Related