Page 1 of 1

GrabDrawingImage()

Posted: Sat Dec 15, 2012 2:45 pm
by IdeasVacuum
I know how to capture an image using Windows API, but I thought I'd try GrabDrawingImage() as it is cross-platform:

Code: Select all

UsePNGImageEncoder()

Enumeration
#Wn
#Image
EndEnumeration

     If OpenWindow(#Wn,0,0,200,200,"Win",#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered)

            SetWindowColor(#Wn,RGB(0,96,96))

             If StartDrawing(WindowOutput(#Wn))
             
                         ;CreateImage(#Image, 200, 200, 24)
                   GrabDrawingImage(#Image, 0, 0, 200, 200)
                           StopDrawing()
             
                             SaveImage(#Image, "C:\Image.png", #PB_ImagePlugin_PNG)
             EndIf
             
             Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

     EndIf

End
Result is a blank image?

Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 3:47 pm
by Michael Vogel
I fear, the window gets invalidated, when GrabDrawingImage gets called. When pressing the button (see code below), you get the colored background but not the lines. I've tried to insert some WaitEvents to allow painting the lines before grabbing the content with no changes in the result.

Code: Select all

UsePNGImageEncoder()

Enumeration
	#Wn
	#Image
EndEnumeration

If OpenWindow(#Wn,0,0,400,200,"Win",#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
	ButtonGadget(33,0,0,200,20,"Hi")
	CreateImage(#Image,200,200,32)
	ImageGadget(99,200,0,200,200,ImageID(#Image))

	SetWindowColor(#Wn,RGB(0,96,96))

	Repeat
		Select WaitWindowEvent()
		Case #PB_Event_CloseWindow
			quit=#True
		Case #PB_Event_Gadget
			If StartDrawing(WindowOutput(#Wn))
				LineXY(50,50,150,150,#Red)
				LineXY(150,50,50,150,#Yellow)
				GrabDrawingImage(#Image,0,0,200,200)
				StopDrawing()
			EndIf
			SetGadgetState(99,ImageID(#Image))
		EndSelect

	Until quit

EndIf

Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 5:56 pm
by luis
IdeasVacuum wrote:Result is a blank image?
Yes.


I'll add something else to the reply :wink:

1) you should wait for all messages to be processed before capturing the window or some pieces could be missing

2) the grabbed image is 32 bit and the alpha is set to fully transparent for the background so you have to set it to fully opaque or you will get the blank image you are reporting (since in your example the window contained background only).

Code: Select all

UsePNGImageEncoder()

Enumeration
#Wn
#Image
#btn
EndEnumeration

Procedure GetIt()
StartDrawing(WindowOutput(#Wn))
 GrabDrawingImage(#Image, 0, 0, 200, 200)
StopDrawing()

StartDrawing(ImageOutput(#Image))
 DrawingMode(#PB_2DDrawing_AlphaChannel)
 Box(0,0,200,200,RGBA(0,0,0,255))    
StopDrawing()

SaveImage(#Image, "C:\Image.png", #PB_ImagePlugin_PNG)       
EndProcedure

If OpenWindow(#Wn,0,0,200,200,"Win",#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered)

    SetWindowColor(#Wn,RGB(0,96,96))
    ButtonGadget(#btn, 10, 10, 180, 30, "Hello")
        
     
    Repeat 
        iEvent = WaitWindowEvent() 
    Until iEvent = #PB_Event_CloseWindow
    
    GetIt()    

EndIf


Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 7:26 pm
by BasicallyPure
@luis,
Hmmm, I don't see how putting GrabDrawingImage before you actually draw on the image demonstrates the GrabDrawingImage function.
It looks to me like your code only saves the image that you drew, not the image that you grabbed.

I tried but was unsuccessful in using GrabDrawingImage directly from a window.
I did discover that if you use drawingmode #PB_2DDrawing_XOr the lines are visible in the grabbed image using Michael Vogel's code.

GrabDrawingImage seems to work correctly when used with another image and presumably screen and canvas would work as well. It seems that it fails only when used directly from a window.

Code: Select all

;
Enumeration
   #ImageGadget_01
   #ImageGadget_02
   #Image_01
   #Image_02
   #ButtonDraw
   #ButtonGrab
EndEnumeration

If OpenWindow(0,0,0,434,240,"Win",#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
   SetWindowColor(0,RGB(0,96,96))
   
   ButtonGadget(#ButtonDraw,010,5,80,20,"Draw")
   ButtonGadget(#ButtonGrab,220,5,80,20,"Grab")
   CreateImage(#Image_01,200,200)
   CreateImage(#Image_02,200,200)
   ImageGadget(#ImageGadget_01,010,30,200,200,ImageID(#Image_01),#PB_Image_Border)
   ImageGadget(#ImageGadget_02,220,30,200,200,ImageID(#Image_02),#PB_Image_Border)
   
   Repeat
      Select WaitWindowEvent()
         Case #PB_Event_CloseWindow
            quit = #True
         Case #PB_Event_Gadget
            Select EventGadget()
               Case #ButtonDraw
                  If StartDrawing(ImageOutput(#Image_01))
                     Box(040,75,50,50,Random($FFFFFF))
                     Box(110,75,50,50,Random($FFFFFF))
                     StopDrawing()
                     SetGadgetState(#ImageGadget_01,ImageID(#Image_01))
                  EndIf
               Case #ButtonGrab
                  If StartDrawing(ImageOutput(#Image_01))
                     GrabDrawingImage(#Image_02,0,0,200,200)
                     StopDrawing()
                     SetGadgetState(#ImageGadget_02,ImageID(#Image_02))
                  EndIf
            EndSelect
      EndSelect
   Until quit
   
EndIf

Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 7:53 pm
by luis
Hi!
BasicallyPure wrote: Hmmm, I don't see how putting GrabDrawingImage before you actually draw on the image demonstrates the GrabDrawingImage function.
I didn't draw on the image, I changed the alpha channel (#PB_2DDrawing_AlphaChannel).
BasicallyPure wrote: It looks to me like your code only saves the image that you drew, not the image that you grabbed.
No. GrabDrawingImage did already transfer the content of the window client area to the image. What GrabDrawingImage grabbed (the pixels) wasn't changed. The problem is the image is transparent and you have to do something about it.
Did you look at the saved image by the way ? Does it looks like a box to you ? So how can be what I drawn (a black box) when it does contain the window with the button ? :)
BasicallyPure wrote: GrabDrawingImage seems to work correctly when used with another image and presumably screen and canvas would work as well. It seems that it fails only when used directly from a window.
And that was the point of the original question. Using it with windowoutput(). Using the two steps demonstrated above the image was grabbed and saved successfully even if GrabDrawingImage behave differently in this context.

Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 9:02 pm
by IdeasVacuum
the grabbed image is 32 bit and the alpha is set to fully transparent
That I did not know - I expected it to be 24bit RGB - would be good to mention in the Help.

I think my example was a bad choice! :?

Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 9:36 pm
by BasicallyPure
@luis,
Thanks for the clarification.
Now I think I finally understand.
Not being familiar with how alpha channels work I was confused by your code.
I did some modification to the code to make sure I understood.
IdeasVacuum wrote:would be good to mention in the Help
I second that.

Code: Select all

; demonstration of how to use GrabDrawingImage() with Window as source
;
Enumeration
   #Wn
   #Image
   #btn
   #ImgGad
EndEnumeration

Procedure GetIt()
   ;grab image directly from window
   ;grabbed image is 32 bit and alpha is fully transparent
   StartDrawing(WindowOutput(#Wn))
      GrabDrawingImage(#Image, 0, 0, 200, 200)
   StopDrawing()
   
   ;adjust the image alpha channel to opaque
   StartDrawing(ImageOutput(#Image))
      DrawingMode(#PB_2DDrawing_AlphaChannel)
      Box(0,0,200,200,RGBA(0,0,0,255))
   StopDrawing()
EndProcedure

If OpenWindow(#Wn,0,0,400,200,"Win",#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
   
   SetWindowColor(#Wn,RGB(0,96,96))
   ButtonGadget(#btn, 10, 10, 180, 30, "Grab and display")
   ImageGadget(#ImgGad,200,0,200,200,0)
   
   ;draw something on the window
   StartDrawing(WindowOutput(#Wn))
   LineXY(50,50,150,150,#Red)
   LineXY(150,50,50,150,#Yellow)
   StopDrawing()
   
   Repeat
      iEvent = WaitWindowEvent() 
      If iEvent = #PB_Event_Gadget And EventGadget() = #btn
         GetIt()
         SetGadgetState(#ImgGad,ImageID(#Image)) ;display the grabbed image
      EndIf
   Until iEvent = #PB_Event_CloseWindow
   
EndIf


Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 9:40 pm
by skywalk
Is there a cross platform way to also grab the window title and borders?

Re: GrabDrawingImage()

Posted: Sat Dec 15, 2012 9:47 pm
by luis
@BasicallyPure

Yup, please note only what it has been drawn directly on the background (and the background itself) is fully transparent.
The gadgets, for example, are visible (opaque).
If you comment from your last code the alpha filling, the button is still visible.
:?

Re: GrabDrawingImage()

Posted: Mon Dec 17, 2012 12:17 pm
by IdeasVacuum
... yeah, done a few experiments and understand it now. The 'problem' is, it does what it is designed to do, rather than what I thought it would do :mrgreen: