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();
}
}
}