package uk.co.mmscomputing.io; import java.io.*; public class BitInputStream extends FilterInputStream{ private int buf; private int bitsAvail; private boolean eof; protected int count=0; protected boolean nextByteMoreSignificant; public BitInputStream(InputStream in,boolean nbms){ super(in); bitsAvail=0; buf=0; eof=false; count=0; nextByteMoreSignificant=nbms; } public BitInputStream(InputStream in){ this(in,true); } public void setNextByteMoreSignificant(boolean nextByteMoreSignificant){ this.nextByteMoreSignificant=nextByteMoreSignificant; } public void reset()throws IOException{ super.reset(); bitsAvail=0; buf=0; eof=false; count=0; } public int availableBits(){ if(eof && (bitsAvail<=0)){return -1;} return bitsAvail; } public void skipPadding(int bits)throws IOException{ clrBits(bitsAvail%bits); } public int readBit()throws IOException{ // read one bit if(eof && (bitsAvail<=0)){ return -1; } needBits(1); int bit=getBits(1); clrBits(1); return bit; } public int readBits(int bitcount)throws IOException{ // read "count" bit if(eof && (bitsAvail<=0)){ return -1; } if(bitcount==0){ return 0; } needBits(bitcount); int bits=getBits(bitcount); clrBits(bitcount); return bits; } protected int cbCount()throws IOException{ // callback for subclasses return in.read(); } public void needBits(int bitcount)throws IOException{ // Assert(bitcount<32); while((eof==false)&&(bitsAvail<bitcount)){ int b=cbCount(); if(b==-1){eof=true;break;} b&=0x00FF; count++; buf|=(nextByteMoreSignificant)?(b<<bitsAvail):(b<<(24-bitsAvail)); bitsAvail += 8; } } protected void clrBits(int bitcount){ bitsAvail -= bitcount; if(nextByteMoreSignificant){buf>>>=bitcount;}else{buf<<=bitcount;} } protected int getBits(int bitcount){ bitcount=32-bitcount; return (nextByteMoreSignificant)?((buf<<bitcount)>>>bitcount):(buf>>>bitcount); } public static void main(String[] argv){ // bytes 1001 1001 1000 1000 1001 1001 // nextByteMoreSignificant=true bitcount=9 // i.e. GIF LZW // code1 = 0 1001 1001 // code2 = 0 1100 0100 // code3 = 0 0010 0110 // nextByteMoreSignificant=false bitcount=9 // i.e. TIFF LZW, JPEG // code1 = 1 0011 0011 // code2 = 0 0010 0010 // code3 = 0 1100 1000 try{ byte[] buf=new byte[]{(byte)0x99,(byte)0x88,(byte)0x99}; ByteArrayInputStream bais=new ByteArrayInputStream(buf); BitInputStream is=new BitInputStream(bais,true); System.out.println("\nnextByteMoreSignificant = true"); int code; while((code=is.readBits(9))!=-1){System.out.println("code= "+Integer.toBinaryString(code));} bais=new ByteArrayInputStream(buf); is=new BitInputStream(bais,false); System.out.println("\nnextByteMoreSignificant = false"); while((code=is.readBits(9))!=-1){System.out.println("code= "+Integer.toBinaryString(code));} }catch(Exception e){ e.printStackTrace(); } } }