package uk.co.mmscomputing.device.twain;
import java.io.*;
public class TwainTransfer implements TwainConstants, TwainITransfer {
TwainSource source;
boolean isCancelled;
public TwainTransfer(TwainSource source){
this.source = source;
isCancelled = false;
}
public void initiate()throws TwainIOException{
commitCancel();
}
public void setCancel(boolean isCancelled){ // program cancelled next scan
this.isCancelled=isCancelled;
}
protected void commitCancel()throws TwainIOException{ // use before transfer setup
if( isCancelled
&& (source.getState()==STATE_TRANSFERREADY)){ // state 6
throw new TwainUserCancelException(); // state 6 -> 5
}
}
public void finish()throws TwainIOException{} // state 7 -> 6 called when image available
public void cancel()throws TwainIOException{} // state 7 -> 5 called when source (gui) cancelled
public void cleanup()throws TwainIOException{} // called once at end of acquisition loop
public static class NativeTransfer extends TwainTransfer{
private byte[] imageHandle=new byte[jtwain.getPtrSize()]; // 32 bit ptr size: 4; 64 bit ptr size: 8
public NativeTransfer(TwainSource source){
super(source);
}
public void initiate()throws TwainIOException{
super.initiate();
source.call(DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET,imageHandle);
}
public void finish()throws TwainIOException{
long handle=jtwain.getPtr(imageHandle,0); // System.err.println("Handle = 0x"+Long.toHexString(handle));
jtwain.transferNativeImage(handle); // convert DIB into BufferedImage and tell listeners about image
}
}
public static class FileTransfer extends TwainTransfer{
protected File file;
public FileTransfer(TwainSource source){
super(source);
file=null;
}
protected int getImageFileFormat(){return source.getImageFileFormat();}
public void setFile(File f){file=f;}
public File getFile(){
if(file==null){ // make sure we have a valid file name
String ext = ImageFileFormatExts[getImageFileFormat()];
try{
File dir=new File(System.getProperty("user.home"),"mmsc/tmp");dir.mkdirs();
file=File.createTempFile("mmsctwain",ext,dir);
}catch(Exception e){
file=new File("c:\\mmsctwain."+ext);
}
} // System.err.println(file.getPath());
return file;
}
public void initiate()throws TwainIOException{
super.initiate();
String file = getFile().getPath();
int iff = getImageFileFormat();
byte[] setup=new byte[260]; // TW_SETUPFILEXFER
jtwain.setString(setup,0,file); // file path for new image
jtwain.setINT16(setup,256,iff); // setup.Format = i.e. TWFF_BMP;
jtwain.setINT16(setup,258,0); // setup.VRefNum = 0; Mac only
source.call(DG_CONTROL,DAT_SETUPFILEXFER,MSG_SET,setup); // tell source file path and image type
source.call(DG_IMAGE,DAT_IMAGEFILEXFER,MSG_GET,null); // tranfer data
}
public void finish()throws TwainIOException{
jtwain.transferFileImage(file); // tell listeners about new image file
}
public void cancel()throws TwainIOException{
if((file!=null)&&file.exists()){
file.delete(); // delete file if it exists
}
}
public void cleanup()throws TwainIOException{
setFile(null); // default behaviour is to setup new temp file every time
}
}
public static class MemoryTransfer extends TwainTransfer{
private byte[] imx = new byte[(jtwain.getPtrSize()==4)?38:42]; // TW_IMAGEMEMXFER 32bit: 38; 64bit: 42
private Info info;
protected int minBufSize=-1; // default -1 don't care: accept sources preferred buffer size
protected int maxBufSize=-1;
protected int preferredSize=-1;
public MemoryTransfer(TwainSource source){
super(source);
}
protected void retrieveBufferSizes()throws TwainIOException{
byte[] setup=new byte[12]; // TW_SETUPMEMXFER
jtwain.setINT32(setup,0,minBufSize);
jtwain.setINT32(setup,4,maxBufSize);
jtwain.setINT32(setup,8,preferredSize);
source.call(DG_CONTROL,DAT_SETUPMEMXFER,MSG_GET,setup); // get preferred buffer size
minBufSize=jtwain.getINT32(setup,0);
maxBufSize=jtwain.getINT32(setup,4);
preferredSize=jtwain.getINT32(setup,8);
}
public void initiate()throws TwainIOException{
super.initiate();
retrieveBufferSizes(); //
jtwain.nnew(imx,preferredSize); // allocate native memory buffer
byte[] buf = new byte[preferredSize];
info = new Info(imx,buf);
while(true){ // while(call does not throw TwainIOException){
source.call(DG_IMAGE,DAT_IMAGEMEMXFER,MSG_GET,imx); // tranfer data
int bytesWritten = jtwain.getINT32(imx,22);
int bytesCopied = jtwain.ncopy(buf,imx,bytesWritten); // copy from native buffer to java buffer
if(bytesCopied==bytesWritten){
jtwain.transferMemoryBuffer(info); // and tell listeners about new image buffer
}
}
}
public void finish()throws TwainIOException{
int bytesWritten = jtwain.getINT32(imx,22);
int bytesCopied = jtwain.ncopy(info.getBuffer(),imx,bytesWritten); // copy from native buffer to java buffer
if(bytesCopied==bytesWritten){
jtwain.transferMemoryBuffer(info); // and tell listeners about new image data buffer
}
}
public void cleanup()throws TwainIOException{
jtwain.ndelete(imx);
}
public static class Info{
private byte[] imx;
private byte[] buf;
private int len;
Info(byte[] imx,byte[] buf){this.imx=imx;this.buf=buf;}
public byte[] getBuffer(){return buf;}
public int getCompression(){return jtwain.getINT16(imx,0);}
public int getBytesPerRow(){return jtwain.getINT32(imx,2);}
public int getWidth(){return jtwain.getINT32(imx,6);} // columns
public int getHeight(){return jtwain.getINT32(imx,10);} // rows
public int getLeft(){return jtwain.getINT32(imx,14);} // xoffset
public int getTop(){return jtwain.getINT32(imx,18);} // yoffset
public int getLength(){return jtwain.getINT32(imx,22);} // bytesWritten
public int getMemFlags(){return jtwain.getINT32(imx,26);}
public int getMemLength(){return jtwain.getINT32(imx,30);}
public long getMemPtr(){return jtwain.getPtr(imx,34);}
public String toString(){
String s=getClass().getName()+"\n";
s+="\tcompression = "+getCompression()+"\n";
s+="\tbytes per row = "+getBytesPerRow()+"\n";
s+="\ttop = "+getTop()+" left = "+getLeft()+" width = "+getWidth()+" height = "+getHeight()+"\n";
s+="\tbytes = "+getLength()+"\n";
s+="\tmemory flags = 0x"+Integer.toHexString(getMemFlags())+"\n";
s+="\tmemory length = "+getMemLength()+"\n";
s+="\tmemory pointer = 0x"+Long.toHexString(getMemPtr())+"\n";
return s;
}
}
}
}
/*
System.err.println("min: "+jtwain.getINT32(setup,0));
System.err.println("max: "+jtwain.getINT32(setup,4));
System.err.println("preferred: "+preferred);
*/
/*
System.err.println("compression "+jtwain.getINT16(imx,0));
System.err.println("bytesPerRow "+jtwain.getINT32(imx,2));
System.err.println("columns "+jtwain.getINT32(imx,6));
System.err.println("rows "+jtwain.getINT32(imx,10));
System.err.println("xoffset "+jtwain.getINT32(imx,14));
System.err.println("yoffset "+jtwain.getINT32(imx,18));
System.err.println("bytes written "+jtwain.getINT32(imx,22));
System.err.println("imx flags 0x"+Integer.toHexString(jtwain.getINT32(imx,26)));
System.err.println("imx len "+jtwain.getINT32(imx,30));
System.err.println("imx theMem 0x"+Integer.toHexString(jtwain.getPTR(imx,34)));
*/