Estrarre il file thumbnail contenuto nel file odt
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.
Uso delle sole risorse di Gambas
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
Uso delle risorse del API di libzip.so.2.1.0
Volendo si possono utilizzare alcune risorse della libreria "libzip.so.2.1.0", la quale pertanto dovrà essere presente nel sistema ed essere richiamata nel progetto Gambas.
Mostriamo un esempio pratico:
Library "libzip:2.1.0"
Public Struct zip_stat
valid As Long
name As Pointer
index As Long
size As Long
comp_size As Long
mtime As Long
crc As Integer
comp_method As Short
encryption_method As Short
flags As Integer
End Struct
' struct zip *zip_open(const char *, int, int *)
' Open zip archive.
Private Extern zip_open(path As String, flags As Integer, errorp As Pointer) As Pointer
' zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t)
' Get number of files in archive.
Private Extern zip_get_num_entries(archive As Pointer, flags As Integer) As Long
' int zip_stat_index(struct zip *, int, int, struct zip_stat *)
' Get information about file by index.
Private Extern zip_stat_index(archive As Pointer, index As Integer, flags As Integer, sb As Zip_stat) As Integer
' struct zip_file * zip_fopen_index(struct zip *, int, int)
' Open file in zip archive for reading by index
Private Extern zip_fopen_index(archive As Pointer, index As Integer, flags As Integer) As Pointer
' zip_int64_t zip_fread(struct zip_file *, void *, zip_uint64_t)
' Read from file.
Private Extern zip_fread(zfile As Pointer, buf As Byte[], nbytes As Long) As Long
' int zip_fclose(struct zip_file *)
' Close file in zip archive.
Private Extern zip_fclose(zfile As Pointer) As Integer
' int zip_close(struct zip *)
' Close zip archive.
Private Extern zip_close(archive As Pointer) As Integer
Public Sub Main()
Dim percorsoODT As String
Dim z, zf As Pointer
Dim i, lun As Integer
Dim zs As New Zip_stat
Dim l As Long
Dim fl As File
Dim buf As New Byte[64]
percorsoODT = "/percorso/del/file.odt"
z = zip_open(percorsoODT, 0, 0)
If z = 0 Then
zip_close(z)
Error.Raise("Impossibile aprire un file '.zip' !")
Endif
For i = 0 To zip_get_num_entries(z, 0) - 1
If zip_stat_index(z, i, 0, zs) = 0 Then
zf = zip_fopen_index(z, i, 0)
If zf = 0 Then
zip_fclose(zf)
Error.Raise("Errore alla funzione 'zip_fopen_index()' !")
Endif
If String@(zs.name) == "Thumbnails/thumbnail.png" Then
fl = Open File.Dir(percorsoODT) &/ "thumbnail.png" For Create
While l < zs.size
lun = zip_fread(zf, buf, 64)
If lun < 0 Then Error.Raise("Errore nella lettura del file !")
buf.Write(fl, 0, lun)
l += lun
Wend
fl.Close
Endif
zip_fclose(zf)
Endif
Next
zip_close(z)
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 negli esempi precedenti), 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
- http://books.evc-cit.info/
- https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=office
- http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os.pdf
- http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2-part1.pdf
- http://opendocument.xml.org/
- https://developer.gnome.org/gdk-pixbuf/unstable/
- http://openbooks.sourceforge.net/books/wga/graphics-gdk-pixbuf.html