Tra le tante applicazioni che possiamo creare con .NET ci sono anche quelle per il divertimento personale, una di queste è l'acquisizioni di immagini tramite una Webcam. Per l'interfaccia con la nostra camera, o qualsiasi altro device di acquisizione, possiamo utilizzare diversi strumenti, ma il più indicato in questo caso è l'utilizzo della
DLL di Windows
avicap32.dll.
AVIcap window class (avicap32.dll) è una libreria di acquisizione che permette di interfacciarsi con dispositivi audio-visivi, senza dover preoccuparci del device. Infatti la libreria ci offre la completa l'interoperabilità con tutti i dispositivi, l'importante è che sia installata correttamente sul nostro sistema.
Il codice presente nell'articolo è VB.NET, per gli appassionati di C# troverete nei file anche la versione in C#.
Nota: L'icona del programma non è originale, ma è ricavata dal set di icone Gorilla_1.3 per KDE, distribuito in licenza GPL. Per informazioni:
http://www.kde-look.org/ ">KDE-Look
http://www.fsf.org/licenses/gpl.html ">Licenza GPL
System.Runtime.InteropServicesIl
System.Runtime.InteropServices è l'assembly che fornisce un'ampia varietà di metodi che ci permettono di lavorare con COM e servizi di chiamata al sistema operativo, infatti per poter catturare il flusso della nostra webcam dobbiamo fare una chiamata al sistema per permettere al nostro applicativo di accedere alla memoria, questa richiesta deve essere inviata in una determinata posizione, la superfice che deve utilizzare e l'applicativo. In seguito bisogna connettersi al flusso e visualizzare i dati.
Per eseguire questi passi dovremo lavorare con due DLL di sistema, l'
Avicap32.dll e la
User32.dll, e per richiamarle è necessario creare delle funzioni che faranno da puntatori alle funzioni interne delle nostre dll.
Elenco dei devicesPrima di catturare immagini e salvare come file immagine, dobbiamo assicurarci di avere una webcam e che sia correttamente installata, per evitare sgradevoli inconvenienti, il nostro applicativo prima di fare qualsiasi operazione controllerà l'esistenza di un device.
Creiamo quindi una funzione
capGetDriverDescriptionA che fa riferimento a una funzione esistente nella nostra
avicap32.dll, i parametri sono gli stessi che la vera funzione richiede.
Public Declare Function capGetDriverDescriptionA Lib "avicap32.dll" (ByVal wDriver As Short, ByVal lpszName As String, ByVal cbName As Integer, ByVal lpszVer As String, ByVal cbVer As Integer) As Boolean
Dopo di che facciamo un piccolo ciclo che elencherà tutti i device disponibili, e aggiungiamo il device a un listBox
Dim strName As String = Space(100)
Dim strVer As String = Space(100)
Dim bReturn As Boolean
Dim x As Integer = 0
'carica la lista completa nell'elenco
Do
'ricava il nome del driver e la versione
bReturn = capGetDriverDescriptionA(x, strName, 100, strVer, 100)
'se un device lo aggiunge alla lista
If bReturn Then lstDevices.Items.Add(strName.Trim)
x += 1
Loop Until bReturn = False
Ecco uno screenshot del nostro elenco, in questo caso è solamente uno, ma se avete più device di acquisizione audio-video vi verrà una lista più lunga.
Acquisizione previewOra che abbiamo selezionato il nostro device di acquisizione vogliamo creare una piccola finestra di preview, che ci farà vedere in tempo reale quello che la webcam invia al nostro sistema.
Il primo passo è creare nella nostra form un pictureBox che utilizzeremo come finestra di preview.
Dopo di che dovremo eseguire i seguenti passi:
? Indicare al sistema che deve dirigere il flusso verso il nostro pictureBox
? Collegarsi al device
? Impostare le dimensioni del flusso in base alle dimensioni del nostro controllo di preview
? Impostare il frame di cattura
? Far partire il processo di preview
Per far ciò dobbiamo utilizzare delle funzioni che faranno da puntatori a routines delle DLL avicap32 e user32, di seguito le funzioni:
Public Declare Function capCreateCaptureWindowA Lib "avicap32.dll" _
(ByVal lpszWindowName As String, ByVal dwStyle As Integer, _
ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, _
ByVal nHeight As Short, ByVal hWndParent As Integer, _
ByVal nID As Integer) As Integer
La funzione
capCreateCaptureWindowA indicherà al sistema in che finestra dovrà inviare il flusso di dati:
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, _
ByVal lParam As Object) As Integer
La funzione
SendMessage la utilizzeremo per inviare messaggi alla
avicap32, dopo aver impostato il flusso di dati:
Public Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Integer, _
ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, _
ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
La funzione
SetWindowPos verrà utilizzata per ridimensionare la finestra del flusso di dati.
Dopo aver creato le funzioni puntatore alle nostre dll di sistema, eseguiamo gli step elencati precedentemente, quindi per prima cosa indicheremo al sistema dove inviare il flusso di dati.
'Handle della finestra di preview
Dim hHwnd As Integer
'Dico alla dll di dirigere il flusso alla mia finestra di preview
hHwnd = capCreateCaptureWindowA(iDevice, WS_VISIBLE Or WS_CHILD, 0, 0, 640, _
480, objPreview.Handle.ToInt32, 0)
La variabile
hHwnd rappresenta l'
Handle della nostra finestra, che non è altro che il numero che identifica in modo univoco il nostro pictureBox, infatti tra i parametri c'è anche il valore
objPreview.Handle.ToInt32 che ritorna proprio quel numero. Oltre a questo parametro passiamo anche il parametro
iDevice che è il numero del device che vogliamo utilizzare, la dimensione del frame di cattura (640, 480), e le costanti
WS_VISIBLE e
WS_CHILD (nel progetto c'è un elenco completo delle costanti e dei loro valori)
Ora è necessario collegarsi al device e lo facciamo richiamando la funzione
SendMessage, in questo modo
SendMessage(hHwnd, WM_CAP_DRIVER_CONNECT, iDevice, 0)La funzione ci ritornerà un valore compreso tra 1 e 9 nel caso l'operazione sia andata a buon fine, e 0 se la connessione è avvenuta in modo corretto.
Ora che siamo connessi facciamo le operazioni di resize e di impostazione dei frame di acquisizione
'Imposto la preview
SendMessage(hHwnd, WM_CAP_SET_SCALE, True, 0)
'imposto il rate in millisecondi
SendMessage(hHwnd, WM_CAP_SET_PREVIEWRATE, 66, 0)
'Faccio partire la preview
SendMessage(hHwnd, WM_CAP_SET_PREVIEW, True, 0)
'Scalo la preview all'interno della dimensione del mio box immagine
SetWindowPos(hHwnd, HWND_BOTTOM, 0, 0, iWidth, iHeight, SWP_NOMOVE Or SWP_NOZORDER)
Come risultato di queste operazioni, vedremo comparire all'interno del nostro pictureBox in tempo reale le acquisizioni della nostra Webcam.
Cattura dell'immagineOra che siamo riusciti a ricavare il flusso di dati dalla nostra Webcam, salviamo un singolo frame in un file immagine bmp. Questa operazione è la più semplice di tutte perché non dovremo far altro che eseguire una chiamata alla funzione sendMessage indicando la costante per il salvataggio e il percorso del file.
'salvo il file
SendMessage(hHwnd, WM_CAP_FILE_SAVEDIB, 0&, txtFileName.Text)
Nota: L'avicap32.dll salva esclusivamente in formato bmp, per chi volesse produrre gif o jpeg dovrà crearsi una funzione di conversione personalizzata. Un esempio potrebbe essere:
'Imposto un oggetto bitmap, indicando il percorso del file da convertire
Dim objBmp As New Bitmap(BMPFullPath)
'salvo l'immagine, indicando il nuovo percorso, e il tipo di formato
objBmp.Save(strFileName, ImageFormat)
'libero le risorse
objBmp.Dispose()
Ed ecco il risultato del nostro duro lavoro.
Chiusura acquisizionePer chiudere la nostra preview, e quindi anche l'accesso esclusivo alla nostra periferica di acquisizione, dobbiamo utilizzare una funzione presente nella
user32dll, che non farà altro che chiudere la finestra di preview, in questo caso bloccherà l?accesso al nostro pictureBox, ecco la funzione:
Public Declare Function DestroyWindow Lib "user32" (ByVal hndw As Integer) As Boolean
E di seguito la chiamata, che come unico parametro vuole l'Handle della nosta finestra:
'chiudo il flusso di dati
DestroyWindow(hHwnd)
Possibili applicazioniLe possibili applicazioni sono svariate, si parte dalla semplice webcam rudimentale per il proprio sito, a un applicativo per il controllo degli accessi, oppure anche registrazione filmati, fino a un applicativo di video conferenza, oppure spiare la nuova segretaria :).