Differenze tra le versioni di "Creare una Image direttamente dai dati di un file immagine scaricato da internet senza ricreare il file nella memoria di massa"

Da Gambas-it.org - Wikipedia.
 
(Una versione intermedia di uno stesso utente non è mostrata)
Riga 1: Riga 1:
Il problema qui posto  è quello di come creare una immagine di tipo ''Image'' (da assegnare convertita in una ''Picture'' ad una ''PictureBox'') direttamente dai dati di un file immagine scaricato da internet, senza che tale file sia stato salvato in un percorso di una cartella nella memoria di massa, e quindi caricato con l'apposito metodo ''.Load()'' della Classe ''Image''.
+
#REDIRECT [[Scaricare_una_immagine_da_un_sito_internet]]
 
 
Per scaricare il file immagine ci serviremo delle risorse della Classe ''HttpClient'', attivando i Componenti Gambas ''gb.net'' e ''gb.net.curl''. Però tale Classe consente di scaricare in dati formato ''Stringa'' il file immagine "''così com'è''". Vengono, cioè scaricati i dati del file immagine nel suo formato in quanto tale, e ''non'' già i suoi dati immagine ''grezzi''. Ciò significa che se viene scaricato un file immagine compresso non potremo fare altro che salvarlo dapprima in memoria dura e solo successivamente caricarlo in memoria RAM con le apposite risorse della Classe ''Image''.
 
 
 
Ricapitolando: l'unica cosa, che abbiamo nella RAM immediatamente dopo lo scarico, è una variabile di tipo ''Stringa'' contenente tutti i dati del file immagine.  La parte difficile è come assegnare ad una ''PictureBox'' i dati del file immagine "''così com'è'' " contenuti dalla variabile di tipo ''Stringa'' senza passare preliminarmente per il metodo ''.Load()'' della Classe ''Image''.
 
 
 
Il problema può essere risolto, purché l'immagine da scaricare abbia il canale Alfa e dunque sia di formato a 32-bit - RGBA. Bisognerà, però, utilizzare alcune funzioni esterne di ''gdk_pixbuf'' richiamando nel progetto Gambas la libreria condivisa: "''libgtk-3.so.0.2404.16'' ".
 
 
 
Mostriamo di seguito il codice con un esistente indirizzo web di un'immagine ''PNG'' da scaricare (è necessario attivare anche i Componenti "gb.net" e "gb.net.curl").
 
Private myhttp As New HttpClient As "myhttp" 
 
 
 
Library "libgtk-3:0.2404.16"
 
 
<FONT Color=gray>' ''GdkPixbufLoader * gdk_pixbuf_loader_new(void)''
 
' ''Creates a new pixbuf loader object.''</font>
 
Private Extern gdk_pixbuf_loader_new() As Pointer
 
 
<FONT Color=gray>' ''gboolean gdk_pixbuf_loader_write (GdkPixbufLoader *loader, const guchar *buf, gsize count, GError **error)'
 
' ''Cause a pixbuf loader to parse the next count bytes of an image.''</font>
 
Private Extern gdk_pixbuf_loader_write(lo As Pointer, buf As Pointer, i As Integer, po As Pointer)
 
 
<FONT Color=gray>' ''gboolean gdk_pixbuf_loader_close (GdkPixbufLoader *loader, GError **error)'
 
' ''Informs a pixbuf loader that no further writes.''</font>
 
Private Extern gdk_pixbuf_loader_close(lo As Pointer, po As Pointer)
 
 
<FONT Color=gray>' ''GdkPixbuf * gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader)'
 
' ''Queries the GdkPixbuf that a pixbuf loader is currently creating.''</font>
 
Private Extern gdk_pixbuf_loader_get_pixbuf(lo As Pointer) As Pointer
 
 
<FONT Color=gray>' ''guchar * gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf)'
 
' ''Queries a pointer to the pixel data of a pixbuf.''</font>
 
Private Extern gdk_pixbuf_get_pixels(GdkPixbuf As Pointer) As Pointer
 
 
<FONT Color=gray>' ''int gdk_pixbuf_get_width (const GdkPixbuf *pixbuf)'
 
' ''Queries the width of a pixbuf.''</font>
 
Private Extern gdk_pixbuf_get_width(GdkPixbuf As Pointer) As Integer
 
 
<FONT Color=gray>' ''int gdk_pixbuf_get_height (const GdkPixbuf *pixbuf)'
 
' ''Queries the height of a pixbuf.''</font>
 
Private Extern gdk_pixbuf_get_height(GdkPixbuf As Pointer) As Integer
 
 
<FONT Color=gray>' ''int gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf)'
 
' ''Queries the number of channels of a pixbuf.''</font>
 
Private Extern gdk_pixbuf_get_n_channels(GdkPixbuf As Pointer) As Integer
 
 
<FONT Color=gray>' ''gboolean gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf)'
 
' ''Queries whether a pixbuf has an alpha channel (opacity information).''</font>
 
Private Extern gdk_pixbuf_get_has_alpha(GdkPixbuf As Pointer) As Boolean
 
 
 
'''Public''' Sub Button1_Click()
 
 
 
<FONT Color=gray>' ''Invia la richiesta al server per scaricare un file immagine:''</font>
 
  myhttp.URL = "https&#058;//www.freepnglogos.com/uploads/eye-png/eye-psd-vector-vectorhqm-18.png"
 
  myhttp.Timeout = 15
 
 
<FONT Color=gray>' ''Lasciando il secondo parametro vuoto, i dati dell'immagine vengono salvati soltanto in memoria:''</font>
 
  myhttp.Get()
 
   
 
'''End'''
 
 
'''Public''' Sub MyHTTP_Finished()
 
 
  Dim s As String
 
 
  MyHTTP.Close
 
 
 
<FONT Color=gray>' ''Trasferiamo in una variabile stringa i dati dell'immagine scaricata e salvata in memoria:''</font>
 
  s = myhttp.Peek()
 
  Print "Immagine scaricata !\n\nDimensione: "; Len(s); " byte"
 
 
 
  Immagine(s)
 
 
 
'''End'''
 
 
'''Private''' Procedure Immagine(im As String)
 
 
 
  Dim bb, bb2 As Byte[]
 
  Dim w, h As Integer
 
  Dim loader, pixbuf, dati As Pointer
 
  Dim c As Byte
 
  Dim bo As Boolean
 
  Dim st As Stream
 
  Dim imago As Image
 
 
 
  bb = Byte[].FromString(im)
 
 
 
  loader = gdk_pixbuf_loader_new()
 
  If loader == 0 Then Error.Raise("Errore !")
 
 
 
  gdk_pixbuf_loader_write(loader, bb.data, bb.count, 0)
 
 
 
  gdk_pixbuf_loader_close(loader, 0)
 
 
 
  pixbuf = gdk_pixbuf_loader_get_pixbuf(loader)
 
  If pixbuf == 0 Then Error.Raise("Errore !")
 
 
 
  w = gdk_pixbuf_get_width(Pixbuf)
 
  Print "Larghezza: "; w; " pixel"
 
  h = gdk_pixbuf_get_height(Pixbuf)
 
  Print "Altezza:  "; h; " pixel"
 
  c = gdk_pixbuf_get_n_channels(Pixbuf)
 
  Print "Canali:    "; c
 
 
 
<FONT Color=gray>' ''Verifichiamo che l'immagine scaricata abbia il canale Alfa:''</font>
 
  bo = gdk_pixbuf_get_has_alpha(Pixbuf)
 
  If bo = False Then Error.Raise("L'immagine scaricata è priva del canale Alfa !")
 
 
 
  dati = gdk_pixbuf_get_pixels(Pixbuf)
 
  If dati == 0 Then Error.Raise("Impossibile ottenere un 'Puntatore' ai dati dei pixel dell'immagine !")
 
 
 
<FONT Color=gray>' ''Carichiamo i dati nel vettore "bb[]" per gestire successivamente i dati grezzi dei pixel:''</font>
 
  st = Memory dati For Read
 
 
 
  With bb = New Byte[w * h * c]
 
    .Read(st, 0, .count)
 
  End With
 
 
 
<FONT Color=gray>' ''Effettua la correzione della disposizione dei dati RGB dei pixel dell'immagine scaricata:''</font>
 
  bb2 = Corregge(bb)
 
 
 
  st.Close
 
 
 
<FONT Color=gray>' ''Viene preparata la variabile di tipo Image per la gestione dei dati del futuro nuovo file immagine:''</font>
 
  With imago = New Image(w, h, 0, 0)
 
    st = Memory .Data For Write
 
  End With
 
 
 
<FONT Color=gray>' ''Scrive i dati presenti nel vettore "bb[]" nell'area di memoria puntata dal Puntatore ".Data" della variabile di tipo "Image":''</font>
 
  bb2.Write(st, 0, bb2.Count)
 
 
 
  st.Close
 
 
 
  With PictureBox1
 
    .W = w
 
    .H = h
 
    .Picture = imago.Picture
 
  End With
 
 
 
'''End'''
 
 
'''Private''' Function Corregge(vett As Byte[]) As Byte[]
 
 
 
  Dim i As Integer
 
  Dim bb As Byte[]
 
 
 
  bb = New Byte[vett.Count]
 
 
 
  For i = 0 To vett.Max Step 4
 
    bb[i + 1] = vett[i + 1]
 
    bb[i + 2] = vett[i]
 
    bb[i] = vett[i + 2]
 
    bb[i + 3] = vett[i + 3]
 
  Next
 
 
 
  Return bb
 
 
 
'''End'''
 

Versione attuale delle 20:37, 7 dic 2021