Recent

Author Topic: Using TBgraBitmap for screenshot - only one image results  (Read 4371 times)

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Using TBgraBitmap for screenshot - only one image results
« on: January 03, 2022, 11:34:28 am »
I have created a screen capture utility, which I use a lot but it has a very annoying behaviour:
- I adjust the rect to capture a certain area
- I make the screenshot and put it into the clipboard
- I paste it into my image editor
So far all works fine.
- Next I scroll the window I am capturing images from so that the next section I want to clip is inside the rect.
- Again I take a screenshot
- I paste it into the image editor and see the previous capture duplicated!

The only way I have found to get around this is to move and resize the capture rect and then move it back and re-adjust to the same size as before.
Then a capture works to get the correct image!

What am I doing wrong here?

My capture function looks like this:

Code: Pascal  [Select][+][-]
  1. private
  2.       FMyCapture: TBgraBitmap;
  3. ...
  4.  
  5. procedure TfrmMain.miCopyImageClick(Sender : TObject);
  6. begin
  7.   Sleep(300); //To let the pop-up menu disappear
  8.   CopyScreenRect(0);
  9. end;
  10.  
  11. procedure TfrmMain.CopyScreenRect(arg: PtrInt);
  12. var
  13.   Clip: TRect;
  14.   X, Y, W, H: integer;
  15. begin
  16.   try
  17.     Clip := Bounds(frmMain.Left, frmMain.Top, frmMain.Width, frmMain.Height);
  18.     X := frmMain.Left;
  19.     Y := frmMain.Top;
  20.     W := frmMain.Width;
  21.     H := frmMain.Height;
  22.     frmMain.Visible := false; //Hide the form defining Clip
  23.     FMyCapture.TakeScreenShot(Clip);
  24.     frmMain.Visible := true;
  25.     frmMain.Left := X;
  26.     frmMain.Top :=  Y;
  27.     frmMain.Width := W;
  28.     frmMain.Height := H;
  29.     Clipboard.Assign(FMyCapture.Bitmap);
  30.   except
  31.     on E: exception do
  32.       Clipboard.AsText := E.Message;
  33.   end;
  34. end;
  35.  
--
Bo Berglund
Sweden

loaded

  • Hero Member
  • *****
  • Posts: 824
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #1 on: January 03, 2022, 11:49:47 am »
It would be useful to have a look at the demo in the link.
https://forum.lazarus.freepascal.org/index.php/topic,57244.msg425599.html#msg425599
Check out  loaded on Strava
https://www.strava.com/athletes/109391137

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #2 on: January 03, 2022, 12:39:36 pm »
Hi!

Use this:

Code: Pascal  [Select][+][-]
  1. ...
  2. var bmp : TBGRABitmap;
  3.     R : TRect;
  4. begin
  5.   R := Rect (100,100,400,400);
  6.   bmp.TakeScreenshot(R);      
  7.   ....
  8. end;

Winni

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #3 on: January 03, 2022, 01:32:18 pm »
Use this:
Code: Pascal  [Select][+][-]
  1. ...
  2. var bmp : TBGRABitmap;
  3.     R : TRect;
  4. begin
  5.   R := Rect (100,100,400,400);
  6.   bmp.TakeScreenshot(R);      
  7.   ....
  8. end;
Winni
But that is what I am doing, except I create the container using this in FormCreate:
Code: Pascal  [Select][+][-]
  1. FMyCapture := TBgraBitmap.Create;
You are not showing if you have created it...
Concerning the rect coordinates, you are setting a fixed size whereas I am using the form as a template:
Code: Pascal  [Select][+][-]
  1. var
  2.   Clip: TRect;
  3.   X, Y, W, H: integer;
  4. begin
  5.   try
  6.     Clip := Bounds(frmMain.Left, frmMain.Top, frmMain.Width, frmMain.Height);

Note that my problem is not how to take the screenshot but the fact that if the area contained by the rect changes content between two screenshots then the old already captured screenshot is returned instead of a new one.
But if I move the form and change its size and then go back to the old position and size then the new clip will be with new content...

UPDATE:
As a test I modified my code to use a local TBGRABitmap variable inside the CopyScreenRect function where it is created-used-destroyed and then it works fine.

But my program has other functions as well, for instance to save into a disk file and these use the global object I have shown here. So when the object is used that way the problem appears.
« Last Edit: January 03, 2022, 01:44:26 pm by BosseB »
--
Bo Berglund
Sweden

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #4 on: January 03, 2022, 02:00:49 pm »
So if I use this code for capturing then it works OK:

Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.CopyScreenRect(arg: PtrInt);
  2. var
  3.   Clip: TRect;
  4.   X, Y, W, H: integer;
  5. begin
  6.   if Assigned(FMyCapture) then FMyCapture.Free; //To clear any remaining image
  7.   FMyCapture := TBgraBitmap.Create;
  8.   try
  9.     X := frmMain.Left;
  10.     Y := frmMain.Top;
  11.     W := frmMain.Width;
  12.     H := frmMain.Height;
  13.     Clip := Bounds(X, Y, W, H);
  14.     frmMain.Visible := false;
  15.     FMyCapture.TakeScreenShot(Clip);
  16.     frmMain.Visible := true;
  17.     frmMain.Left := X;
  18.     frmMain.Top :=  Y;
  19.     frmMain.Width := W;
  20.     frmMain.Height := H;
  21.     Clipboard.Assign(FMyCapture.Bitmap);
  22.   except
  23.     on E: exception do
  24.       Clipboard.AsText := E.Message;
  25.   end;
  26. end;
  27.  

I do not understand why it does not work in the original version but doing this create/free inside the function is a workaround in any case.
And my other usage of FMyCapture was a mis-read of my code. Those functions actually call this before doing their thing...
--
Bo Berglund
Sweden

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #5 on: January 06, 2022, 01:57:33 pm »
This could be a bug of BGRABitmap. Though I checked the code and the function InvalidateBitmap seems to be called so normally the Bitmap object should be rebuilt.

What if you call FMyCapture.InvalidateBitmap before calling Clipboard.Assign?

Or if you do FMyCapture.SetSize(0,0) before calling FMyCapture.TakeScreenShot ?

Regards
Conscience is the debugger of the mind

Manlio

  • Full Member
  • ***
  • Posts: 162
  • Pascal dev
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #6 on: January 22, 2022, 09:15:08 pm »
I encountered similar problems with TBGRABitmap in the past, and I suspect that there may be some kind of Canvas locking/unlocking mechanism involved, or some caching mechanism, or something along those lines, that is implicitly invoked by certain operations, and which requires some action (which I could never figure out) in order for the object to be completely reset.

And whenever I could not figure it out, I resorted to creating/freeing a new object every time I need it, and stopped worrying about it...

If however someone more knowledgeable can tell us how to completely reset the object, it will be very appreciated :)
manlio mazzon gmail

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #7 on: January 23, 2022, 10:45:40 am »
Hi!
This will rebuild the TBGRAbitmap:

Code: Pascal  [Select][+][-]
  1. var bmp: TBGRAbitmap;
  2. ...
  3. bmp.InvalidateBitmap
  4. ...
  5.  

Winni

AlexTP

  • Hero Member
  • *****
  • Posts: 2365
    • UVviewsoft
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #8 on: January 23, 2022, 10:57:09 am »
That method is mentioned here
https://wiki.freepascal.org/BGRABitmap#Direct_access_to_pixels
But it's deep inside the wiki text and not visible.

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: Using TBgraBitmap for screenshot - only one image results
« Reply #9 on: January 29, 2022, 12:34:04 pm »
Well normally you shouldn't have to call InvalidateBitmap unless you write direct access to pixels. But maybe in this case it is not already called for some reason.
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018