Ottenere l'immagine di una pagina web

Da Gambas-it.org - Wikipedia.

Per ottenere l'immagine di un'intera pagina web [Nota 1], caricata all'interno dell'Oggetto "WebView", potremo adottare alcune modalità.

Uso della Classe DesktopWindow

Questa modalità prevede l'uso in particolare del Metodo ".GetScreeshot()" della Classe DesktopWindow.

Mostriamo un esempio pratico (è necessario attivare anche i Componenti gb.desktop e gb.desktop.x11):

Private wv As WebView


Public Sub Form_Open()

 With wv = New WebView(Me) As "Webv"
   .X = 0
   .Y = 0
   .W = 640
   .H = 640
' Carica la pagina web, della quale creare un'immagine finale:
   .Url = "http://www.gambas-it.org"
 End With
  
End


Public Sub Webv_Finish()
 
 Dim dw As DesktopWindow
 Dim pc As Picture
  
' Crea un Oggetto "DesktopWindow" che punta all'Oggetto "WebView":
 With dw = New DesktopWindow(wv.Handle)
' Esegue una schermata del contenuto corrente dell'Oggetto "WebView", generandone un'immagine di tipo "Picture":
   pc = .GetScreenshot(True)
 End With
  
' Salva l'immagine di tipo "Picture" finale della pagina web caricata inizialmente:
 pc.Save("/tmp/test.png", 100)
  
End


Uso della Classe Desktop

Questa modalità prevede l'uso in particolare del Metodo ".Screeshot()" della Classe Desktop.

Mostriamo un esempio pratico (è necessario attivare anche i Componenti "gb.desktop" e "gb.desktop.x11"):

Private wv As WebView


Public Sub Form_Open()

 With wv = New WebView(Me) As "Webv"
   .X = 0
   .Y = 0
   .W = 640
   .H = 640
' Carica la pagina web, della quale creare un'immagine finale:
   .Url = "https://www.gambas-it.org"
 End With
  
End


Public Sub Webv_Finish()
 
 Dim pc As Picture
  
' Esegue una schermata del contenuto corrente dell'Oggetto "WebView", generandone un'immagine di tipo "Picture":
 pc = Desktop.Screenshot(wv.ScreenX, wv.ScreenY, wv.Width, wv.Height)
     
' Salva l'immagine di tipo "Picture" finale della pagina web caricata inizialmente:
 pc.Save("/tmp/test.png", 100)
  
End


Uso delle risorse del Componente gb.media

Public Sub Form_Open()

 WebView1.Url = "https://www.gambas-it.org"

End


Public Sub WebView1_Finish()  ' Si solleva questo Evento, quando la "WebView" carica completamente la pagina web

 Dim pl As MediaPipeline
 Dim src, con, png, snk As MediaControl

 pl = New MediaPipeline

 src = New MediaControl(pl, "ximagesrc")
 src["xid"] = WebView1.Id                ' Assegna il numero identificativo del Controllo "WebView", del quale si otterrà il file PNG
 con = New MediaControl(pl, "videoconvert")
 png = New MediaControl(pl, "pngenc")
 snk = New MediaControl(pl, "filesink")
 snk["location"] = "/tmp/immagine_pagina_web.png"

 src.LinkTo(con)
 con.LinkTo(png)
 png.LinkTo(snk)

' Crea il file PNG e poi chiude il flusso di dati:
 pl.Play()
 pl.Stop()
 pl.Close

End


Uso delle funzioni esterne del API di X11

Questa modalità prevede l'uso di alcune funzioni esterne appartenenti al API del sistema grafico X11. E' pertanto richiesta la dichiarazione in Gambas della libreria condivisa: "libX11.so.6.4.0 ".

L'assegnazione dei dati dei pixel della pagina mostrata dal WebView, contenuti nell'area di memoria puntata dal Puntatore restituito dalla funzione esterna "XGetImage()" della libreria di X11, direttamente all'area di memoria puntata dalla Proprietà ".Data" di un Oggetto Image preliminarmente creato.

Nell'esempio pratico, che segue, porremo sul Form un WebView e un Button:

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 Form_Open()

 WebView1.Url = "https://www.gambas-it.org/smf/"
 
End


Public Sub Button1_Click()
 
 Dim dsp As Pointer
 Dim xi As XImage
 Dim im As Image
 Dim st As Stream
 Dim i As Integer
  
 dsp = XOpenDisplay(0)
 If dsp == 0 Then Error.Raise("Impossibile aprire una connessione al server X !")
  
' Otteniamo un puntatore alla "Struttura" dei dati della pagina web mostrata dal "WebView":
 xi = XGetImage(dsp, WebView1.Handle, 0, 0, WebView1.W, WebView1.H, XAllPlanes(), ZPixmap)
 If IsNull(Image) Then Error.Raise("Impossibile ottenere un 'Puntatore' ai dati dell'immagine del Form !")
  
