Catturare l'immagine della finestra di un programma mediante le risorse della Classe DesktopWindow e le funzioni esterne del API di X11

Da Gambas-it.org - Wikipedia.

Per catturare l'immagine della finestra di un qualsiasi programma (ma più in generale qualsiasi fienstra) e salvare tale cattura in un file immagine, si potranno utilizzare le risorse della Classe DesktopWindow e alcune funzioni esterne del API di X11. [nota 1]

E' necessario richiamare in Gambas la libreria dinamica condivisa: "libX11.so.6.4.0 ".


Mostriamo un esempio pratico (bisognerà attivare i Componenti gb.desktop e gb.desktop.x11), nel quale sarà catturata un'immagine del programma audio VLC:

Library "libX11:6.4.0"

Public Struct funcs
  create_image As Pointer
  destroy_image As Pointer
  get_pixel As Pointer
  put_pixel As Pointer
  sub_image As Pointer
  add_pixel As Pointer
End Struct

Public Struct XImage
  width As Integer
  height As Integer
  xoffset As Integer
  gformat As Integer
  data As Pointer
  byte_order As Integer
  bitmap_unit As Integer
  bitmap_bit_order As Integer
  bitmap_pad As Integer
  depth As Integer
  bytes_per_line As Integer
  bits_per_pixel As Integer
  red_mask As Long
  green_mask As Long
  blue_mask As Long
  obdata As Pointer
  func As Struct Funcs
End Struct

Private Enum XYBitmap = 0, XYPixmap, ZPixmap

' Display *XOpenDisplay(char *display_name)
' Opens a connection to the X server that controls a display.
Private Extern XOpenDisplay(display_name As Pointer) As Pointer

' unsigned long XAllPlanes()
' Returns a value with all bits set to 1 suitable for use in a plane argument to a procedure.
Private Extern XAllPlanes() As Long

' XImage *XGetImage(Display *display, Drawable d, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format)
' Returns a pointer to an XImage structure.
Private Extern XGetImage(display As Pointer, d As Long, x As Integer, y As Integer, width As Integer, height As Integer, plane_mask As Long, xformat As Integer) As XImage

' XCloseDisplay(Display *display)
' Closes the connection to the X server for the display specified in the Display structure and destroys all windows.
Private Extern XCloseDisplay(display As Pointer)


Public Sub Button1_Click()
 
 dim dw As DesktopWindow
 Dim dsp As Pointer
 Dim xi As XImage
 Dim im As Image
 Dim st As Stream
 Dim i As Integer
 
' Individua il numero identificativo della finestra del programma VLC:
 i = Desktop.FindWindow("*VLC*", Null, Null)[0]
  
' Si passa il numero identificatore della finestra alla Classe "DesktopWindows" per generare una variabile che punti a quella finestra:
 dw = New DesktopWindow(i)
  
 dsp = XOpenDisplay(0)
 If dsp == 0 Then Error.Raise("Impossibile aprire una connessione al server X !")
 
' Otteniamo un puntatore alla "Struttura" contenente i dati dell'immagine disegnata nella "DrawingArea":
 xi = XGetImage(dsp, i, 0, 0, dw.W, dw.H, XAllPlanes(), ZPixmap)
 If IsNull(xi) Then Error.Raise("Impossibile ottenere un 'Puntatore' ai dati dell'immagine della DrawingArea !")
    
' Creiamo un semplice oggetto di tipo "Image":
 im = New Image(dw.W, dw.H)
 If IsNull(im) Then Error.Raise("Impossibile creare un oggetto 'Image' !")
  
' Utilizziamo ovviamente i "Memory Stream" per scrivere nell'area di memoria dell'oggetto "Image", destinata ai dati attinenti ai pixel, il cui indirizzo di memoria è ritornato dalla proprietà ".Data" della variabile di tipo "Image":
 st = Memory im.Data For Write
  
 For i = 0 To im.W * im.H * Len(im.Format)
   Write #st, Byte@(xi.data + i) As Byte
 Next
  
 st.Close
  
' Genera in fine il file immagine finale:
 im.Save("/tmp/test.png", 100)
 
' Va in chiusura:
 XCloseDisplay(dsp)
  
End


Note

[1] Vedi anche le seguenti pagine: