package uk.co.mmscomputing.imageio.sff; import java.io.*; import uk.co.mmscomputing.io.*; public class SFFOutputStream extends BufferedOutputStream{ private byte[] G3WhiteLineCode=new byte[]{(byte)0xB2,(byte)0x59,(byte)0x01}; // 1728;(other codes are possible 1704+24) private byte[] buf=null; private boolean lastByteWasZero; private int index; private int width=0/*,xres*/,yres; private int whiteLines; public SFFOutputStream(OutputStream out)throws IOException{ super(out); writeHeader(); index=0;lastByteWasZero=false; whiteLines=0; // xres=203; yres=196; } public void setXYResolution(int xres,int yres){ // this.xres=xres; // should be 203 dpi; we don't know any other value! this.yres=yres; // should be 98 dpi or 196 dpi } public void write(int cw)throws IOException{ // modified huffman code 'bytes' buf[index++]=(byte)cw; if(lastByteWasZero){ // 0x00,0x80 end of line code words if((cw&0x00FF)==0x80){ // inserted by SFFInputStream or ModHuffmanOutputStream writeLine(buf,index-2);index=0; // write line data } } lastByteWasZero=(cw==0x00); // check for possible end of line code } public void write(byte[] b)throws IOException{ write(b,0,b.length); } public void write(byte[] b,int off,int len)throws IOException{ for(int i=0;i<len;i++){ write(b[off+i]); } } // Common-ISDN-API Part I : Annex B // http://www.capi.org/download/capi20-1.pdf private void writeLine(byte[] buf,int len)throws IOException{ /* // Nobody seems to count white lines; Maybe for a reason. if((width==1728)&&(len==G3WhiteLineCode.length)){ // may have another white line int i=0; while(i<len){ // compare with white line code bytes if(buf[i]!=G3WhiteLineCode[i]){break;} // not a white line i++; } if(i==len){whiteLines++;return;} // found white line } writeWhiteLines(); // write any white lines first */ if(len>0){ if(len<=216){ out.write(len); }else{ out.write(0); out.write(len&0x0FF);out.write((len>>8)&0x0FF); // little endian (low byte first) } out.write(buf,0,len); } } private void writeWhiteLines()throws IOException{ if(whiteLines>0){ while(whiteLines>37){ // max 37: 217..253 out.write(253);whiteLines-=37; } out.write(216+whiteLines);whiteLines=0; } } private void writeHeader()throws IOException{ out.write('S');out.write('f'); // 0: magic value out.write('f');out.write('f'); out.write(0x01);out.write(0x00); // 4: version 0x01 5: 0x00 out.write(0x00);out.write(0x00); // 6: userInfo, not used by capi out.write(0x00);out.write(0x00); // 8: page count; 0x0000 if not known out.write(0x14);out.write(0x00); // 10: first page header out.write(0);out.write(0);out.write(0);out.write(0);// 12: last page header; 0x00000000 if not known out.write(0);out.write(0);out.write(0);out.write(0);// 16: offset document end; 0x00000000 if not known } // 20: 0x14 public void writePageHeader(int width)throws IOException{ if((buf==null)||(buf.length!=width)){buf=new byte[width];} this.width=width; out.write(254); // 0: pageSignature out.write(0x10); // 1: offset from after this byte to data out.write((yres==98)?0x00:0x01); // 2: resVert 0x00 => 98lpi 0x01 => 196lpi out.write(0x00); // 3: resHorz = 0x00 => 203dpi out.write(0x00); // 4: coding 0x00 => modified huffman out.write(0); // 5: reserved out.write(width&0x0FF);out.write((width>>8)&0x0FF); // 6: width out.write(0);out.write(0); // 8: height; 0x0000 if not known out.write(0);out.write(0);out.write(0);out.write(0);// 10: offset previous page out.write(0);out.write(0);out.write(0);out.write(0);// 14: offset next page index=0;lastByteWasZero=false; } // 18: end of page: start image data public void writePageEnd()throws IOException{ writeLine(buf,index); // write line data } public void writeDocumentEnd()throws IOException{ out.write(254); // 0: pageSignature out.write(0x00); // 1: 0x00 } }