package uk.co.mmscomputing.io; import java.io.*; abstract public class READOutputStream extends ModHuffmanOutputStream{ // T.6 MMR Output Stream. How to use, see ..imageio.tiff.TIFFImageWriter private boolean H2; // if true: code next run length as mod huffman code 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 width; // page width private int[] refline=null; private int[] codeline=null; public READOutputStream(OutputStream out,int width){ super(out);init(width); } private void init(int width){ this.width=width; refline =new int[width+3]; codeline =new int[width+3]; H2=false; clindex =0; codeline[0] =width; // setup imaginary white line } protected void cleanupEOL()throws IOException{ if(H2){writeH2(0);} // write second part of H code, if left over } public void flush()throws IOException{ cleanupEOL(); super.flush(); // padding } public void writeEOL()throws IOException{ // MMR does not write EOL code, but we can do our initialisations here 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;H2=false; } private void writeH2(int rl)throws IOException{ H2=false;write1D(rl); } private void setB1(){ // find b1 so that a0 < b1 if(a0==0){ // and ref line and code line runlength have opposite colour 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 } protected void write2D(int rl)throws IOException{ if(H2){writeH2(rl);return;} // write second part of H code int a1=a0+rl; setB1(); // find b1>a0 and opposite colour while(refline[b1+1]<a1){ // pass mode while b2<a1 write(0x0008,4); // P a0=refline[b1+1]; // a0=b2 setB1(); // find b1>a0 and opposite colour } int offset=a1-refline[b1]; if(Math.abs(offset)<=3){ // vertical codes switch(offset){ case -3:write(0x0020,7);break; // VL3: a1 is three pixels to the left of b1 case -2:write(0x0010,6);break; // VL2: a1 is two pixels to the left of b1 case -1:write(0x0002,3);break; // VL1: a1 is one pixel to the left of b1 case 0:write(0x0001,1);break; // V0 : a1 is under b1 case 1:write(0x0006,3);break; // VR1: a1 is one pixel to the right of b1 case 2:write(0x0030,6);break; // VR2: a1 is two pixels to the right of b1 case 3:write(0x0060,7);break; // VR3: a1 is three pixels to the right of b1 } a0=a1; codeline[clindex++]=a0; }else{ // horizontal code write(0x0004,3); // H write1D(a1-a0); // write rest of runlen as mod huffman code H2=true; // write next runlen as mod huffman code } } protected void write1D(int runlen)throws IOException{ state=((clindex&0x01)==0)?WHITE:BLACK; // set right 'colour' table in ModHuffmanInputStream super.write(runlen); // write Modified Huffman code a0+=runlen; codeline[clindex++]=a0; } } /* [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] */