Jump to content
Sign in to follow this  
matrix1233

Problem with FPC

Recommended Posts

Hi,

Am using Lazarus(FPC) and am trying to execute the Demo29 (work perfectly on delphi). the problem when i open Image and i Execute (Use Device Context Unchecked) the program go to the end and Image1.Picture.Graphic.LoadFromStream(_stream);  raise an exception Wrong Image Format  

 if (Image1.Picture.Graphic = nil) or Image1.Picture.Graphic.Empty then
    raise Exception.Create('You must first select an image');
  PythonEngine1.ExecStrings(Memo1.Lines);
  _im := MainModule.ProcessImage(ImageToPyBytes(Image1.Picture.Graphic));
  if not chkUseDC.Checked then
  begin
    // We have to call PyString_AsStringAndSize because the image may contain zeros
    with GetPythonEngine do begin
      pargs := MakePyTuple([ExtractPythonObjectFrom(_im)]);
      try
        presult := PyEval_CallObjectWithKeywords(
            ExtractPythonObjectFrom(MainModule.ImageToBytes), pargs, nil);
        try
          if (P = nil) or (PyBytes_AsStringAndSize(presult, P, Len) < 0) then begin
            ShowMessage('This does not work and needs fixing');
            Abort;
          end;
        finally
          Py_XDECREF(pResult);
        end;
      finally
        Py_DECREF(pargs);
      end;
    end;

    _stream := TMemoryStream.Create();
    try
      _stream.Write(P^, Len);
      _stream.Position := 0;
      Image1.Picture.Graphic.LoadFromStream(_stream);
    finally
      _stream.Free;
    end;
  end
  else
  begin
    Image1.Picture.Bitmap.SetSize(Image1.Width, Image1.Height);
    _dib := Import('PIL.ImageWin').Dib(_im);
    Image1.Picture.Bitmap.SetSize(Image1.Height, Image1.Width);
    _dib.expose(NativeInt(Image1.Picture.Bitmap.Canvas.Handle));
  end;  

How can i correct that ?  Thanks .

Capture d’écran 2020-12-22 à 1.53.33 AM.png

Capture d’écran 2020-12-22 à 1.47.15 AM.png

Edited by matrix1233

Share this post


Link to post

Looking original code in unit1.pas from git: value of P is undefined there, because it is never initialized. What happens, if you add

p := nil;

at the beginning of Button2Click?

Share this post


Link to post

if  p := nil then i have the msg 'This does not work and needs fixing' 


 

 if (Image1.Picture.Graphic = nil) or Image1.Picture.Graphic.Empty then
    raise Exception.Create('You must first select an image');
  PythonEngine1.ExecStrings(Memo1.Lines);
  _im := MainModule.ProcessImage(ImageToPyBytes(Image1.Picture.Graphic));
  if not chkUseDC.Checked then
  begin
     P := nil;
    // We have to call PyString_AsStringAndSize because the image may contain zeros
    with GetPythonEngine do begin
      pargs := MakePyTuple([ExtractPythonObjectFrom(_im)]);
      try
        presult := PyEval_CallObjectWithKeywords(
            ExtractPythonObjectFrom(MainModule.ImageToBytes), pargs, nil);
        try
          if (P = nil) or (PyBytes_AsStringAndSize(presult, P, Len) < 0) then begin
            ShowMessage('This does not work and needs fixing');
            Abort;
          end;
        finally
          Py_XDECREF(pResult);
        end;
      finally
        Py_DECREF(pargs);
      end;
    end;

    _stream := TMemoryStream.Create();
    try
      _stream.Write(P^, Len);
      _stream.Position := 0;
      _stream.SaveToFile('test.jpeg');
     // Image1.Picture.Graphic.LoadFromStream(_stream);
    finally
      _stream.Free;
    end;
  end
  else
  begin
    Image1.Picture.Bitmap.SetSize(Image1.Width, Image1.Height);
    _dib := Import('PIL.ImageWin').Dib(_im);
    Image1.Picture.Bitmap.SetSize(Image1.Height, Image1.Width);
    _dib.expose(NativeInt(Image1.Picture.Bitmap.Canvas.Handle));
  end;     

 

Capture d’écran 2020-12-22 à 12.57.59 PM.png

Share this post


Link to post

i think that the problem is on MainModule.ImageToBytes  because on Delphi when i try to display it to a memo (Memo3.Lines.Add(MainModule.ImageToBytes); ) i have <function ImageToBytes at 0x00000000068DDCA0> but when i try the same code on Lazarus i have nothing . any idea how can i resolve on lazarus ?

Share this post


Link to post

Right, there was or, so p value was red herring. Although (p=nil) check is invalid anyway, because value of p is undefined there.

Share this post


Link to post

the problem is not P, i think that is just  MainModule.ImageToBytes like i explained above .. any idea ? 

Edited by matrix1233

Share this post


Link to post

After reading Python documentation I do not understand, how it can work in Delphi.

Move

          _stream := TMemoryStream.Create();
          try
            _stream.Write(P^, Len);
            _stream.Position := 0;
            Image1.Picture.Graphic.LoadFromStream(_stream);
          finally
            _stream.Free;
          end;


before

        finally
          Py_XDECREF(pResult);
        end;

 

