Estrarre il file thumbnail contenuto nel file odt

Da Gambas-it.org - Wikipedia.

Il file di formato ODT, file di testo facente parte della famiglia dei file ODF, è sostanzialmente un file XML contenuto in un file .zip . Infatti all'interno del file compresso ODT si trova - tra gli altri - anche la cartella Thumbnails/, la quale a sua volta contiene un file immagine in formato .png di piccole dimensioni che riproduce quanto mostrato dal file odt.

Per estrarre il file thumbnail .png, contenuto nel file .odt, senza dover preventivamente utilizzare un decompressore il file medesimo, si può adottare il seguente codice che utilizza esclusivamente risorse native di Gambas:

Public Sub Form_Open()
 
 Dim fl As File
 Dim i, sp As Integer
 Dim bb As Byte[]
 Dim s As String
 
  fl = Open "/percorso/del/file.odt" For Read
   
' Legge la dimensione del file immagine ".png" presente nel file ".odt":
  Seek #fl, 99
  Read #fl, i
  
' Legge dopo quanti byte iniziano i dati del file immagine ".png":
  Read #fl, sp
  
' Ci si sposta sul primo byte dei dati del file immagine ".png":
  Seek #fl, Seek(fl) + sp
  
' Legge i soli dati appartenenti al file immagine ".png":
  With bb = New Byte[i]
    .Read(fl, 0, i)
' Salva i dati in una variabile di tipo "Stringa":
    s = .ToString(0, i)
  End With
  
  fl.Close
  
' Salva i dati letti in un nuovo file immagine ".png" esternamente al file ".odt":
  File.Save("/percorso/del/file.png", s)
  
  PictureBox1.Picture = Picture.Load("/percorso/del/file.png")
  
End


Mostrare in una PictureBox l'immagine del thumbnail senza creare un file immagine d'appoggio

Se si intende mostrare, per esempio, in una PictureBox l'immagine del thumbnail senza creare un file immagine d'appoggio (come avviene nell'esempio precedente), allora si potranno tulizzare alcune risorse del API di libgdk_pixbuf.

Per poter fruire in Gambas di tali risorse, sarà necessario aver installato e richiamare la libreria dinamica condivisa: "libgdk_pixbuf-2.0.so.0.3000.7"


Mostriamo un esempio:

Library "libgdk_pixbuf-2.0:0.3000.7"

' GdkPixbufLoader * gdk_pixbuf_loader_new(void)
' Creates a new pixbuf loader object.
Private Extern gdk_pixbuf_loader_new() As Pointer

' gboolean gdk_pixbuf_loader_write (GdkPixbufLoader *loader, const guchar *buf, gsize count, GError **error)
' Causes a pixbuf loader to parse the next count bytes of an image.
Private Extern gdk_pixbuf_loader_write(loader As Pointer, buf As Pointer, count As Integer, Gerror As Pointer)

' gboolean gdk_pixbuf_loader_close (GdkPixbufLoader *loader, GError **error)
' Informs a pixbuf loader that no further writes.
Private Extern gdk_pixbuf_loader_close(loader As Pointer, Gerror As Pointer)

' GdkPixbuf * gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader)
' Queries the GdkPixbuf that a pixbuf loader is currently creating.
Private Extern gdk_pixbuf_loader_get_pixbuf(loader As Pointer) As Pointer

' int gdk_pixbuf_get_width (const GdkPixbuf *pixbuf)
' Queries the width of a pixbuf.
Private Extern gdk_pixbuf_get_width(pixbuf As Pointer) As Integer

' int gdk_pixbuf_get_height (const GdkPixbuf *pixbuf)
' Queries the height of a pixbuf.
Private Extern gdk_pixbuf_get_height(pixbuf As Pointer) As Integer

' int gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf)
' Queries the number of channels of a pixbuf.
Private Extern gdk_pixbuf_get_n_channels(pixbuf As Pointer) As Integer

' gboolean gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf)
' Queries whether a pixbuf has an alpha channel (opacity information).
Private Extern gdk_pixbuf_get_has_alpha(pixbuf As Pointer) As Boolean

' guchar * gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf)
' Queries a pointer to the pixel data of a pixbuf.
Private Extern gdk_pixbuf_get_pixels(pixbuf As Pointer) As Pointer


Public Sub Form_Open()
 
 Dim lo, pb, dati As Pointer
 Dim fl As File
 Dim i, sp, w, h, c, bo, whc As Integer
 Dim bb, cc As Byte[]
 Dim st As Stream
 Dim immago As Image
 
  fl = Open "/percorso/del/file.odt" For Read
   
  Seek #fl, 99
  Read #fl, i
   
  Read #fl, sp
  Seek #fl, Seek(fl) + sp
   
  With bb = New Byte[i]
    .Read(fl, 0, i)
  End With
   
  fl.Close
  
  lo = gdk_pixbuf_loader_new()
  
  gdk_pixbuf_loader_write(lo, bb.data, bb.count, 0)
  
  gdk_pixbuf_loader_close(lo, 0)
  
  pb = gdk_pixbuf_loader_get_pixbuf(lo)
  
  w = gdk_pixbuf_get_width(pb)
  Print "Larghezza:   "; w; " pixel"
  h = gdk_pixbuf_get_height(pb)
  Print "Altezza:     "; h; " pixel"
  c = gdk_pixbuf_get_n_channels(pb)
  Print "Canali:      "; c
  bo = gdk_pixbuf_get_has_alpha(pb)
  Print "Canale Alfa: "; CBool(bo)
  
  dati = gdk_pixbuf_get_pixels(pb)
 
  whc = w * h * c
  
' Dereferenziamo il "Puntatore" con i "Memory Stream", e ne leggiamo i valori contenuti (i dati/byte grezzi dei pixel) dell'immagine:
  st = Memory dati For Read
  With bb = New Byte[whc]
    .Read(st, 0, .Count)
  End With
  st.Close
  
  For i = w * c To whc - 1 Step w * c
    bb.Remove(i, 1)
  Next
  
  cc = New Byte[bb.Count]
  For i = 0 To cc.Count - 1 Step 3
    cc[i + 2] = bb[i]
    cc[i + 1] = bb[i + 1]
    cc[i] = bb[i + 2]
  Next
  
  For i = 3 To w * h * 4.023 Step 4
    cc.Add(&FF, i)
  Next
  
  With immago = New Image(w, h, 0, 0)
    st = Memory .Data For Write
  End With
  cc.Write(st, 0, cc.Count)
  st.Close
  
  With PictureBox1
    .X = 10
    .Y = 10
    .W = w
    .H = h
    .Picture = immago.Picture
  End With
  
End



Riferimenti