14 de febrero de 2015

Controlando dispositivos TWAIN desde VFP

Artículo original: Controlling TWAIN devices from within VFP 
http://www.ml-consult.co.uk/foxst-29.htm
Autor: Mike Lewis 
Traducido por: Carlos A. Miranda



¿Necesita manejar un escaner o una cámara de video desde su aplicación?. Aquí le decimos como hacerlo.

Recientemente escribimos una aplicación FoxPro que manejaba el registro de delegados atendiendo a una conferencia internacional. el Cliente quería que la aplicación fotografiara a cada delegado que llegara, y también guardar la imagen digitalizada de las tarjetas de negocios de los delegados. Debido al gran número de delegados involucrados, la fotografía y el proceso de digitalización tenia que ser los más libre de problemas y fácil posible. Era particularmente importante para el operador ser capaz de controlar la cámara y el escanner mientras estaba sentado en su PC.

En este artículo, nosotros le diremos como desarrollamos este proyecto. La estrategia que adoptamos es razonablemente genérica y no es específica de ningún escanner en particular. Usted no debería tener dificultades en aplicar nuestras técnicas en sus propias aplicaciones si lo desea.

Primer paso: escoger el equipo


Para la fotografía, nosotros desacartamos una cámara digital estandar, principalmente porque no encontrabamos un método de transferir las imágenes sin utilizar las manos hacia nuestra aplicación. En vez de eso, nosotros escogimos una Philips ToUcam web camera (izquierda). Este tipo de dispositivo es utilizado usualmente para video conferencias y como una cámara on-line web cam, pero también puede capturar un solo frame. Este tiene la ventaja de ser un dispositivo TWAIN-compliant y puede ser controlado enteramente desde la PC.
El escanner que nosotros escogimos fue un Targus Mini Business Card Scanner (izquierda). Como su nombre sugiere, este está diseñado especificmente para digitalizar tarjetas de negocios. Como la cámara, esta es TWAIN-compliant también.

A pesar de que nosotros estamos contentos de recomendar ambos dispositivos, la mayoría de los modelos de cámara web o escanner habrían servido para nuestros propositos. El código que nosotros mostraremos en este artículo es capaz de capturar imagenes desde cualquier dispositivo compatible con TWAIN.




 ... Y el software

Hay muchos productos de sofware disponibles que le permiten a uste controlar un dispositivo TWAIN de forma programatica. El que nosotros optamos fue EZTWAIN, de Dosadi. Nos gustó este producto por las siguientes razones:
  • Fácil de programar. Nosotros teníamos media docena o algo así de funciones que preocuparnos de llamar.
  • Fácil de distribuir. Porque es un DLL que a diferencia de un control ActiveX, no tenemos que preocuparnos de registrarlo en el sistema del usuario.
  • Bajo costo. Dependiendo de las necesidades y del tipo de aplicaciones que escribas, el precio varia de nada a alrededor de US$200.
  • Excelente soporte del autor del producto, Spike McLarty.
Declarando sus función

El EZTWAIN DLL tiene alrededor de 70 funciones, pero para muchas aplicaciones usted nunca utilizará más de 7 u ocho de ellas. Aquí estan las declaraciones de las funciones más comunes:

DECLARE INTEGER TWAIN_SelectImageSource ;
  IN Eztw32.DLL INTEGER hWnd
DECLARE INTEGER TWAIN_GetSourceList ;
  IN Eztw32.dll
DECLARE INTEGER TWAIN_GetNextSourceName ;
  IN Eztw32.dll STRING @cSourceName
DECLARE INTEGER TWAIN_OpenSource ;
  IN Eztw32.DLL STRING cSourceName
DECLARE INTEGER TWAIN_AcquireNative ;
  IN Eztw32.DLL INTEGER nAppWind, INTEGER nPixelTypes
DECLARE INTEGER TWAIN_WriteNativeToFilename ;
  IN Eztw32.DLL INTEGER nDIB, STRING cFilename
