Differenze tra le versioni di "Eseguire una scansione con lo Scanner mediante le funzioni esterne di libsane"
Da Gambas-it.org - Wikipedia.
(18 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 1: | Riga 1: | ||
Con il sistema SANE è possibile gestire il proprio Scanner, come ottenere la scansione di un documento. | Con il sistema SANE è possibile gestire il proprio Scanner, come ottenere la scansione di un documento. | ||
− | Per poter usare tale libreria è necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "''libsane.so.1. | + | Per poter usare tale libreria è necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "''libsane.so.1.3.1'' ". |
Mostriamo di seguito un semplice esempio pratico di programma molto essenziale a ''riga di comando'', nel quale sono impostati, come predefiniti, i seguenti valori: | Mostriamo di seguito un semplice esempio pratico di programma molto essenziale a ''riga di comando'', nel quale sono impostati, come predefiniti, i seguenti valori: | ||
Riga 8: | Riga 8: | ||
<BR>E' possibile variare i predetti valori modificando l'assegnazione alla costante "MODUS" e alla variabile globale "RISOLUZIONE". | <BR>E' possibile variare i predetti valori modificando l'assegnazione alla costante "MODUS" e alla variabile globale "RISOLUZIONE". | ||
Private Const BUFFER As Integer = 65536 | Private Const BUFFER As Integer = 65536 | ||
− | Private Const MODUS As String = "<B>Color</b>" <FONT Color=gray>' ''Modalità possibili: <FONT Color=#B22222>Color</font> <FONT Color=gray>- <B>Gray</b> -</font> <FONT Color=Black>Lineart</font></font> | + | Private Const MODUS As String = "<B>Color</b>" <FONT Color=gray>' ''Modalità possibili: <FONT Color=#B22222>Color</font> <FONT Color=gray>- <B>Gray</b> -</font> <FONT Color=Black>Lineart</font>''</font> |
− | Private RISOLUZIONE As Integer = <B>150</b> | + | Private RISOLUZIONE As Integer = <B>150</b> <FONT Color=gray>' ''E' una possibile risoluzione in DPI della scansione''</font> |
− | Library "libsane:1. | + | Library "libsane:1.3.1" |
Public Struct SANE_Option_Descriptor | Public Struct SANE_Option_Descriptor | ||
Riga 27: | Riga 27: | ||
Public Struct SANE_Parameters | Public Struct SANE_Parameters | ||
− | sformat As | + | sformat As Integer |
− | last_frame As | + | last_frame As Integer |
bytes_per_line As Integer | bytes_per_line As Integer | ||
pixels_per_line As Integer | pixels_per_line As Integer | ||
Riga 66: | Riga 66: | ||
<FONT Color=gray>' ''SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length)'' | <FONT Color=gray>' ''SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length)'' | ||
− | ' '' | + | ' ''Reads image data from the device represented by handle h.''</font> |
Private Extern sane_read(handle As Pointer, data As Pointer, max_length As Integer, length As Pointer) As Integer | Private Extern sane_read(handle As Pointer, data As Pointer, max_length As Integer, length As Pointer) As Integer | ||
<FONT Color=gray>' ''void sane_cancel (SANE_Handle handle)'' | <FONT Color=gray>' ''void sane_cancel (SANE_Handle handle)'' | ||
− | ' '' | + | ' ''Cancels the currently pending operation of the device.''</font> |
Private Extern sane_cancel(handle As Pointer) | Private Extern sane_cancel(handle As Pointer) | ||
+ | |||
+ | <FONT Color=gray>' ''void sane_close (SANE_Handle h)'' | ||
+ | ' ''Terminates the association between the device handle passed in argument h and the device it represents.''</font> | ||
+ | Private Extern sane_close(h As Pointer) | ||
<FONT Color=gray>' ''void sane_exit (void)'' | <FONT Color=gray>' ''void sane_exit (void)'' | ||
Riga 78: | Riga 82: | ||
− | + | Public Sub Main() | |
− | Dim i, | + | Dim i, n, maxlun, lun As Integer |
− | Dim | + | Dim dev, hnd, md, buf, plun As Pointer |
Dim nom As String | Dim nom As String | ||
Dim sod As SANE_Option_Descriptor | Dim sod As SANE_Option_Descriptor | ||
Dim par As New SANE_Parameters | Dim par As New SANE_Parameters | ||
Dim fl As File | Dim fl As File | ||
− | + | ||
Write "\e[1m\e[5mRestare in attesa...\e[0m" | Write "\e[1m\e[5mRestare in attesa...\e[0m" | ||
Flush | Flush | ||
− | + | ||
i = sane_init(0, 0) | i = sane_init(0, 0) | ||
If i > 0 Then GestErrore("sane_init()") | If i > 0 Then GestErrore("sane_init()") | ||
− | + | ||
− | |||
i = sane_get_devices(VarPtr(dev), False) | i = sane_get_devices(VarPtr(dev), False) | ||
If i > 0 Then GestErrore("sane_get_devices()") | If i > 0 Then GestErrore("sane_get_devices()") | ||
− | + | ||
− | + | While Pointer@(dev + i) > 0 | |
+ | nom = String@(Pointer@(Pointer@(dev + i))) | ||
+ | i += 8 | ||
+ | Wend | ||
+ | |||
Write "\rDispositivo: \e[31m" & nom | Write "\rDispositivo: \e[31m" & nom | ||
− | + | ||
i = sane_open(nom, VarPtr(hnd)) | i = sane_open(nom, VarPtr(hnd)) | ||
− | If i > 0 Then GestErrore("sane_open()") | + | If i > 0 Then |
− | + | GestErrore("sane_open()") | |
− | i = sane_control_option(hnd, 0, SANE_ACTION_GET_VALUE, VarPtr( | + | saneUscita(hnd) |
− | If i > 0 Then GestErrore("sane_control_option()") | + | Endif |
− | + | ||
− | For | + | i = sane_control_option(hnd, 0, SANE_ACTION_GET_VALUE, VarPtr(n), 0) |
− | sod = sane_get_option_descriptor(hnd, | + | If i > 0 Then |
+ | GestErrore("sane_control_option()") | ||
+ | saneUscita(hnd) | ||
+ | Endif | ||
+ | |||
+ | Print "\n\n\e[0mPossibili opzioni:\e[32m" | ||
+ | For i = 0 To n - 1 | ||
+ | sod = sane_get_option_descriptor(hnd, i) | ||
If IsNull(String@(sod.name)) Then Continue | If IsNull(String@(sod.name)) Then Continue | ||
+ | Print " " & String@(sod.name) | ||
Select Case String@(sod.name) | Select Case String@(sod.name) | ||
Case "mode" <FONT Color=gray>' '' Color - Gray - Lineart''</font> | Case "mode" <FONT Color=gray>' '' Color - Gray - Lineart''</font> | ||
md = Alloc(MODUS) | md = Alloc(MODUS) | ||
− | sane_control_option(hnd, | + | sane_control_option(hnd, i, SANE_ACTION_SET_VALUE, md, 0) |
Case "resolution" | Case "resolution" | ||
− | sane_control_option(hnd, | + | sane_control_option(hnd, i, SANE_ACTION_SET_VALUE, VarPtr(RISOLUZIONE), 0) |
End Select | End Select | ||
Next | Next | ||
i = sane_get_parameters(hnd, par) | i = sane_get_parameters(hnd, par) | ||
− | If i > 0 Then GestErrore("sane_get_parameters()") | + | If i > 0 Then |
+ | GestErrore("sane_get_parameters()") | ||
+ | saneUscita(hnd) | ||
+ | Endif | ||
+ | |||
With par | With par | ||
− | Print "\n\e[ | + | Dim px As Byte = .bytes_per_line / .pixels_per_line |
− | Print " | + | Dim rgb As String = " byte)" |
− | Print " | + | If px == 3 Then rgb = " byte = RGB)" |
− | Print " | + | Print "\n\e[0mColonne: "; .pixels_per_line; " (1 colonna = 1 pixel = "; px; RGB |
− | Print "Modalità: | + | Print "Righe: "; .lines |
− | Print "Risoluzione: | + | Print "Byte per riga: "; .bytes_per_line; " (colonne x "; px; Left(rgb, 5); ")" |
+ | Print "Bit per campione: "; .depth | ||
+ | Print "Modalità: "; MODUS | ||
+ | Print "Risoluzione: "; RISOLUZIONE; " dpi\n" | ||
End With | End With | ||
i = sane_start(hnd) | i = sane_start(hnd) | ||
− | If i > 0 Then GestErrore("sane_start()") | + | If i > 0 Then |
+ | GestErrore(hnd, "sane_start()") | ||
+ | saneUscita(hnd) | ||
+ | Endif | ||
buf = Alloc(SizeOf(gb.Byte), BUFFER) | buf = Alloc(SizeOf(gb.Byte), BUFFER) | ||
plun = Alloc(SizeOf(gb.Integer), 1) | plun = Alloc(SizeOf(gb.Integer), 1) | ||
maxlun = BUFFER | maxlun = BUFFER | ||
− | + | ||
− | + | fl = Open "/tmp/imm" For Create | |
− | fl = Open "/tmp/imm" For | + | |
− | |||
Repeat | Repeat | ||
i = sane_read(hnd, buf, maxlun, plun) | i = sane_read(hnd, buf, maxlun, plun) | ||
Riga 144: | Riga 168: | ||
Case 1 | Case 1 | ||
GestErrore("sane_read()") | GestErrore("sane_read()") | ||
+ | saneUscita(hnd) | ||
Case 3 To 4 | Case 3 To 4 | ||
GestErrore("sane_read()") | GestErrore("sane_read()") | ||
+ | saneUscita(hnd) | ||
Case 6 To 11 | Case 6 To 11 | ||
GestErrore("sane_read()") | GestErrore("sane_read()") | ||
+ | saneUscita(hnd) | ||
End Select | End Select | ||
lun = Int@(plun) | lun = Int@(plun) | ||
Write #fl, buf, lun | Write #fl, buf, lun | ||
Until lun = 0 | Until lun = 0 | ||
− | + | ||
− | |||
− | |||
MostraImmagine(par) | MostraImmagine(par) | ||
Riga 162: | Riga 187: | ||
Free(plun) | Free(plun) | ||
Free(buf) | Free(buf) | ||
− | + | saneUscita(hnd) | |
− | saneUscita() | + | |
+ | End | ||
+ | |||
− | + | Private Procedure GestErrore(fnz As String) | |
− | + | ||
− | |||
− | |||
− | |||
Error.Raise("Errore alla funzione: " & fnz) | Error.Raise("Errore alla funzione: " & fnz) | ||
+ | |||
+ | End | ||
+ | |||
− | + | Private Procedure saneUscita(handle As Pointer) | |
− | + | ||
− | + | sane_cancel(handle) | |
− | + | sane_close(handle) | |
sane_exit() | sane_exit() | ||
− | |||
− | |||
− | + | End | |
− | + | ||
+ | |||
+ | Private Procedure MostraImmagine(prmt As SANE_Parameters) | ||
+ | |||
Dim s, finale, mg As String | Dim s, finale, mg As String | ||
− | Dim pro, p4, | + | Dim pro, p4, colonne, righe As Integer |
− | Dim | + | Dim bBN As Byte |
− | pro = prmt.lines * prmt. | + | pro = prmt.lines * prmt.bytes_per_line |
s = File.Load("/tmp/imm") | s = File.Load("/tmp/imm") | ||
− | Print "Dati grezzi: | + | Print "Dati grezzi: "; Len(s); " byte (Colonne x Righe x 3 byte_RGB)" |
− | + | ||
− | + | colonne = prmt.pixels_per_line | |
− | + | righe = prmt.lines | |
− | + | ||
− | |||
Select Case MODUS | Select Case MODUS | ||
Case "Color" | Case "Color" | ||
Riga 217: | Riga 244: | ||
<FONT Color=gray>' ''Se il numero dei dati grezzi è maggiore di (Colonne x Righe) / 8, allora colma la differenza:''</font> | <FONT Color=gray>' ''Se il numero dei dati grezzi è maggiore di (Colonne x Righe) / 8, allora colma la differenza:''</font> | ||
If Len(s) > (pro / 8) Then | If Len(s) > (pro / 8) Then | ||
− | For | + | For bBN = 1 To 8 |
− | If (Len(s) * 8) Mod (prmt.lines + | + | If (Len(s) * 8) Mod (prmt.lines + bBN) == 0 |
− | + | colonne = prmt.lines + bBN | |
− | + | righe = Len(s) * 8 / prmt.lines | |
Endif | Endif | ||
Next | Next | ||
Riga 236: | Riga 263: | ||
' '' i dati grezzi dell'immagine scansita;'' | ' '' i dati grezzi dell'immagine scansita;'' | ||
' '' le informazioni e commento finale:''</font> | ' '' le informazioni e commento finale:''</font> | ||
− | finale = mg & | + | finale = mg & CStr(colonne) & Chr(&20) & CStr(righe) & " 255" & Chr(10) & s & Chr(10) & |
"# file creato da " & Application.Name & " - " & CStr(Now) | "# file creato da " & Application.Name & " - " & CStr(Now) | ||
<FONT Color=gray>' ''...e lo salva:''</font> | <FONT Color=gray>' ''...e lo salva:''</font> | ||
File.Save("/tmp/scansione.pnm", finale) | File.Save("/tmp/scansione.pnm", finale) | ||
− | + | End | |
Versione attuale delle 12:52, 8 giu 2024
Con il sistema SANE è possibile gestire il proprio Scanner, come ottenere la scansione di un documento.
Per poter usare tale libreria è necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "libsane.so.1.3.1 ".
Mostriamo di seguito un semplice esempio pratico di programma molto essenziale a riga di comando, nel quale sono impostati, come predefiniti, i seguenti valori:
- modalità: "Color" (le modalità possibili sono: "Color": scansione a colori; "Gray": scansione in scala di grigi; "Lineart": scansione in bianco e nero)
- risoluzione: 150 dpi
E' possibile variare i predetti valori modificando l'assegnazione alla costante "MODUS" e alla variabile globale "RISOLUZIONE".
Private Const BUFFER As Integer = 65536 Private Const MODUS As String = "Color" ' Modalità possibili: Color - Gray - Lineart Private RISOLUZIONE As Integer = 150 ' E' una possibile risoluzione in DPI della scansione Library "libsane:1.3.1" Public Struct SANE_Option_Descriptor name As Pointer title As Pointer desc As Pointer type As Integer unit As Integer size As Integer cap As Integer constraint_type As Integer union As Pointer End Struct Public Struct SANE_Parameters sformat As Integer last_frame As Integer bytes_per_line As Integer pixels_per_line As Integer lines As Integer depth As Integer End Struct Private Enum SANE_ACTION_GET_VALUE = 0, SANE_ACTION_SET_VALUE, SANE_ACTION_SET_AUTO ' SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) ' This function must be called before any other SANE function can be called. Private Extern sane_init(version_code As Pointer, authorize As Pointer) As Integer ' SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) ' To query the list of devices that are available. Private Extern sane_get_devices(device_list As Pointer, local_only As Boolean) As Integer ' SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) ' To establish a connection to a particular device. Private Extern sane_open(devicename As String, handle As Pointer) As Integer ' SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) ' To set or inquire the current value of option number n of the device represented by handle h. Private Extern sane_control_option(handle As Pointer, option As Integer, action As Integer, value As Pointer, info As Pointer) As Integer ' const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) ' To access option descriptors. Private Extern sane_get_option_descriptor(handle As Pointer, option As Integer) As Pointer ' SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) ' To obtain the current scan parameters. Private Extern sane_get_parameters(handle As Pointer, params As SANE_Parameters) As Integer ' SANE_Status sane_start (SANE_Handle handle) ' Initiates aquisition of an image from the device represented by handle h. Private Extern sane_start(handle As Pointer) As Integer ' SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) ' Reads image data from the device represented by handle h. Private Extern sane_read(handle As Pointer, data As Pointer, max_length As Integer, length As Pointer) As Integer ' void sane_cancel (SANE_Handle handle) ' Cancels the currently pending operation of the device. Private Extern sane_cancel(handle As Pointer) ' void sane_close (SANE_Handle h) ' Terminates the association between the device handle passed in argument h and the device it represents. Private Extern sane_close(h As Pointer) ' void sane_exit (void) ' To terminate use of a backend. Private Extern sane_exit() Public Sub Main() Dim i, n, maxlun, lun As Integer Dim dev, hnd, md, buf, plun As Pointer Dim nom As String Dim sod As SANE_Option_Descriptor Dim par As New SANE_Parameters Dim fl As File Write "\e[1m\e[5mRestare in attesa...\e[0m" Flush i = sane_init(0, 0) If i > 0 Then GestErrore("sane_init()") i = sane_get_devices(VarPtr(dev), False) If i > 0 Then GestErrore("sane_get_devices()") While Pointer@(dev + i) > 0 nom = String@(Pointer@(Pointer@(dev + i))) i += 8 Wend Write "\rDispositivo: \e[31m" & nom i = sane_open(nom, VarPtr(hnd)) If i > 0 Then GestErrore("sane_open()") saneUscita(hnd) Endif i = sane_control_option(hnd, 0, SANE_ACTION_GET_VALUE, VarPtr(n), 0) If i > 0 Then GestErrore("sane_control_option()") saneUscita(hnd) Endif Print "\n\n\e[0mPossibili opzioni:\e[32m" For i = 0 To n - 1 sod = sane_get_option_descriptor(hnd, i) If IsNull(String@(sod.name)) Then Continue Print " " & String@(sod.name) Select Case String@(sod.name) Case "mode" ' Color - Gray - Lineart md = Alloc(MODUS) sane_control_option(hnd, i, SANE_ACTION_SET_VALUE, md, 0) Case "resolution" sane_control_option(hnd, i, SANE_ACTION_SET_VALUE, VarPtr(RISOLUZIONE), 0) End Select Next i = sane_get_parameters(hnd, par) If i > 0 Then GestErrore("sane_get_parameters()") saneUscita(hnd) Endif With par Dim px As Byte = .bytes_per_line / .pixels_per_line Dim rgb As String = " byte)" If px == 3 Then rgb = " byte = RGB)" Print "\n\e[0mColonne: "; .pixels_per_line; " (1 colonna = 1 pixel = "; px; RGB Print "Righe: "; .lines Print "Byte per riga: "; .bytes_per_line; " (colonne x "; px; Left(rgb, 5); ")" Print "Bit per campione: "; .depth Print "Modalità: "; MODUS Print "Risoluzione: "; RISOLUZIONE; " dpi\n" End With i = sane_start(hnd) If i > 0 Then GestErrore(hnd, "sane_start()") saneUscita(hnd) Endif buf = Alloc(SizeOf(gb.Byte), BUFFER) plun = Alloc(SizeOf(gb.Integer), 1) maxlun = BUFFER fl = Open "/tmp/imm" For Create Repeat i = sane_read(hnd, buf, maxlun, plun) Select Case i Case 1 GestErrore("sane_read()") saneUscita(hnd) Case 3 To 4 GestErrore("sane_read()") saneUscita(hnd) Case 6 To 11 GestErrore("sane_read()") saneUscita(hnd) End Select lun = Int@(plun) Write #fl, buf, lun Until lun = 0 MostraImmagine(par) ' Libera la memoria precedentemente allocata: fl.Close Free(md) Free(plun) Free(buf) saneUscita(hnd) End Private Procedure GestErrore(fnz As String) Error.Raise("Errore alla funzione: " & fnz) End Private Procedure saneUscita(handle As Pointer) sane_cancel(handle) sane_close(handle) sane_exit() End Private Procedure MostraImmagine(prmt As SANE_Parameters) Dim s, finale, mg As String Dim pro, p4, colonne, righe As Integer Dim bBN As Byte pro = prmt.lines * prmt.bytes_per_line s = File.Load("/tmp/imm") Print "Dati grezzi: "; Len(s); " byte (Colonne x Righe x 3 byte_RGB)" colonne = prmt.pixels_per_line righe = prmt.lines Select Case MODUS Case "Color" mg = "P6 " ' Se il numero dei dati grezzi è inferiore a (Colonne x Righe) x 3, allora colma la differenza: If Len(s) < ((pro / 8) * 3) Then s = s & String(((pro) * 3) - Len(s), Chr(255)) ' Se invece il numero dei dati grezzi è maggiore di (Colonne x Righe) x 3, allora colma la differenza, ma tagliando i dati grezzi dalla fine: If Len(s) > ((pro) * 3) Then s = Left(s, pro * 3) Case "Gray" mg = "P5 " ' Se il numero dei dati grezzi è inferiore a Colonne x Righe, allora colma la differenza: If Len(s) < (pro) Then s = s & String((pro) - Len(s), Chr(255)) ' Se invece il numero dei dati grezzi è maggiore di Colonne x Righe, allora colma la differenza, ma tagliando i dati grezzi dalla fine: If Len(s) > (pro) Then s = Left(s, pro) Case "Lineart" mg = "P4 " ' Se il numero dei dati grezzi è inferiore a (Colonne x Righe) / 8, allora colma la differenza: If Len(s) < (pro / 8) Then p4 = pro \ 8 s = s & String(p4 - Len(s), Chr(255)) Endif ' Se il numero dei dati grezzi è maggiore di (Colonne x Righe) / 8, allora colma la differenza: If Len(s) > (pro / 8) Then For bBN = 1 To 8 If (Len(s) * 8) Mod (prmt.lines + bBN) == 0 colonne = prmt.lines + bBN righe = Len(s) * 8 / prmt.lines Endif Next Endif End Select ' Quindi, crea l'intero file .PNM finale, costituito da: ' l'header: ' - numero Magico + spazio; ' - numero colonne; ' - spazio; ' - numero righe; ' - spazio; ' - profondità colore; ' - chiusura con "salto di riga"; ' i dati grezzi dell'immagine scansita; ' le informazioni e commento finale: finale = mg & CStr(colonne) & Chr(&20) & CStr(righe) & " 255" & Chr(10) & s & Chr(10) & "# file creato da " & Application.Name & " - " & CStr(Now) ' ...e lo salva: File.Save("/tmp/scansione.pnm", finale) End