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
}
}