P will be reference to internal buffer in pResult and Py_XDECREF(pResult); frees that memory.

  • Like 1

Share this post


Link to post

But also, from

if (P = nil) or (PyBytes_AsStringAndSize(presult, P, Len) < 0) then begin

 

"(p = nil) or" should be removed, because P is uninitialized, which only means, that it causes error, when P happens coincidentally initialize to nil.

Share this post


Link to post

yes i see! .. between Delphi and Lazarus the result of execution are different for example this code below With Delphi work perfectly and with lazarus it doesn't work and it say that  ( 'This does not work and needs fixing' ) generated by the test on PyBytes_AsStringAndSize. Any idea for this example why it's different ? 
   

var _im : Variant;
_dib : Variant;
 i:integer;
 pargs: PPyObject;
 pResult :PPyObject;
 P : PAnsiChar;
 _stream:TmemoryStream;
 Len : NativeInt;
 SPython:TstringList;
begin

SPython:=TstringList.Create;
SPython.Add('from io import BytesIO');
SPython.Add('from PIL import ImageGrab');
SPython.Add('def screenshot():');
SPython.Add('   im = ImageGrab.grab()');
SPython.Add('   stream = BytesIO()');
SPython.Add('   im.save(stream, "BMP")');
SPython.Add('   return stream.getvalue()');
SPython.Add('screenshot()');
PythonEngine1.ExecStrings(SPython);

 with GetPythonEngine do begin
        try
          pResult := ExtractPythonObjectFrom(MainModule.screenshot());
          if (PyBytes_AsStringAndSize(pResult, P, Len) < 0)   then begin
            ShowMessage('This does not work and needs fixing');
            Abort;
          end;
        finally
         _stream := TMemoryStream.Create();
          try
            _stream.Write(P^, Len);
            _stream.Position := 0;
            Memo2.Lines.add(_stream.Size.ToString);
            Image1.Picture.LoadFromStream(_stream);
            application.ProcessMessages;
          finally
            _stream.Free;
          end;
        end;
end;

 

Share this post


Link to post

Hi, i stored MainModule.screenshot() to a variable _im like you asked and it doesn't work (See the first code below)  but when i change the line where pResult are affected with presult := PyEval_CallObjectWithKeywords(ExtractPythonObjectFrom(MainModule.screenshot()), nil, nil), it work on lazarus . (See the second code below) .

i think that ExtractPythonObjectFrom are only needed to do the job and adding PyEval_CallObjectWithKeywords is not needed in this case but lazarus have some bugs .. we can perhaps correct this ?

 

var _im : Variant;
_dib : Variant;
 i:integer;
 pargs: PPyObject;
 pResult :PPyObject;
 P : PAnsiChar;
 _stream:TmemoryStream;
 Len : NativeInt;
 SPython:TstringList;
begin

SPython:=TstringList.Create;
SPython.Add('from io import BytesIO');
SPython.Add('from PIL import ImageGrab');
SPython.Add('def screenshot():');
SPython.Add('   im = ImageGrab.grab()');
SPython.Add('   stream = BytesIO()');
SPython.Add('   im.save(stream, "BMP")');
SPython.Add('   return stream.getvalue()');
SPython.Add('screenshot()');
PythonEngine1.ExecStrings(SPython);
 _im:=MainModule.screenshot();
 with GetPythonEngine do begin
        try
          pResult := ExtractPythonObjectFrom(_im);
          if (PyBytes_AsStringAndSize(pResult, P, Len) < 0)   then begin
            ShowMessage('This does not work and needs fixing');
            Abort;
          end;
        finally
         _stream := TMemoryStream.Create();
          try
            _stream.Write(P^, Len);
            _stream.Position := 0;
            Memo2.Lines.add(_stream.Size.ToString);
            Image1.Picture.LoadFromStream(_stream);
            application.ProcessMessages;
          finally
            _stream.Free;
          end;
        end;
end;

 

var _im : Variant;
_dib : Variant;
 i:integer;
 pargs: PPyObject;
 pResult :PPyObject;
 P : PAnsiChar;
 _stream:TmemoryStream;
 Len : NativeInt;
 SPython:TstringList;
begin

SPython:=TstringList.Create;
SPython.Add('from io import BytesIO');
SPython.Add('from PIL import ImageGrab');
SPython.Add('def screenshot():');
SPython.Add('   im = ImageGrab.grab()');
SPython.Add('   stream = BytesIO()');
SPython.Add('   im.save(stream, "BMP")');
SPython.Add('   return stream.getvalue()');
SPython.Add('screenshot()');
PythonEngine1.ExecStrings(SPython);

 with GetPythonEngine do begin
        try
         presult := PyEval_CallObjectWithKeywords(ExtractPythonObjectFrom(MainModule.screenshot()), nil, nil);
          if (PyBytes_AsStringAndSize(pResult, P, Len) < 0)   then begin
            ShowMessage('This does not work and needs fixing');
            Abort;
          end;
        finally
         _stream := TMemoryStream.Create();
          try
            _stream.Write(P^, Len);
            _stream.Position := 0;
            Memo2.Lines.add(_stream.Size.ToString);
            Image1.Picture.LoadFromStream(_stream);
            application.ProcessMessages;
          finally
            _stream.Free;
          end;
        end;
end;            

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×