DECLARE INTEGER TWAIN_FreeNative ;
  IN Eztw32.DLL INTEGER nDIB
DECLARE INTEGER TWAIN_SetMultiTransfer ;
  IN Eztw32.dll INTEGER nFlag

Capturando una imagen

Si uste solo tiene un dispositivo TWAIN device instalado, simplemente llame a la función TWAIN_AcquireNative() para capturar la imagen. Esta función inicia el proceso de captura. Cuando este ha finalizado, la imagen será presentada en memoria, en formato "device-independent bitmap (DIB)". La función utiliza dos parámetros de tipo integer; in la mayoría de casos estos serán cero. Retorna un manejador ( handle ) para la imagen.

En el caso de nuestra camara Web ToUcam, llamando a TWAIN_AcquireNative() lanza el visor de la cámara en pantalla (Figura 1). Esto despliega una alimentación continua de la imagen. En cualquier momento, el usuario puede hacer click en el botón de Captura para tomar la fotografía.


Figura 1: Esto es lo que el usuario ve cuando usted empieza el proceso de captura desde la cámar web.

Una vez que la imagen DIB esta en memoria, usted puede llamarl a la función TWAIN_WriteNativeToFilename() para escribir a un archivo que uste escoja. Por defecto, este será un BMP file, pero otros formatos también son soportados. Usted pasa dos parámetros para esta función: El primero es el manejador (handle) DIB retornado por TWAIN_AcquireNative(), y el segundo el nombre calificado del archivo destino.

Finalmente, llamar al TWAIN_FreeNative() para borrar de memoria la imagen DIB. Si usted no hace esto, usted rápidamente perdería memoria.

Aquí esta nuestro código para tomar una fotografía con la cámara web:

LOCAL lcFile, lnImageHandle, lnReply
lcFile = "c:testtest_image.bmp"
* Captura la imágen
lnImageHandle = TWAIN_AcquireNative(0,0)
* copia la imagen a un archivo
lnReply = ;
  TWAIN_WriteNativeToFilename(lnImageHandle,lcFile)
* Libera la memoria del manejador de la imágen
TWAIN_FreeNative(lnImageHandle)
* Chequear errores
IF lnReply = 0
  * imagen fue exitosamente grabada
ELSE
  * algo no estuvo bien
ENDIF

Note que la respuesta de TWAIN_WriteNativeToFilename() le dice a usted si el archivo fue escrito de forma exitosa. Sin embargo, esto no le dice a usted si el trabajo para obtener la imagen trabajó apropiadamente - la captura podría haber fallado por alguna razón, o podría haber sido cancelada por el usuario. Una manera de probarlo es verificando el tamaño del archivo resultante; si es cero, entonces ninguna imagen fue capturada.

Múltiples dispositivos

El código anterior captura una imagen desde cualquier dispositivo TWAIN que usted tenga instalado. Si usted tiene un escaner o una camera, el código iniciará el proceso de digitalización y grabará la imagen.

Pero que pasa si uste necesita manejar dos dispositivos de captura para la misma PC? Este fue el caso de nuestra aplicación, en la cual el usuario necesitaba controlar tanto la cámara como el escaner de tarjeta de negocios.

Por defecto, TWAIN_AcquireNative() capturará del primer dispositivo TWAIN que encuentre. Sin embargo, el EZTWAIN DLL tiene una función llamada TWAIN_SelectImageSource(), la cual le da al usuario la oportunidad de seleccionar un diferente dispositivo de captura. Cuando uste llama a esta función (usualmente con 0 como parámetro), el usuario ve el diálogo estñandar de la Figura 2 de las fuentes de disposivitos TWAIN que tiene disponibles para seleccionar. La función retorna 0 si el usuario cancela el dialogo o si no hay dispositivos de captura instaladps, de otra manera este retorna 1.


Figura 2: Dialogo estándar para seleccionar la fuente de captura de los dispositivos TWAIN.

