Loading image file into TGraphic

Win 10 / Delphi 10.3 / TMS WEB Core 1.6 beta

What is the suggested Graphic class I should use with TMS WEB Core for an Electron app? Is the TGraphic.LoadFromFile() also asynchronous? If so, what is a possible pattern to wait for finish loading?

Var
  PDFLib :  TTMSFNCPDFLib;
  g : TGraphic;
  rect : TRectF:

begin
  PDFLib:= TTMSFNCPDFLib.Create();
  PDFLib.BeginDocument();

  g:= TGraphic.Create;
  g.OnChange:= OnGraphicChange;
  g.LoadFromFile('Image.png');

  rect.Left:= 40;
  rect.Top:= 100;
  rect.Right:= 40 + g.Width;
  rect.Bottom:= 100 + g.Height;

  PDFLib.Graphics.DrawImage(g , rect);
  PDFLib.EndDocument().SaveToFile(FileName);
end;

When setting a breakpoint after the LoadFromFile() and inspect the TGraphic object, it seems the image data is not loaded

TGraphicLoadFromFile_1

Assuming the LoadFromFile() method is working asychronous, I assigned an event handler to the TGraphic.OnChange event. The event handler is never called.

My next thought was, that the TGraphic.LoadFromFile() is not working because of restrictions for a Electron app to access local data. So I used a TElectronBinaryDataStream

  g:= TGraphic.Create();
  g.OnChange:= OnGraphicChanged;

  stream.LoadFromFile('Image.png');
  g.LoadFromURL(stream.Base64);

There seems to be some image data loaded into the TGraphic object, but nothing what I could paint on the PDF canvas. Also the TGraphic.OnChange event is not called when assigning the image data from the stream to the TGraphic object.

TGraphicLoadFromFile_2

Hi,

Yes, you should use TElectronBinaryDataStream to access local files. Try TGraphic.LoadFromResource instead of TGraphic.LoadFromURL. Implement the TGraphic.OnChange event, and in that implementation you can create your PDF. You can access the needed TGraphic object with Sender as TGraphic.

Hello,

when using

TGraphic.LoadFromResource()

the debugger shows a very similar result:

TGraphicLoadFromFile_3

my assigned OnChange event handler is

procedure TFMain.OnGraphicChanged(Sender: TObject);
Var
  g : TGraphic;
  stream : TElectronBinaryDataStream;
begin
  try
    g:= Sender as TGraphic;
    stream:= TElectronBinaryDataStream.Create();

    stream.Base64:= g.GetBase64Image();
    stream.SaveToFile('ImageCopy.png');
  finally
    g.free();
    stream.free();
  end;
end;

which basically should create a copy of the image file. Unfortunately the event handler is never called. Any idea for that?

The following code triggers the event, I'm not sure what you are doing differently:

procedure TForm1.GraphicDataChange(Sender: TObject);
begin
  ShowMessage('Graphic data changed');
end;

procedure TForm1.WebButton1Click(Sender: TObject);
var
  g: TGraphic;
  stream: TElectronBinaryDataStream;
begin
  stream := TElectronBinaryDataStream.Create;
  stream.LoadFromFile('C:\Users\TMS\Pictures\meow_knife.png');
  g := TGraphic.Create;
  g.OnChange := GraphicDataChange;
  g.LoadFromResource(stream.Base64);
end;

However there seems to be an issue with getting the base64 string from TGraphic. We will investigate that.

Hello,

ok, lesson learned : "Never free an object in a finally block, you might still need it" ;-)

  try
    g:= TGraphic.Create();
    g.OnChange:= OnGraphicChanged;

    stream.LoadFromFile('Image.png');
    g.LoadFromURL(stream.Base64);
  finally
    g.free();
    stream.free();
  end;

When the object g is no longer existing, the event handler never will be called .....

Ok, this part is working, but to save back the image by a TElectronBinaryDataStream creates an empty file, you noticed the issue with the TGraphic.GetBase64Image already.

Thank you for your patience :slight_smile: