.Net - scansione dei documenti tramite Scanner - seconda parte

Seconda ed ultima parte dell'articolo sulla gestione dello scanner in .Net con i linguaggi di programmazione VB.Net e C#.

il
Sviluppatore Microsoft .Net, Collaboratore di IProgrammatori

Riprendiamo l’articolo riguardante la scansione dei documenti tramite la tecnologia .Net con i linguaggi di programmazione VB.Net e C# qui https://www.iprogrammatori.it/articoli/microsoft-net-framework/art_net-effettuare-la-scansione-dei-documenti-tramite-scanner-prima-parte_1643.aspx la prima parte.

In questa seconda ed ultima parte, vedremo come effettuare la scansione, salvare il file e visualizzare il risultato nella form e precisamente nel controllo picturebox.
Si apre il progetto creato in precedenza, e dobbiamo scrivere le funzione per impostare il tipo di scansione e soprattutto il settaggio delle dimensione della nostra immagine.


Stesura del codice

Passiamo in visualizzazione codice, e nella classe della form, scriviamo la funzione con il quale andremo ad impostare alcuni parametri con tanto di valore per la gestione della scansione.
Le proprietà permetteranno all’oggetto per la scansione di effettuare la scansione in base alle informazioni che gli forniamo, come la grandezza, il formato, ed altro ancora per l’area in cui dovrà rilevare il foglio messo sopra allo scanner.
Questa funzione avrà il compito di impostare un valore a determinate proprietà e sarà richiamata da un’altra funzione.
Qui di seguito la dichiarazione per entrambi i linguaggi.

VB.Net
Private Shared Sub SetWIAProperty(ByVal properties As IProperties, ByVal propName As Object, ByVal propValue As Object)
Dim prop As [Property] = properties.Item(propName)
prop.let_Value(propValue)
End Sub
C#
private static void SetWIAProperty(IProperties properties, object propName, object propValue)
{
Property prop = properties.get_Item(ref propName);
prop.set_Value(ref propValue);
}

Ora dovremmo creare la funzione, che richiama quella precedente per impostare i vari parametri di scansione.

La funzione che andremo a scrivere permetterà di impostare la risoluzione, la larghezza ed altre utili informazioni per gestire al meglio lo scanner.
La funzione avrà dei parametri, tra questi l’oggetto di tipo “IItem” che è l’interfaccia per gestire lo scanner con il quale effettueremo la scansione.
Qui di seguito si riporta la creazione della funzione, con il quale andremo ad impostare i vari parametri.
La dichiarazione delle suddette operazioni per entrambi i linguaggi di programmazione.

VB.Net
Private Shared Sub AdjustScannerSettings(ByVal scannnerItem As IItem, ByVal scanResolutionDPI As Integer, ByVal scanStartLeftPixel As Integer, ByVal scanStartTopPixel As Integer, ByVal scanWidthPixels As Integer, ByVal scanHeightPixels As Integer, ByVal brightnessPercents As Integer, ByVal contrastPercents As Integer, ByVal colorMode As Integer)
Const WIA_SCAN_COLOR_MODE As String = "6146"
Const WIA_HORIZONTAL_SCAN_RESOLUTION_DPI As String = "6147"
Const WIA_VERTICAL_SCAN_RESOLUTION_DPI As String = "6148"
Const WIA_HORIZONTAL_SCAN_START_PIXEL As String = "6149"
Const WIA_VERTICAL_SCAN_START_PIXEL As String = "6150"
Const WIA_HORIZONTAL_SCAN_SIZE_PIXELS As String = "6151"
Const WIA_VERTICAL_SCAN_SIZE_PIXELS As String = "6152"
Const WIA_SCAN_BRIGHTNESS_PERCENTS As String = "6154"
Const WIA_SCAN_CONTRAST_PERCENTS As String = "6155"
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_RESOLUTION_DPI, scanResolutionDPI)
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_RESOLUTION_DPI, scanResolutionDPI)
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_START_PIXEL, scanStartLeftPixel)
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_START_PIXEL, scanStartTopPixel)
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_SIZE_PIXELS, scanWidthPixels)
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_SIZE_PIXELS, scanHeightPixels)
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BRIGHTNESS_PERCENTS, brightnessPercents)
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_CONTRAST_PERCENTS, contrastPercents)
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_COLOR_MODE, colorMode)
End Sub
C#
private static void AdjustScannerSettings(IItem scannnerItem, int scanResolutionDPI, int scanStartLeftPixel, int scanStartTopPixel, int scanWidthPixels, int scanHeightPixels, int brightnessPercents, int contrastPercents, int colorMode) { const string WIA_SCAN_COLOR_MODE = "6146"; const string WIA_HORIZONTAL_SCAN_RESOLUTION_DPI = "6147"; const string WIA_VERTICAL_SCAN_RESOLUTION_DPI = "6148"; const string WIA_HORIZONTAL_SCAN_START_PIXEL = "6149"; const string WIA_VERTICAL_SCAN_START_PIXEL = "6150"; const string WIA_HORIZONTAL_SCAN_SIZE_PIXELS = "6151"; const string WIA_VERTICAL_SCAN_SIZE_PIXELS = "6152"; const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154"; const string WIA_SCAN_CONTRAST_PERCENTS = "6155"; SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_RESOLUTION_DPI, scanResolutionDPI); SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_RESOLUTION_DPI, scanResolutionDPI); SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_START_PIXEL, scanStartLeftPixel); SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_START_PIXEL, scanStartTopPixel); SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_SIZE_PIXELS, scanWidthPixels); SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_SIZE_PIXELS, scanHeightPixels); SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BRIGHTNESS_PERCENTS, brightnessPercents); SetWIAProperty(scannnerItem.Properties, WIA_SCAN_CONTRAST_PERCENTS, contrastPercents); SetWIAProperty(scannnerItem.Properties, WIA_SCAN_COLOR_MODE, colorMode); }

Terminata la creazione di queste due funzioni, che hanno l’obiettivo di impostare le informazioni per effettuare una corretta scansione del documento, non resta che creare una funzione, che sarà richiamato dal altra funzione che poi sarà quella del pulsante di scansione, per effettuare la vera scansione.
Questa funzione, avrà un oggetto di tipo “Wia.CommonDialog” con il quale andremo ad effettuare l’avvio della scansione.
Mentre l’oggetto di tipo “DeviceInfo” tramite il metodo “Connect” sarà quello di gestire il dispositivo hardware, infatti passando alle precedenti funzioni la proprietà “Item” si andrà ad impostare la modalità con il quale faremo la scansione.
Tramite il metodo “ShowTransfer” della classe Wia.CommonDialog” verrà avviata la scansione, passando come parametro, l’oggetto Item, il formato di scansione in base al valore selezionato nella casella combinata, ed il risultato della scansione sarà un oggetto di tipo “ImageFile”.
Con il quale salveremo i file sul nostro pc per poi farlo vedere nel controllo Picturebox.

Nella gestione delle eccezioni in base al codice di errore andremo a visualizzare un messaggio personalizzato.
Qui di seguito la dichiarazione delle suddette operazioni.

VB.Net
Public Function ScansionaFormato(ByVal device As DeviceInfo, ByVal formato As String) As ImageFile
Dim deviceScanner = device.Connect()
Dim dlg As WIA.CommonDialog = New WIA.CommonDialog()
Dim item = deviceScanner.Items(1)
Dim resolution As Integer = 100
Dim width_pixel As Integer = 1250
Dim height_pixel As Integer = 1700
Dim color_mode As Integer = 0
Try
AdjustScannerSettings(item, resolution, 10, 10, 600, 600, 100, 100, color_mode)
Dim scanRisultato As Object = Nothing
If formato.ToLower() = "jpg" Then
scanRisultato = dlg.ShowTransfer(item, WIA.FormatID.wiaFormatJPEG, True)
ElseIf formato.ToLower() = "png" Then
scanRisultato = dlg.ShowTransfer(item, WIA.FormatID.wiaFormatPNG, True)
Else
scanRisultato = dlg.ShowTransfer(item, WIA.FormatID.wiaFormatTIFF, True)
End If
If scanRisultato IsNot Nothing Then
Dim imageFile = CType(scanRisultato, ImageFile)
Return imageFile
End If
Catch ex As COMException
Dim errorCode As UInteger = CUInt(ex.ErrorCode)
If errorCode = &H80210006 Then
MessageBox.Show("Scanner non pronto oppure impegnato")
ElseIf errorCode = &H80210064 Then
MessageBox.Show("Annullata la scansione")
Else
MessageBox.Show("Errore: " & ex.Message)
End If
End Try
Return New ImageFile()
End Function
C#
public ImageFile ScansionaFormato(DeviceInfo device, string formato) { //Mi connetto al dispositivo var deviceScanner = device.Connect(); int resolution = 100; int width_pixel = 1250; int height_pixel = 1700; int color_mode = 0; //Visualizzo la dialogo WIA.CommonDialog dlg = new WIA.CommonDialog(); var item = deviceScanner.Items[1]; try { //Imposto le dimensioni di scansione AdjustScannerSettings(item, resolution, 10, 10, 600, 600, 100,100, color_mode); object scanRisultato = null; if (formato.ToLower() == "jpg") { scanRisultato = dlg.ShowTransfer(item, WIA.FormatID.wiaFormatJPEG, true); } else if (formato.ToLower() == "png") { scanRisultato = dlg.ShowTransfer(item, WIA.FormatID.wiaFormatPNG, true); } else { scanRisultato = dlg.ShowTransfer(item, WIA.FormatID.wiaFormatTIFF, true); } if (scanRisultato != null) { var imageFile = (ImageFile)scanRisultato; //ritorno oggetto immagine return imageFile; } } catch (COMException ex) { uint errorCode = (uint)ex.ErrorCode; if (errorCode == 0x80210006) { MessageBox.Show("Scanner non pronto oppure impegnato"); } else if (errorCode == 0x80210064) { MessageBox.Show("Annullata la scansione"); } else { MessageBox.Show("Errore: " + ex.Message); } } return new ImageFile(); }

Ora non ci resta creare la funzione che sarà richiamato dal pulsante di scansione, questa funzione richiama la precedente funzione, passando come parametro, lo scanner selezionato, il formato del file immagine, ed altre informazioni utili, inoltre verrà salvata l’immagine e visualizzata in anteprima.
Qui di seguito la dichiarazione del codice.

VB.Net
Private Function Scansiona() As Boolean
Dim risultatoScansione As Boolean = False
Try
Dim deviceManager = New DeviceManager()
Dim device As DeviceInfo = Nothing
If listScanner.SelectedIndex < 0 Then
MessageBox.Show("Selezionare un dispositivo valido", "Esempio Scanner", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return False
End If
For i As Integer = 1 To deviceManager.DeviceInfos.Count
If deviceManager.DeviceInfos(i).Type <> WiaDeviceType.ScannerDeviceType Then
Continue For
End If
If deviceManager.DeviceInfos(i).Properties("Name").Value.ToString() = listScanner.SelectedItem.ToString() Then
device = deviceManager.DeviceInfos(i)
Exit For
End If
Next
If device Is Nothing Then
MessageBox.Show("Selezionare un dispositivo valido", "Esempio Scanner", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return False
End If
Dim ImmagineScansionata As ImageFile = New ImageFile()
Dim EstensioneImmagine As String = cmbFormato.SelectedItem.ToString()
ImmagineScansionata = ScansionaFormato(device, EstensioneImmagine)
risultatoScansione = True
Dim Percorso = Path.Combine("D:\Test." & EstensioneImmagine)
If File.Exists(Percorso) Then
File.Delete(Percorso)
End If
ImmagineScansionata.SaveFile(Percorso)
pictureBox1.Image = New System.Drawing.Bitmap(Percorso)
Return risultatoScansione
Catch ex As System.Exception
MessageBox.Show(ex.Message)
Return risultatoScansione
End Try
End Function
C#
private bool Scansiona()
{
bool risultatoScansione = false;
try
{
var deviceManager = new DeviceManager();
DeviceInfo device = null;
if (listScanner.SelectedIndex < 0)
{
MessageBox.Show("Selezionare un dispositivo valido", "Esempio Scanner", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
{
if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
{
continue;
}
if (deviceManager.DeviceInfos[i].Properties["Name"].get_Value().ToString() == listScanner.SelectedItem.ToString())
{
device = deviceManager.DeviceInfos[i];
break;
}
}
if (device == null)
{
MessageBox.Show("Selezionare un dispositivo valido", "Esempio Scanner", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
ImageFile ImmagineScansionata = new ImageFile();
string EstensioneImmagine = cmbFormato.SelectedItem.ToString();
ImmagineScansionata =    ScansionaFormato(device, EstensioneImmagine);
risultatoScansione = true;
var Percorso = Path.Combine("D:\\Test." + EstensioneImmagine);
if (File.Exists(Percorso))
{
File.Delete(Percorso);
}
ImmagineScansionata.SaveFile(Percorso);
pictureBox1.Image = new Bitmap(Percorso);
return risultatoScansione;
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
return risultatoScansione;
}
}

Ora dobbiamo richiamare questa funzione dall’evento click del pulsante, passiamo in visualizzazione grafica del nostro progetto, e nella form, facciamo doppio click sul pulsante, in modo che passiamo in modalità codice dell’evento click.
Nell’evento click, verrà richiamata la funzione illustra in precedenza.

VB.Net
Private Sub BtnScansiona_Click(sender As Object, e As EventArgs) Handles BtnScansiona.Click
If String.IsNullOrEmpty(txtPercorsoNomeFile.Text) Then
MessageBox.Show("Inserire il percorso e nome file", "Scanner", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return
End If
If Scansiona() = True Then
MessageBox.Show("Scansione effettuata con successo.", "Scanner", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
C#
private void BtnScansiona_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(txtPercorsoNomeFile.Text))
{
MessageBox.Show("Inserire il percorso e nome file", "Scanner", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (Scansiona() == true)
MessageBox.Show("Scansione avvenuta con successo.", "Scanner", MessageBoxButtons.OK, MessageBoxIcon.Information);
}


Manca solo un piccolo dettaglio, quello di abbinare al click del pulsante per il salvataggio del file, il percorso e nome del file.
Qui l’evento click del pulsante, per visualizzare la finestra di dialogo per selezionare la cartella e dare il nome del file immagine relativo alla scansione

VB.Net
Private Sub btnSalva_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim DlgpercorsoNomeFile As SaveFileDialog = New SaveFileDialog()
If DlgpercorsoNomeFile.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
txtPercorsoNomeFile.Text = DlgpercorsoNomeFile.FileName
End If
End Sub
C#
private void btnSalva_Click(object sender, EventArgs e)
{
SaveFileDialog DlgpercorsoNomeFile = new SaveFileDialog();
if (DlgpercorsoNomeFile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtPercorsoNomeFile.Text = DlgpercorsoNomeFile.FileName;
}
}

Conclusioni

Ora non ci resta che testare il nostro applicativo, collegando al nostro pc uno scanner, ed effettuare la scansione, noteremo come al termine verrà mostrato il file relativo alla scansione.
L’articolo ha voluto fornire al lettore, le conoscenze per dotare i propri applicazioni, Windows Application, più che altro, ma anche Web application, la gestione dello scanner.
Strumento che può tornare molto utile nei progetto nel quale si devono gestire documenti, e quindi applicazioni di gestione documentale. -
Naturalmente può essere anche un punto di partenza per creare programma dedicati alla scansione, quindi non nei propri progetti, ma un vero software.