Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Bridge the gap between Java and Twain

Bridge the gap between Java and Twain

Tutorial Details:

Bridge the gap between Java and Twain
Bridge the gap between Java and Twain
By: By Hugo Scavino
Integrate imaging devices in Java using Twain and JNI
wain has long allowed Win32 programmers to integrate imaging devices into their applications at no cost. Twain allows us to capture images from seemingly disparate devices like flatbed scanners, fingerprint readers, Web cams, and digital cameras. The standard allows Aunt Emma to take a picture at a wedding, acquire the images onto her PC that afternoon, and send the edited pictures to the entire family that night. Thus, when interfacing with image devices, application developers can free themselves from working with arcane and many times proprietary interfaces, and instead concentrate on one interface.
Twain functionality would greatly benefit the Win32 Java community, but, alas, these open-standards benefits have been available for years in the Win32 world, but, because of Java's platform independence, not the Java world. In this article I show how you too can talk Twain by introducing an architecture that integrates a Java 1.4 Swing application with a simple JNI (Java Native Interface)-based package.
Let's start by discussing the architectural layers involved in retrieving a JPEG file from your favorite Twain-enabled device. Twain natively acquires a Win32 DIB (Device-Independent Bitmap), but we will retrieve a Java readable JPEG file. Retrieving such a file involves five architectural layers:
Your Swing 1.4 GUI (graphical user interface).
The org.scavino.jtwain source code shown later in this article.
The generated JNI wrapper classes.
The EZTwain DLL (dynamic link library), a freeware library encapsulating much of the Twain interface with an easy-to-use C API. The EZTwain library has long helped our C brethren with Twain. The same library via JNI can now assist our Java bothers and sisters.
The free Intel JPEG Library (IJL) for encoding and decoding JPEG images. While it does feature more functionalites, providing a Java-readable JPEG is its main responsibility.
Thankfully all these technologies are free.
Now that we have thought out the architectural layers, we now self impose a process. As an OOAD (object-oriented analysis and design) instructor, I insist on an inception phase and mission statement when developing new APIs. My mission is to build the smallest API possible that will satisfy the specified requirements. What requirements you may ask? Rather than enumerating countless never-to-be-read shall statements, I use the Rational Unified Process (RUP) for guidance. As RUP is a use-case-focused process, we start with our "Acquire a Twain Image" use-case, which has one primary flow consisting of several steps to accomplish our result.
You will find the entire use-case here . The document is intentionally human readable and devoid of code mumbo-jumbo. If we write our requirements in plain English, our stakeholders will take the time to understand our use-case. When analysts, management, and testers understand the use-cases, we receive software on time and on budget. Let me paraphrase the primary use-case as follows:
Acquire Twain image steps (Happy Day Scenario):
The application checks for Twain's existence
Twain exists
The application queries the Twain subsystem for all available sources
The application displays the choices in the Swing 1.4 GUI
The user chooses a source
The user presses an "Acquire" button
The application retrieves a Java image into the application
The application further processes a Java image as the requirements state
Technically the use-case will conclude when you add your application-specific requirements.
Now that we have our use-case defined, we can begin to move towards design by creating a UML (Unified Modeling Language) sequence diagram. The diagram below lets us sequentially follow the steps required to fulfill the preceding use-case. The diagram allows us to follow the messages as they touch each class and thus, clearly see how the use-case is being implemented.
Acquire image primary flow. Click on thumbnail to view full-size image.
Without the use-case and flow, we could write large cumbersome APIs that no one will use or, worse yet, come up short during construction.
We can place the above steps into an iteration plan. We finish the iteration when we accomplish all the steps. We can add more features in subsequent iterations once we evaluate feedback from the first iteration. For now, we need only the bare minimum.
When I wrote the first version of the org.scavino.jtwain library, I added almost every function that Twain exposed?not a good idea. My client wanted only the minimum, and I gave the near maximum. I could have forgone the extra code to maintain, understand, and document.
Intel JPEG Library
Our architecture first needs a reliable JPEG decoder that can convert the native Twain DIBs to a format that Java can interpret. The IJL encodes and decodes your JPEG images. In its simplest form, the IJL can convert the native Twain DIBs to JPEGs rather than the default Windows BMP (Bitmap). Since Java natively handles JPEGs and not BMPs, some subsystem must complete the conversion. Choosing which layer handles the conversion is an important decision for several reasons:
First, we must decide if Java GUI clients should need additional libraries like Sun Microsystems' JAI (Java Advanced Imaging) or Java native BMP classes to manipulate the BMP file format. Or should the native DLL process the image?
Second, if the DLL converts the images to JPEG, then the IJL DLL might have to reside in the client machine's path. Adding a DLL to the DOS path is not a trivial deployment decision.
Third, an additional option would link the much larger ijl15l.lib library in lieu of the smaller ijl15.lib link library. This static library increases the stack size and would ignore potential ijl15l.lib DLL upgrades from Intel. If we wanted new JPEG functionality from the ijl15.dll , we would have to rebuild and test again.
To make this exercise cleaner and less daunting, the static link library option is the best. We won't need to call the cumbersome GetProcAddress(...) method, and we have one less deployment hassle to manage.
Classic EZTwain 1.x DLL
Now that we can decode the native image from Twain to a supported Java format like JPEG, wrapping the Twain C API becomes a priority. At first, I started to write my own Twain wrapper library. After several failures and a bruised ego, I searched for an alternative. I strained my brain until I found the EZTwain DLL library. Dosadi has given away their 1.x version to the Twain community at large. After some minor modifications, we can use the EZTwain DLL with our JNI headers. Because the DLL as-is hangs during the Twain calls, source code changes were required.
Specifically I modified the TWAIN_UnloadSourceManager() method. I had to ensure all the pointers were set to null, otherwise the DLL would not properly unload the source manager. After I changed the source code, the Java application responded without errors. The native Win32 environment didn't need these changes, as the DLL unloaded properly
Java and Win32 hardware: The ugly truth
Though the low-level plumbing is set up, communication between Java and Win32 will still present problems. Java has difficulty integrating with hardware devices because of the Win32 message pump. Java has no real way to connect to the event handlers in the Win32 world. Instead, you must create a proxy window, so it, not the Java application, can receive the Win32 SDK messages.
That approach negates the need to pass the HWND parameter to EZTwain DLL; instead we can use a null HWND as a parameter within the DLL. When the EZTwain 1.x DLL detects a null, it creates a proxy window, hides it, and uses it for pumping message handlers. The Java client is relieved of the HWND responsibility, simplifying the bridge between the two layers.
Note: That technique proves useful for synchronous hardware devices like Twain or utility libraries that lack a real GUI. With Twain, you pass it a command, the vendor-supplied dialog appears, the acquisition occurs, and then Twain eventually returns a DIB. However, be aware that, with TAPI (Telephony Application Programmers Interface) and other asynchronous technologies, passing a null HWND will not suffice. Further processing of call-back methods may be required. Asynchronous hardware devices need both the application and the DLL to participate in two-way communication via the Win32 message handlers. As Java clients cannot take part, more complex solutions are required: perhaps a TCP/IP socket server.
The JNI C interface
Now we need to map the previous flow of events to an actual interface in the JNI layer. We must write the exact number of JNI methods required to realize the use-case?no more and no less. Strictly adhering to RUP keeps us focused. The sequence diagram depicts the user actor going through the use-case and exercising our API. I detail the methods below:
isTwainAvailble()
The JNI method jboolean Java_org_scavino_twain_JTwain_isTwainAvailble() allows an application to test for Twain's existence. This method accomplishes Step 1 in the use-case's primary flow. isTwainAvailble() does not confirm whether your particular Twain device is enabled or even attached to the machine. It merely tests for the existence of the twain.dll in your path and verifies that you have at least one Twain device installed. This result is cached after the Twain library has been prodded. A more elaborate exception-handling mechanism could replace the simple boolean return type. Again, the current goal is simplicity, and a future iteration could have exception handling in the interface.
While the JNI jboolean Java_org_scavino_twain_JTwain_isTwainAvailble() method could poll each device to see if it is actually attached, doing so would sacrifice performance and usability. Calling the device not only degrades performance


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Bridge the gap between Java and Twain

View Tutorial:
Bridge the gap between Java and Twain

Related Tutorials:

A promise of easier embedded-systems networking - JavaWorld November 1999
A promise of easier embedded-systems networking - JavaWorld November 1999
 
A ZipClassLoader for automated application distribution - JavaWorld April 2000
A ZipClassLoader for automated application distribution - JavaWorld April 2000
 
JDBC drivers in the wild - JavaWorld July 2000
JDBC drivers in the wild - JavaWorld July 2000
 
Deliver cellular messages with SMS - JavaWorld March 2001
Deliver cellular messages with SMS - JavaWorld March 2001
 
Flex your grid layout
Flex your grid layout
 
Create your own type 3 JDBC driver, Part 1
Create your own type 3 JDBC driver, Part 1
 
Design patterns make for better J2EE apps
Design patterns make for better J2EE apps
 
Bridge the gap between Java and Twain
Bridge the gap between Java and Twain
 
JAligner
JAligner JAligner is an open source Java implementation of the Smith-Waterman algorithm with Gotoh's improvement for biological local pairwise sequence alignment using the affine gap penalty model.
 
Bridging the Gap: J2SE 5.0 Annotations
Bridging the Gap: J2SE 5.0 Annotations It takes a long time for the Java community to fully absorb a major new JDK release; it seems to take about two more releases after a brand new version of the JDK before everything settles down. Application server v
 
