package uk.co.mmscomputing.imageio.sff; import java.io.*; import uk.co.mmscomputing.io.ModHuffmanOutputStream; public class SFFInputStream extends FilterInputStream{ /* Input: sff image file data Output: modified huffman code read(),read(byte[]),read(byte[],int,int): signal [-1] means 'end of page'. start/resumes reading if hasImage() returns true. */ private int resVert,resHorz; private int width,height,offset; private byte[] data; private byte[] lineData=null; private int index,length; private boolean eop; // end of page private byte[] whiteLine; private int whiteLines; private boolean needToDuplicateLine,duplicateLine; private int maxIllegalLineCodings=-1; // -1 => don't throw IllegalLineCoding exception public SFFInputStream(InputStream in)throws IOException{ super(in); readHeader(); if(in.read()!=254){ // 0: page signature 254 throw new IOException(getClass().getName()+".readHeader\n\tMissing page signature in sff fax document"); } } public int getWidth(){return width;} public int getHeight(){return height;} public boolean isEndOfPage(){return eop;} public void setMaxAllowedIllegalLineCodings(int max){maxIllegalLineCodings=max;} public int getVerticalResolution(){ switch(resVert){ // case 0: return 98; case 0: // duplicate lines case 1: return 196; default: return 0; // unknown,error } } public int getHorizontalResolution(){ switch(resHorz){ case 0: return 203; default: return 0; // unknown,error } } public boolean hasImage()throws IOException{ data=null;index=0;length=0; height=0;eop=false; whiteLines=0;whiteLine=null; duplicateLine=true; return readImageHeader(); } public int read(byte[] b)throws IOException{ return read(b,0,b.length); } public int read(byte[] b,int off,int len)throws IOException{ // eop=false; for(int i=0;i0){return i;} // have some data in buffer return -1; // end of page } b[off+i]=(byte)c; } return len; } public int read()throws IOException{ if(index>=length){ // get next scan line if(0 B2 59 01 [00 80] } // Common-ISDN-API Part I : Annex B // http://www.capi.org/download/capi20-1.pdf private void readHeader()throws IOException{ byte[] Sfff = new byte[4]; in.read(Sfff); // 0: 'Sfff' if((Sfff[0]!=(byte)'S')||(Sfff[1]!=(byte)'f')||(Sfff[2]!=(byte)'f')||(Sfff[3]!=(byte)'f')){ throw new IOException(getClass().getName()+".readHeader:\n\tInvalid sff fax document : Magic value is missing."); } int version=readUnsignedShort(); // 4: version 0x01 5: 0x00 if(version!=1){ throw new IOException(getClass().getName()+".readHeader:\n\tUnknown file version ["+version+"]"); } int userInfo=readUnsignedShort(); // 6: not used by capi 0x0000 int pageCount=readUnsignedShort(); // 8: 0x0000 if not known int firstPageHeader=readUnsignedShort(); // 10: capi : 0x14 but may be more int lastPageHeader=readInt(); // 12: 0x00000000 if not known int offDocEnd=readInt(); // 16: 0x00000000 if not known skipBytes(firstPageHeader-0x14); // 20: header length (0x14) } private boolean readImageHeader()throws IOException{ // int pageSignature=in.read(); // 0: 254 (read this in readLine) int pageHeaderLen=in.read(); // 1: offset from after this byte to data (usually 0x10) if(pageHeaderLen<=0){ if(pageHeaderLen==-1){ System.err.println(getClass().getName()+".readHeader:\n\tMissing page header."); }else{ // need to read until -1 so that capi system does not moan: // Disconnected during transfer (local abort) int b; if((b=in.read())!=-1){ System.err.println(getClass().getName()+".readHeader:\n\tAdditional data after end of document."); do{b=in.read();}while(b>0); } } return false; // end of stream,end of document } resVert=in.read(); // 2: 0x00 => 98lpi 0x01 => 196lpi if(resVert==255){return false;} // end of document (should not be done like that) needToDuplicateLine=(resVert==0); resHorz=in.read(); // 3: 0x00 => 203dpi int coding=in.read(); // 4: 0x00 => modified huffman if(coding!=0){throw new IOException(getClass().getName()+".readPageHeader:\n\tDo not know how to handle this sff page coding ["+coding+"].");} /*reserved=*/in.read(); // 5: 0x00 width=readUnsignedShort(); // 6: line length if((lineData==null)||(lineData.length