1
votes

I store PNG image into Ini file with the following code :

procedure TfrmParametres.SaveIni;
var
  IniFile: TIniFile;
  MS: TMemoryStream;
  PNG: TPngImage;
begin
  IniFile := TIniFile.Create(IniFileName);
  try
  PNG := TPngImage.Create;
  try
    PNG.LoadFromFile(edtLogo.Text);//edtlogo contain image file path
    MS  := TMemoryStream.Create;
    try
      PNG.SaveToStream(MS);
      MS.Seek(0, 0);
      IniFile.WriteBinaryStream('REPORT_HEADER', 'LOGO', MS);
    finally
      MS.Free;
    end;
  finally
    PNG.Free;
  end;
finally
  FreeAndNil(IniFile);
end;
end;

and to show the picture in another form OnShow event I used the same approach :

  1. Load DATA in TMemoryStream object

  2. Load DATA from MemoryStream into TPngImage object

  3. Show the picture in TImage component

    procedure TfrmLoadPicture.FormShow(Sender: TObject);
    var
      IniFile: TIniFile;
      MS: TMemoryStream;
      PNG: TPngImage;
    begin
      IniFile:= TIniFile.Create(frmParametres.IniFileName);
      try
        MS:= TMemoryStream.Create;
        try
          IniFile.ReadBinaryStream('REPORT_HEADER', 'LOGO', MS);
          PNG := TPngImage.Create;
          try
            MS.Seek(0, 0);
            PNG.LoadFromStream(MS);
            Image.Picture.Assign(PNG);
          finally
            PNG.Free;
          end;
        finally
          MS.Free;
        end;
      finally
        IniFile.Free;
      end;
    end;
    

however I always get Exception error: enter image description here

2
What's the size of your picture? TIniFile.ReadString reads at most 2048 characters. - Sertac Akyuz
I didn't used ReadString i used ReadBinaryStream instead ? ! did you means I need to set up the size of the memory stream ? - S.FATEH
ReadBinaryStream uses ReadString. - Sertac Akyuz

2 Answers

5
votes

TIniFile has a hard-coded cap on the size of any one value it can read, partly due to the fact the underlying Windows API (GetPrivateProfileString and friends) doesn't allow querying the size of a saved value. IMO TIniFile should really raise an exception on an attempt to write a larger value, but regardless, if you use TMemIniFile instead of TIniFile you should be fine (I've just tried it).

1
votes

Chris has answered the direct question that you asked. I have some other comments.

No need to decode the PNG to transfer it to the INI file

You can copy the file directly without decoding the PNG and then recoding.

Stream := TFileStream.Create(FileName, fmOpenRead);
try
  IniFile.WriteBinaryStream('REPORT_HEADER', 'LOGO', Stream);
finally
  Stream.Free;
end;

Hexadecimal encoding is not efficient

WriteBinaryStream is not a very efficient way to encode binary as text. In effect you are using base16 and it would be more conventional and efficient to use base64.

I suggest that you encode the binary file stream to a base64 string and write that string to the INI file.

INI files are not suited to binary data

INI files were never intended to be used to store large binary blobs. On first inspection it would seem odd that you are trying to shoe horn a PNG image into an INI file.