package uk.co.mmscomputing.io; import java.io.*; public class ModHuffmanInputStream extends BitInputStream implements ModHuffmanTable{ protected int state; public ModHuffmanInputStream(InputStream in){ super(in); state=WHITE; } public void skipPadding(int bits)throws IOException{ // TIFFImageReader (Class B MH) super.skipPadding(bits); state=WHITE; } public void syncWithEOL()throws IOException{ // SFFImageReader, TIFFImageReader (Class F T4 MH) if(state!=EOL){ needBits(12); while(availableBits()>=12){ if(getBits(12)==EOLCW){ clrBits(12);break; } clrBits(1);needBits(12); } } state=WHITE; } public void readEOL()throws IOException{ syncWithEOL(); } public int getState(){return state;} public int getColour(int colwhite){return (state==BLACK)?~colwhite:colwhite;} public int read()throws IOException{ int r; if(state == WHITE){ state=BLACK; r=read(makeUpWhite,12,termWhite,8); }else{ state=WHITE; r=read(makeUpBlack,13,termBlack,12); } // System.err.println(((state==WHITE)?"B ":"W ")+r); return r; } public int read(byte[] b)throws IOException{ throw new IOException(getClass().getName()+".read:\n\tInternal Error. Cannot read whole byte array with this stream !!!"); } public int read(byte[] b,int off,int len)throws IOException{ throw new IOException(getClass().getName()+".read:\n\tInternal Error. Cannot read whole byte array with this stream !!!"); } private int read(int[][] makeUp,int maxmakeUp,int[][] term,int maxterm)throws IOException{ needBits(maxterm); int len=findToken(term); // read terminating code if(len>=0){return len;} int runlen=0; needBits(maxmakeUp); // expect make-up code now len=findToken(makeUp); // read make-up code if(len==0){state=EOL;return 0;} if(len>=0){ // found make-up code while(len==MAXCHUNK){ // read 2560 codes runlen+=MAXCHUNK; needBits(maxmakeUp); len=findToken(makeUp); } if(len>=0){runlen+=len;} needBits(maxterm); } len=findToken(term); // read terminating code if(len>=0){return runlen+len;} return checkEOL(); } protected int findToken(int[][] table){ for(int i=0; i<table.length; i++) { int[] entry=table[i]; int bits=getBits(entry[2]); if(entry[0]==bits){ clrBits(entry[2]); return entry[1]; } } return -1; } protected int checkEOL()throws IOException{ int bits; needBits(12); while(availableBits()>=12){ bits=getBits(12); if(bits==EOLCW){state=EOL;clrBits(12);return 0;} if(bits!=0){throw new ModHuffmanCodingException(getClass().getName()+".checkEOL:\n\tCoding error: End of line code is missing.");} clrBits(1);needBits(12); } return -1; // eof } static public class ModHuffmanCodingException extends IOException{ public ModHuffmanCodingException(String msg){ super(msg); } } public static void main(String[] argv){ try{ // byte[] buf=new byte[]{0x06,0x25,(byte)0xD0,0x01}; 1728=1704+24 // 1728 white standard G3 fax line => B2 59 01 byte[] buf=new byte[]{(byte)0xB2,0x59,0x01}; ByteArrayInputStream bais=new ByteArrayInputStream(buf); ModHuffmanInputStream mhis=new ModHuffmanInputStream(bais); int runlen; while((runlen=mhis.read())!=-1){ System.out.println("runlen= "+runlen); } }catch(Exception e){ e.printStackTrace(); } } }