Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Bridge the gap between Java and Twain

Integrate imaging devices in Java using Twain and JNI

  • Print
  • Feedback

Page 4 of 6

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, but might also actually prompt the user to capture an image. A vendor dialog abruptly appearing is not a pleasant user experience.

getAvailableSources()

The JNI jobjectArray Java_org_scavino_twain_JTwain_getAvailableSources() method accomplishes Steps 2 and 3 in the use-case flow. As identified in the Twain specification, the Twain layer is interrogated for each driver's vendor name. This method's source code actually originates from the Twain specification, not EZTwain.

The names are stored in the simplest container possible: a Java String array. When originally designing the API, I used the Java Vector and later decided against it. I eventually chose the jobjectArray type already available in JNI. The choice obviated the need to directly invoke expensive Vector constructors and then call add() methods via JNI. The application ultimately uses jobjectArray to display the installed devices' names.

acquire(...)

The jstring Java_org_scavino_twain_JTwain_acquire(__Ljava_lang_String_2) method helps to realize Steps 4 and 5 in the event flow. The application passes a Java String representing the device's name to JNI. If this name exists, the device's UI displays to the user for image capture.

After user intervention, the subsystem returns the fully qualified filename of the resulting JPEG image. Java can read JPEG files natively; thus, we've surmounted the Java-to-Twain gap.

I must note a few pitfalls with device names: They are not normally internationalized. Worse yet, sometimes vendors give their devices less-than-descriptive names. For example, one particular fingerprint-reader vendor doesn't even have the word fingerprint in its Twain name. Regardless, you could consider using the ResourceBundle class and some device name-mapping to make the device names logical and international. This tactic assumes you understand the devices you are deploying; otherwise you are at the vendor's mercy for writing descriptive names.

Below you will find the entire org.scavino.jtwain API as previously outlined, with all its methods and sections, minus the Javadoc. I purposely kept the API's Java portion to a minimum:

org.scavino.jtwain: The simple Twain library

package org.scavino.twain;
public class JTwain {
    private static final JTwain mInstance = new JTwain();
    protected final String DLL_NAME = "jtwain";
    
    private JTwain() {
        initLib();
    }
    
    public static JTwain getInstance(){
        return mInstance;
    }
    native public boolean isTwainAvailble();
    native public String[] getAvailableSources();
    native public String acquire();
    native public String acquire(String sourceName);
    private void initLib(){
        try {
            
            System.loadLibrary(DLL_NAME);
        }
        
        finally {
            System.out.println("Loading : " + DLL_NAME + ".dll");
        }
    }
}


As expected, the actual Java source code is rather straightforward and not complicated. The code accomplishes its actual work and details in the lower layers. Java clients see a rather simple API of mostly native methods.

  • Print
  • Feedback

Resources