' Creiamo un semplice oggetto di tipo "Image":
 im = New Image(Me.W, Me.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:
 im.Save("/percorso/del/file/immagine.xxx", 100)
  
' Va in chiusura:
 XCloseDisplay(dsp)
  
End

oppure anche così:

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 Form_Open()

 WebView1.Url = "https://www.gambas-it.org/smf/"
 
End


Public Sub Button1_Click()
 
 Dim dsp, p As Pointer
 Dim xi As XImage
 Dim bb As Byte[]
 Dim i As Integer
 Dim st As Stream
 Dim im As Image
  
 dsp = XOpenDisplay(0)
 If dsp == 0 Then Error.Raise("Impossibile aprire una connessione al server X !")
  
' Otteniamo un puntatore alla "Struttura" dei dati della pagina web mostrata dal "WebView":
 xi = XGetImage(dsp, WebView1.Handle, 0, 0, WebView1.W, WebView1.H, XAllPlanes(), ZPixmap)
 If IsNull(Image) Then Error.Raise("Impossibile ottenere un 'Puntatore' ai dati dell'immagine del Form !")
  
 bb = New Byte[]
  
 For i = 0 To (WebView1.W * WebView1.H * 4) - 1
   bb.Push(Byte@(xi.data + i))
 Next
  
' Creiamo un semplice oggetto di tipo "Image":
 im = New Image(WebView1.W, WebView1.H)
 If IsNull(im) Then Error.Raise("Impossibile creare un oggetto 'Image' !")
  
 p = Pointer@(Object.Address(im) + (SizeOf(gb.Pointer) * 2))
  
' Scriviamo i dati immagine grezzi, ottenuti dalla funzione XGetImage(), nell'area di memoria puntata dal membro "*data" della Struttura "GB_IMG" contenuta nel file sorgente ".../main/lib/image/gb.image.h":
 st = Memory p For Write
 bb.Write(st, 0, bb.Count)
 st.Close
  
' Genera in fine il file immagine:
 im.Save("/percorso/del/file/immagine.xxx", 100)
  
' Va in chiusura:
 XCloseDisplay(dsp)
  
End


Uso delle funzioni esterne del API di X11 e di ImLib2

L'uso delle risorse delle librerie esterne X11 e ImLib2 richiede nel codice Gambas la dichiarazione delle seguenti librerie condivise:

  • "libX11.so.6.4.0 "
  • "libImlib2.so.12.2 "

Mostriamo di seguito un semplice esempio, nel quale poniamo un Oggetto WebView e un Button:

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)


Library "libImlib2:1.12.2"

' Imlib_Image imlib_create_image_using_data(int width, int height, DATA32 * data)
' Creates an image from the image data - in the format of a DATA32 (32 bits) per pixel in a linear array - specified with the width and the height specified.
Private Extern imlib_create_image_using_data(width As Integer, height As Integer, data As Pointer) As Pointer

' void imlib_context_set_image(Imlib_Image image)
' Sets the current image Imlib2 will be using with its function calls.
Private Extern imlib_context_set_image(Iimage As Pointer)

' void imlib_save_image(const char *filename)
' Saves the current image in the format specified by the current image's format settings to the filename.
Private Extern imlib_save_image(filename As String)

' void imlib_free_image(void)
' Frees the image that is set as the current image in Imlib2's context.
Private Extern imlib_free_image()


Public Sub Form_Open()

 WebView1.Url = "http://www.gambas-it.org/smf/"
 
End


Public Sub Button1_Click()
 
 Dim dsp, immago As Pointer
 Dim xi As XImage
  
 dsp = XOpenDisplay(0)
 If dsp == 0 Then Error.Raise("Impossibile aprire una connessione al server X !")
  
' Otteniamo un puntatore alla "Struttura" contenente i dati della pagina web mostrata dal "WebView":
 xi = XGetImage(dsp, WebView1.Handle, 0, 0, WebView1.W, WebView1.H, XAllPlanes(), ZPixmap)
 If IsNull(Image) Then Error.Raise("Impossibile ottenere un 'Puntatore' ai dati del WebView !")
  
' Viene creata l'immagine dai dati grezzi passando il "Puntatore" ai dati grezzi dell'immagine:
 immago = imlib_create_image_using_data(WebView1.W, WebView1.H, xi.data)
 If immago == 0 Then Error.Raise("Impossibile creare l'immagine dai dati grezzi acquisiti !")
   
 imlib_context_set_image(immago)
   
' L'immagine creata viene salvata in un file immagine. Al nome del file immagine da creare va indicata l'estensione del formato immagine desiderato:
 imlib_save_image("/percorso/dove/salvare/il/file/immagine.xxx")
  
' Va in chiusura:
 imlib_free_image()
 XCloseDisplay(dsp)
 
End


Note

[1] In via generale, per scaricare un file immagine da un sito web: Scaricare una immagine da un sito internet