Differenze tra le versioni di "Decomprimere un file immagine jpeg per ottenerne i dati grezzi mediante le funzioni esterne del API di libjpeg"

Da Gambas-it.org - Wikipedia.
 
Riga 1: Riga 1:
 
Il formato ''JPEG'' (Joint Photographic Experts Group) è uno standard di compressione delle immagini, arrivando a ridurre le dimensioni di un file immagine anche sino al 5%.
 
Il formato ''JPEG'' (Joint Photographic Experts Group) è uno standard di compressione delle immagini, arrivando a ridurre le dimensioni di un file immagine anche sino al 5%.
  
E' possibile ottenere da un file immagine ''JPEG'' i suoi dati in formato grezzo utilizzando alcune funzioni della libreria dinamica condivisa: "''libjpeg.so.8.0.2''".
+
E' possibile ottenere da un file immagine ''JPEG'' i suoi dati in formato grezzo utilizzando alcune funzioni della libreria condivisa: "''libjpeg.so.8.2.2'' ".
 
 
  
 
Mostriamo di seguito un esempio di decodifica di un file ''JPEG'', nel quale utilizzeremo - al fine di gestire con sicurezza una parte di codice - istruzioni in linguaggio C che saranno poste in un'apposita libreria esterna da noi creata.
 
Mostriamo di seguito un esempio di decodifica di un file ''JPEG'', nel quale utilizzeremo - al fine di gestire con sicurezza una parte di codice - istruzioni in linguaggio C che saranno poste in un'apposita libreria esterna da noi creata.
 
<BR>Il progamma mostrerà anche alcune informazioni di carattere generale sul file ''JPEG'' caricato.
 
<BR>Il progamma mostrerà anche alcune informazioni di carattere generale sul file ''JPEG'' caricato.
  Library "libjpeg:8.0.2"
+
  Library "libjpeg:8.2.2"
 
   
 
   
 
  <FONT Color=gray>' ''struct jpeg_error_mgr * jpeg_std_error(struct jpeg_error_mgr * error_mgr)''
 
  <FONT Color=gray>' ''struct jpeg_error_mgr * jpeg_std_error(struct jpeg_error_mgr * error_mgr)''
Riga 54: Riga 53:
 
   
 
   
 
  <FONT Color=gray>' ''Crea la libreria esterna condivisa .so appositamente scritta:''</font>
 
  <FONT Color=gray>' ''Crea la libreria esterna condivisa .so appositamente scritta:''</font>
  Creaso()
+
  Creaso()
 
    
 
    
  percorso = "''/percorso/del/file/immagine.jpg''"
+
  percorso = "<FONT Color=gray>''/percorso/del/file/immagine.jpg''</font>"
  If Not Exist(percorso) Then Error.Raise("Percorso file immagine inesistente !")
+
  If Not Exist(percorso) Then Error.Raise("Percorso file immagine inesistente !")
  Print "File immagine JPEG:  ", Null; percorso
+
  Print "File immagine JPEG:  ", Null; percorso
 
   
 
   
 
  <FONT Color=gray>' ''Carica i dati jpeg da un file in un buffer di memoria:''</font>
 
  <FONT Color=gray>' ''Carica i dati jpeg da un file in un buffer di memoria:''</font>
  dim_jpg = Stat(percorso).Size
+
  dim_jpg = Stat(percorso).Size
  Print "Dimensione del file: "; dim_jpg; " byte"
+
  Print "Dimensione del file: "; dim_jpg; " byte"
 
   
 
   
  fl = Open percorso For Read
+
  fl = Open percorso For Read
 
   
 
   
  With buffer = New Byte[dim_jpg]
+
  With buffer = New Byte[dim_jpg]
    .Read(fl, 0, buffer.Max)
+
    .Read(fl, 0, buffer.Max)
  End With
+
  End With
 
   
 
   
  fl.close()
+
  fl.close()
 
   
 
   
  mgr = Alloc(168)
+
  mgr = Alloc(Sizeof(gb.Byte), 168)
  cinfo = Alloc(656)
+
  cinfo = Alloc(Sizeof(gb.Byte), 656)
 
    
 
    
  st = Memory cinfo For Write
+
  st = Memory cinfo For Write
  Write #st, jpeg_std_error(mgr) As Pointer
+
  Write #st, jpeg_std_error(mgr) As Pointer
 
   
 
   
  jpeg_CreateDecompress(cinfo, 80, 656)
+
  jpeg_CreateDecompress(cinfo, 80, 656)
 
    
 
    
  jpeg_mem_src(cinfo, buffer, dim_jpg)
+
  jpeg_mem_src(cinfo, buffer, dim_jpg)
 
   
 
   
  rc = jpeg_read_header(cinfo, True)
+
  rc = jpeg_read_header(cinfo, True)
  If rc <> 1 Then Error.Raise("Il file non sembra essere un normale JPEG !")
+
  If rc <> 1 Then Error.Raise("Il file non sembra essere un normale JPEG !")
 
    
 
    
 
  <FONT Color=gray>' ''Comincia la decompressione dei dati JPEG:''</font>
 
  <FONT Color=gray>' ''Comincia la decompressione dei dati JPEG:''</font>
  jpeg_start_decompress(cinfo)
+
  jpeg_start_decompress(cinfo)
 
    
 
    
  Seek #st, 48
+
  Seek #st, 48
  Read #st, width
+
  Read #st, width
  Print "Larghezza in pixel:  "; width
+
  Print "Larghezza in pixel:  "; width
  Read #st, height
+
  Read #st, height
  Print "Altezza in pixel:    "; height
+
  Print "Altezza in pixel:    "; height
  Read #st, num_comp
+
  Read #st, num_comp
  Read #st, dim_pixel
+
  Read #st, dim_pixel
  Print "Byte per pixel:      "; num_comp; " (profondità: "; dim_pixel * 8; " bit)"
+
  Print "Byte per pixel:      "; num_comp; " (profondità: "; dim_pixel * 8; " bit)"
  st.Close
+
  st.Close
 
    
 
    
  dim_bmp = width * height * dim_pixel
+
  dim_bmp = width * height * dim_pixel
  Print "Dimensione bitMap:  "; dim_bmp; " byte\n"
+
  Print "Dimensione bitMap:  "; dim_bmp; " byte\n"
 
    
 
    
 
  <FONT Color=gray>' ''La variabile "prog_riga" è il numero totale di byte che serve per memorizzare un'intera linea di scansione (riga):''</font>
 
  <FONT Color=gray>' ''La variabile "prog_riga" è il numero totale di byte che serve per memorizzare un'intera linea di scansione (riga):''</font>
  prog_riga = width * dim_pixel
+
  prog_riga = width * dim_pixel
 
   
 
   
  <FONT Color=gray>' ''Al termine della decompressione, si va a leggere tutte le linee di scansione del jpeg,''
+
  <FONT Color=gray>' ''Al termine della decompressione, si va a leggere tutte le linee di scansione del jpeg, le quali di norma risultano disposte con l'ordine RGBRGBRGB (ordine che può essere cambiato agendo sul membro "cinfo.out_color_space"):''</font>
' ''le quali di norma risultano disposte con l'ordine RGBRGBRGB (ordine che può essere cambiato agendo sul membro "cinfo.out_color_space"):''</font>
+
  bmp = Legge_linee(cinfo, dim_bmp, prog_riga)
  bmp = Legge_linee(cinfo, dim_bmp, prog_riga)
 
 
   
 
   
  jpeg_finish_decompress(cinfo)
+
  jpeg_finish_decompress(cinfo)
   
+
  jpeg_destroy_decompress(cinfo)
  jpeg_destroy_decompress(cinfo)
 
 
  <FONT Color=gray>' '''''''''''''''''''''''''''''''''''''''''''</font>
 
  <FONT Color=gray>' '''''''''''''''''''''''''''''''''''''''''''</font>
 
    
 
    
 
  <FONT Color=gray>' ''Ottenuti i dati grezzi, possiamo utilizzarli, ad esempio creando un file immagine non compresso (in questo caso di formato [[Struttura_e_gestione_del_file_di_tipo_PNM#Il_formato_PPM|PNM]]):''</font>
 
  <FONT Color=gray>' ''Ottenuti i dati grezzi, possiamo utilizzarli, ad esempio creando un file immagine non compresso (in questo caso di formato [[Struttura_e_gestione_del_file_di_tipo_PNM#Il_formato_PPM|PNM]]):''</font>
  fl = Open "/tmp/file.ppm" For Create
+
  fl = Open "/tmp/file.ppm" For Create
 
 
  st = Memory bmp For Read
 
  bb = New Byte[dim_bmp]
 
  bb.Read(st)
 
 
    
 
    
  header = "P6 " & CStr(width) & " " & CStr(height) & " 255\n"
+
  st = Memory bmp For Read
 +
  bb = New Byte[dim_bmp]
 +
  bb.Read(st)
 
    
 
    
  With buf = Byte[].FromString(header)
+
  header = "P6 " & CStr(width) & " " & CStr(height) & " 255\n"
    .Insert(bb)
 
    .Write(fl)
 
  End With
 
 
    
 
    
 +
  With buf = Byte[].FromString(header)
 +
    .Insert(bb)
 +
    .Write(fl)
 +
  End With
 
   
 
   
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
  st.Close
+
  st.Close
  fl.Close
+
  fl.Close
  Free(cinfo)
+
  Free(cinfo)
  Free(mgr)
+
  Free(mgr)
 
   
 
   
 
  '''End'''
 
  '''End'''
 
 
   
 
   
 
  '''Private''' Procedure Creaso()
 
  '''Private''' Procedure Creaso()
Riga 154: Riga 149:
 
    
 
    
 
  '''End'''
 
  '''End'''
 
  
  

Versione attuale delle 18:58, 1 dic 2021

Il formato JPEG (Joint Photographic Experts Group) è uno standard di compressione delle immagini, arrivando a ridurre le dimensioni di un file immagine anche sino al 5%.

E' possibile ottenere da un file immagine JPEG i suoi dati in formato grezzo utilizzando alcune funzioni della libreria condivisa: "libjpeg.so.8.2.2 ".

Mostriamo di seguito un esempio di decodifica di un file JPEG, nel quale utilizzeremo - al fine di gestire con sicurezza una parte di codice - istruzioni in linguaggio C che saranno poste in un'apposita libreria esterna da noi creata.
Il progamma mostrerà anche alcune informazioni di carattere generale sul file JPEG caricato.

Library "libjpeg:8.2.2"

' struct jpeg_error_mgr * jpeg_std_error(struct jpeg_error_mgr * error_mgr)
' Update the given jpeg_error_mgr object with standard error handling methods.
Private Extern jpeg_std_error(error_mgr As Pointer) As Pointer

' void jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t size)
' Allocate and initialize a JPEG decompression object of type struct jpeg_decompress_struct.
Private Extern jpeg_CreateDecompress(cinfo_ptr As Pointer, version As Integer, size As Integer)

' void jpeg_mem_src(j_decompress_ptr cinfo, unsigned char * inbuffer, unsigned long insize)
' Data source and destination managers: memory buffers.
Private Extern jpeg_mem_src(cinfo_ptr As Pointer, inbuffer As Byte[], insize As Long)

' int jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
' Read the JPEG datastream until the first SOS marker is encountered.
Private Extern jpeg_read_header(cinfo_ptr As Pointer, require_image As Boolean) As Integer

' boolean jpeg_start_decompress(j_decompress_ptr cinfo)
' Initialize state for a JPEG decompression cycle and allocate working memory.
Private Extern jpeg_start_decompress(cinfo_ptr As Pointer) As Boolean

' boolean jpeg_finish_decompress(j_decompress_ptr cinfo)
' Set the decompression state to completion.
Private Extern jpeg_finish_decompress(cinfo_ptr As Pointer) As Boolean

' void jpeg_destroy_decompress(j_decompress_ptr cinfo)
' Deallocate and release all memory associated with the decompression object.
Private Extern jpeg_destroy_decompress(cinfo_ptr As Pointer)


' unsigned char *  Legge_linee(struct jpeg_decompress_struct * cinfo, int bmp_size, int row_stride)
' Invoca la libreria externa appositamente creata per leggere le righe di pixel del file JPEG.
Private Extern Legge_linee(cinfo_ptr As Pointer, bmp_buf As Pointer, row As Integer) As Pointer In "/tmp/libadhoc"


Public Sub Main()

 Dim percorso, header As String
 Dim mgr, cinfo, bmp As Pointer
 Dim st As Stream
 Dim dim_jpg, dim_bmp As Long
 Dim fl As File
 Dim prog_riga, width, height As Integer
 Dim num_comp, dim_pixel, rc As Integer
 Dim buffer, buf, bb As Byte[]

' Crea la libreria esterna condivisa .so appositamente scritta:
 Creaso()
  
 percorso = "/percorso/del/file/immagine.jpg"
 If Not Exist(percorso) Then Error.Raise("Percorso file immagine inesistente !")
 Print "File immagine JPEG:  ", Null; percorso

' Carica i dati jpeg da un file in un buffer di memoria:
 dim_jpg = Stat(percorso).Size
 Print "Dimensione del file: "; dim_jpg; " byte"

 fl = Open percorso For Read

 With buffer = New Byte[dim_jpg]
   .Read(fl, 0, buffer.Max)
 End With

 fl.close()

 mgr = Alloc(Sizeof(gb.Byte), 168)
 cinfo = Alloc(Sizeof(gb.Byte), 656)
 
 st = Memory cinfo For Write
 Write #st, jpeg_std_error(mgr) As Pointer

 jpeg_CreateDecompress(cinfo, 80, 656)
 
 jpeg_mem_src(cinfo, buffer, dim_jpg)

 rc = jpeg_read_header(cinfo, True)
 If rc <> 1 Then Error.Raise("Il file non sembra essere un normale JPEG !")
 
' Comincia la decompressione dei dati JPEG:
 jpeg_start_decompress(cinfo)
 
 Seek #st, 48
 Read #st, width
 Print "Larghezza in pixel:  "; width
 Read #st, height
 Print "Altezza in pixel:    "; height
 Read #st, num_comp
 Read #st, dim_pixel
 Print "Byte per pixel:      "; num_comp; " (profondità: "; dim_pixel * 8; " bit)"
 st.Close
  
 dim_bmp = width * height * dim_pixel
 Print "Dimensione bitMap:   "; dim_bmp; " byte\n"
 
' La variabile "prog_riga" è il numero totale di byte che serve per memorizzare un'intera linea di scansione (riga):
 prog_riga = width * dim_pixel

' Al termine della decompressione, si va a leggere tutte le linee di scansione del jpeg, le quali di norma risultano disposte con l'ordine RGBRGBRGB (ordine che può essere cambiato agendo sul membro "cinfo.out_color_space"):
 bmp = Legge_linee(cinfo, dim_bmp, prog_riga)

 jpeg_finish_decompress(cinfo)  
 jpeg_destroy_decompress(cinfo)
' ''''''''''''''''''''''''''''''''''''''
  
' Ottenuti i dati grezzi, possiamo utilizzarli, ad esempio creando un file immagine non compresso (in questo caso di formato PNM):
 fl = Open "/tmp/file.ppm" For Create
 
 st = Memory bmp For Read
 bb = New Byte[dim_bmp]
 bb.Read(st)
 
 header = "P6 " & CStr(width) & " " & CStr(height) & " 255\n"
 
 With buf = Byte[].FromString(header)
   .Insert(bb)
   .Write(fl)
 End With

' Va in chiusura:
 st.Close
 fl.Close
 Free(cinfo)
 Free(mgr)

End

Private Procedure Creaso()
 
' Imposta il codice sorgente della parte in linguaggio C:
 File.Save("/tmp/libadhoc.c", "#include <stdio.h>\n#include <stdlib.h>\n#include <jpeglib.h>\n\n" &
           "unsigned char * bmp_buffer;\n\n" &
           "unsigned char *  Legge_linee(struct jpeg_decompress_struct * cinfo, int bmp_size, int row_stride) {\n\n" &
           "   bmp_buffer = (unsigned char*) malloc(bmp_size);\n\n" &
           "   while (cinfo->output_scanline < cinfo->output_height) {\n" &
           "     unsigned char *buffer_array[1];\n" &
           "     buffer_array[0] = bmp_buffer + (cinfo->output_scanline) * row_stride;\n" &
           "     jpeg_read_scanlines(cinfo, buffer_array, 1);\n   }\n\n" &
           "   return bmp_buffer;\n\n}")
 
' Crea la libreria esterna condivisa .so appositamente scritta per gestire la parte in linguaggio C:
 Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -shared -fPIC -ljpeg" Wait
 
End


Riferimenti