En nuestro caso, nosotros no hemos querido utilizar esto para ver el díalogo. Porque nuestra aplicación tenía un botón específico para la cámara y otro para el digitalizador de tarjetas, nosotros quisimos seleccionar el dispositivo de forma progrmática.

Para hacer eso, nosotros utilizamos las dos siguientes funciones: TWAIN_GetSourceList(), la cual lee una lista de nombres de dispositivos dentro de la memoria del EZTWAIN; y TWAIN_GetNextSourceName(), la cual trae el siguiente dispositivo de la lista. Después llamamos a TWAIN_GetSourceList() una vez, y llamamos a TWAIN_GetNextSourceName() repetidamente hasta que este retorne 0 para indicar que no hay más nombre en la lista.

Como un ejemplo, aquí esta algo de código que usted podría utilizar para llenar un combo box con los nombres de los dispositivos disponibles:

LOCAL lcSource, lnReply
* Obtiene la lista de los dispositivos en memoria
TWAIN_GetSourceList()
lcSource = SPACE(255)
DO WHILE .T.
  * Obtiene el siguiente nombre de dispositivo
  lnReply = TWAIN_GetNextSourceName(@lcSource)
  IF lnReply = 0
    * No hay más nombres de dispositivos
    EXIT
  ENDIF
  
  * quitar los nulos, etc
  lcSource = ;
    LEFT(lcSource,AT(CHR(0),lcSource)-1)
  
* Agreagar al combo
  THISFORM.cboDevices.AddItem(lcSource)
ENDDO

Una vez que usted conozca los nombres de las fuentes, usted puede pasar estos a la función TWAIN_OpenSource(). Esta establecerá el dispositivo para la siguiente llamada a TWAIN_AcquireNative().

Por defecto, TWAIN_AcquireNative() cerrará la fuente de captura despùes de que finalice el proceso. Así que, si usted tiene más de un dispositivo, usted necesitará llamar a TWAIN_OpenSource() antes de cada llamada a TWAIN_AcquireNative(). Desafortunadamente, abrir la fuente de captura consume tiempo. Dependiendo del dispositivo, los usuarios podrían notar un retraso de algunos segundo antes de que la captura pueda empezar.

Como una alternativa usted puede llamar a la función TWAIN_SetMultiTransfer(1) para decirle al EZTWAIN que deje la fuente de captura abierta. De esta manera, usted solo necesita llamar a TWAIN_OpenSource() cuando usted quiera cambiar a un dispostivo diferente. Cuando nosotros tratamos de hacer esto, sin embargo, encontramos que the el visor para la cámar web ToUcam permanecia en la pantalla, frente a la ventana de nuestras aplicaciones todo el tiempo. Esto obstruía parte de la ventana de nuestra aplicación. Por esta razón, nosotros escogimos no mantener el dispositivo abierto.

Ir más lejos....

En este artículo, nosotros hemos tratado de darle a usted un pequeñ bocado del EZTWAIN DLL. Esta es una herrmienta extremadamente capaz. Con muchas más funciones que nosotros no tendriamos espacio para describir aquí. Si usted necesita contolar uno o más dispositivos TWAIN devices desde su aplicación Visual Foxpro, porque no descarga una copia y la explorae por si mismo.

Para más información acerca de EZTWAIN y otros productos relacionados con TWAIN, y para descargar una copia de la DLL, visite www.dosadi.com.

Si usted quiere conecer más acerca de Philips ToUcam web camera:
El escaner "Targus card-scanner" cuesta alrededor de US$125:
Mike Lewis Consultants Ltd. February 2003

3 comentarios :

  1. Muy bueno. Yo he usado otro camino, pero este es muy bueno.

    ResponderBorrar
  2. como hago para levantar una imagen de un escaner en un formulario en visualfoxpro

    ResponderBorrar
  3. hola soy programador principiante pero tengo un proyecto en donde necesito escanear documentos me pueden ayudar

    ResponderBorrar

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.