import java.io.*;

public class ImageInputStream extends InputStream {
    private EasyBufferedImage source;
    private int column, row, band, channel, numberOfChannels;

    public ImageInputStream(EasyBufferedImage src, int channels) {
	numberOfChannels = channels;
	source = src;
	column = 0;
	row = 0;
	band = 0;
	channel = 0;
    }

    public boolean hasMoreBits() {
	return row < source.getHeight();
    }

    // channel is 0 through 7
    // 0 is LSB
    // 7 is MSB
    private int getBit(int value, int channel) {
	int result = (0x01 << channel) & value;
	return result == 0?0:1;
    }

   // channel is 0 through 7
    // 0 is LSB
    // 7 is MSB
    private int setBit(int value, int theBit, int channel) {
	theBit = theBit & 0x01;
	if(theBit == 0) return setOff(value, channel);
	else return setOn(value, channel);
    }

    private int setOn(int value, int channel) {
	return value | (0x01 << channel);
    }

    private int setOff(int value, int channel) {
	return value & (~(0x01 << channel));
    }

    private void advanceIndices() {
	channel = (channel + 1) % numberOfChannels;
	if(channel == 0) {
	    band = (band + 1) % source.getRaster().getNumBands();
	    if(band == 0) {
		column = (column + 1) % source.getWidth();
		if(column == 0) row++;
	    }
	}
    }

    // returns either a 0x00 or a 0x01
    public int getNextBit() throws IOException {
	if(!hasMoreBits()) throw new IOException();
	int result = source.getRaster().getSample(column, row, band);
	result = getBit(result, channel);
	advanceIndices();

	return result;
    }

    public int getNextByte() throws IOException {
	int result = 0;
	for(int i=0; i<8; i++) {
	    result = setBit(result, getNextBit(), i);
	}
	return result;
    }

    public int getNextInt() throws IOException {
	int result = 0;
	for(int i=0; i<32; i++) {
	    result = (result | (getNextBit() << i));
	}
	return result;
    }

    public int read() throws IOException {
	return getNextByte();
    }
}

