package uk.co.mmscomputing.io;
import java.io.*;
public class ModModREADInputStream extends ModHuffmanInputStream implements ModREADTable{
// T.6 MMR Input Stream. How to use, see ..imageio.tiff.TIFFImageReader
private int[] refline=null;
private int[] codeline=null;
private int clindex=0; // index into code line
private int a0; // pixel position in scan line
private int b1; // index into reference line
private int maxb1; // maximum available run length values from reference line
private int code; // next READ code
private int width; // page width
public ModModREADInputStream(InputStream in,int width)throws IOException{
super(in);
this.width=width;
refline =new int[width+3];
codeline =new int[width+3];
init(width);
}
protected void init(int width)throws IOException{
clindex =1;
codeline[0] =width; // setup imaginary white line
getREADCode(); // read first READ code
}
protected void initNewLine()throws IOException{
if(code==HX){readHorizontalMode2();} // HX is left over when H coded at end of line and second run is zero.
int[] swap=refline;refline=codeline;codeline=swap;
maxb1=clindex; // set max possible code index from last line.
refline[maxb1] =width; // set max possible line width
refline[maxb1+1]=width;
refline[maxb1+2]=width;
clindex=0;b1=0;a0=0;
}
public void readEOL()throws IOException{ // remark: T.6 does not use EOL codes
initNewLine(); // but we need to set up our buffers
}
protected int getREADCode()throws IOException{
needBits(24);
code=findToken(codes);
return code;
}
private void setB1(){ // find b1 so that a0 < b1 and ref line and code line runlength have opposite colour
if(a0==0){
b1=0;
}else{
while((0<b1)&&(a0<refline[b1-1])){b1--;}
while((b1<maxb1)&&(refline[b1]<=a0)){b1++;}
}
if((b1&0x0001)!=(clindex&0x0001)){b1++;} // want opposite colour
}
private int readPassMode()throws IOException{
int rl=0,len;
do{
setB1(); // find b1>a0 and opposite colour
len =refline[b1+1]-a0; // b2 - a0
a0 +=len;
rl +=len;
}while(getREADCode()==P);
rl+=read2D(); // colour in pass mode never changes, hence need to add another run
return rl;
}
private int readHorizontalMode1()throws IOException{
state=((clindex&0x01)==0)?WHITE:BLACK; // set right 'colour' table in ModHuffmanInputStream
int rl=super.read(); // read first mod huffman code
a0+=rl;
codeline[clindex++]=a0;
code=HX; // signal to read second ModHuffman code during next read()
return rl;
}
private int readHorizontalMode2()throws IOException{
int rl=super.read(); // read second mod huffman code
a0+=rl;
codeline[clindex++]=a0;
getREADCode();
return rl;
}
private int readVerticalMode()throws IOException{
setB1(); // find b1>a0 and opposite colour
int offset = code-V0;
int a1 = refline[b1]+offset; // a1 = reference line position +- offset
int rl = a1-a0;
a0=a1;
codeline[clindex++]=a0;
getREADCode();
return rl;
}
protected int read2D()throws IOException{
switch(code){
case P: return readPassMode();
case H: return readHorizontalMode1();
case V0:
case VL1:case VL2:case VL3:
case VR1:case VR2:case VR3:
return readVerticalMode();
case HX: return readHorizontalMode2();
case EOFB: // TIFF F : end of strip
default: return -1;
}
}
protected int read1D()throws IOException{
int rl=super.read();
a0+=rl;
codeline[clindex++]=a0;
return rl;
}
public int read()throws IOException{
return read2D(); // remark: T.6 does only use READ codes, no reference line
}
}
/*
[1] FAX: Facsimile Technology and Systems (3rd);
Kenneth McConnell,Dennis Bodson,Stephen Urban
Artech House Publishers
ISBN: 0-89006-944-1
[2] RFC 2306: Tag Image File Format (TIFF) - F Profile for Facsimile
[3] ITU T.4: Group 3 MR code; Modified READ Code; READ = Relative Element Address Designate
[4] ITU T.6: Group 4 MMR code; Modified Modified READ
[5] http://einstein.informatik.uni-oldenburg.de/rechnernetze/ccitt_t4.htm [last accessed: 2005-08-26]
[6] http://www.buddism.ru//DHARMA_text/YagpoTibetanOCR/_OCR/WORK_ARCH/hsfsys2.2/src/lib/image/grp4deco.c [last accessed: 2005-10-13]
*/