Integrate COM and Java components
Interoperability issues have long made integration of Microsoft® Component Object Model (COM) and Java™ components a daunting task. The Development Tool for Java-COM Bridge, available from IBM alphaWorks, simplifies the job and also provides an evoluti
 
Development Tool for Java-COM Bridge
What is Development Tool for Java-COM Bridge? Development Tool for Java-COM Bridge is a tool for developing and enabling tight communication between JavaTM- and COM-based applications. An application running on Microsoft Windows® systems is typically co
 
An Introduction to Java Object Persistence with EJB
The 'impedance mismatch' between relational databases' tabular orientation and object-oriented Java's hierarchical one is a perennial problem for which the Java world has several good solution offerings. This article, the first in a three-part series, wil
 
Java Tech: Acquire Images with TWAIN and SANE, Part 1
Scanners, digital cameras, and other image-acquisition devices are part of the computing landscape. Despite their ubiquity, however, Java does not provide a standard API for interacting with these devices. And yet there certainly is a desire to have a sta
 
JTwain
JTwain will implement a Java interface to the the Win32 C DLL TWAIN acquire methods.
 
Accessing the Database from Servlet
This article shows you how to access database from servlets. Here I am assuming that you are using win95/98/2000 and running Java Web Server.
 
Overview of JDBC and its use with Microsoft Access
JDBC provides a set of classes for Java with a standard SQL database access interface. Goal is uniform access to a wide range of relational databases.
 
Distributed Objects & Components: JavaBeans
What is JavaBeans ? (from the FAQ)
 
Introduction to the JDBC
Introduction to the JDBC Introduction to the JDBC Introduction T his article introduce you with JDBC and shows you how to our search engine with database. What is JDBC? J ava Database Connectivity or JDBC for short is set of Java API's that
 
DB Visual Architect for Eclipse
DB Visual Architect for Eclipse (DBVA-EC) is a full featured Object Relational Mapping (ORM) plugin for Eclipse that provides the industry\'s best round-trip code engineering support with Java.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.