package uk.co.mmscomputing.imageio.tiff; import java.io.*; import uk.co.mmscomputing.io.BitSwapTable; public class TIFFClassBOutputStream extends FilterOutputStream implements TIFFConstants,BitSwapTable{ private ByteArrayOutputStream buf=null; private boolean lastByteWasZero; private int width,height,offset; public TIFFClassBOutputStream(OutputStream out)throws IOException{ super(out); writeHeader(); } public void write(int cw)throws IOException{ // modified huffman code 'bytes' if(lastByteWasZero){ // 0x00,0x80 end of line code words if((cw&0x00FF)==0x80){ // inserted by SFFInputStream lastByteWasZero=false; height++; // end of line increase height return; } buf.write(0); // if not part of end of line code, write last 0 byte } if(cw==0x00){ // check for possible end of line code lastByteWasZero=true; // don't write 0 byte just yet, maybe end of line code }else{ lastByteWasZero=false; buf.write(bitSwapTable[cw&0x000000FF]); // write code word } } 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]);} } public void writeShort(int i) throws IOException{ out.write(i&0x000000FF); // first : LSB least significant byte out.write((i>>8)&0x000000FF); // MSB most significant byte } public void writeInt(int i) throws IOException{ out.write(i&0x000000FF); // first : LSB least significant byte out.write((i>>8)&0x000000FF); out.write((i>>16)&0x000000FF); out.write((i>>24)&0x000000FF); // MSB most significant byte } private void writeHeader()throws IOException{ writeShort(0x00004949); // 0: II = intel = little endian writeShort(42); // 2: version, magic value // writeInt(8); // 4: offset first Image File Directory offset=8; // 8: header size } public void writePageHeader(int width)throws IOException{ buf=new ByteArrayOutputStream(); this.width=width; this.height=0; lastByteWasZero=false; } public void writePageEnd()throws IOException{ if(lastByteWasZero){buf.write(0);} // can that happen ? int align=buf.size()&0x01; byte[] data=buf.toByteArray(); int ifdoffset=offset+data.length+align+16; // data.length+xres.size+yres.size writeInt(ifdoffset); // ptr to ifd; write data in front of ifd out.write(data); // write to image stream if(align>0){out.write(0);} // word alignment writeInt(203); // xres -16 writeInt(1); writeInt(196); // yres -8 writeInt(1); writeShort(10); // IFD +0: count directory entries // entries need to be in tag order ! writeShort(ImageWidth); // 256 +2 writeShort(LONG); writeInt(1); writeInt(width); writeShort(ImageLength); // 257 +14 writeShort(LONG); writeInt(1); writeInt(height); writeShort(Compression); // 259 +26 writeShort(SHORT); writeInt(1); writeInt(CCITTGROUP3MODHUFFMAN); writeShort(PhotometricInterpretation); // 262 +38 writeShort(SHORT); writeInt(1); writeInt(WhiteIsZero); writeShort(StripOffsets); // 273 +50 writeShort(LONG); writeInt(1); // all data in one strip ! writeInt(offset); writeShort(RowsPerStrip); // 278 +62 writeShort(LONG); writeInt(1); writeInt(height); // all data in one strip ! writeShort(StripByteCounts); // 279 +74 writeShort(LONG); writeInt(1); writeInt(data.length); // all data in one strip ! writeShort(XResolution); // 282 +86 writeShort(RATIONAL); writeInt(1); writeInt(ifdoffset-16); // 203.0 writeShort(YResolution); // 283 +98 writeShort(RATIONAL); writeInt(1); writeInt(ifdoffset-8); // 196.0 writeShort(ResolutionUnit); // 296 +110 writeShort(SHORT); writeInt(1); writeInt(Inch); // +122 offset=ifdoffset+126; } public void writeDocumentEnd()throws IOException{ writeInt(0); // end of file: ptr to next ifd == NULL } }