package uk.co.mmscomputing.imageio.jpeg;
import java.io.*;
public class JPEGHuffmanOutputStream extends OutputStream{
protected int[] BITS=new int[16]; // 16-byte list containing number of Huffman codes of each length
protected int[] HUFFVAL;
protected int[] HUFFSIZE;
protected int[] HUFFCODE;
protected int[] EHUFSI;
protected int[] EHUFCO;
protected int[] VALPTR = new int[16];
protected int[] MINCODE = new int[16];
protected int[] MAXCODE = new int[16];
protected JPEGBitOutputStream out;
public JPEGHuffmanOutputStream(JPEGBitOutputStream out,InputStream tables)throws IOException{
this.out=out;
initialize(tables);
}
private void initialize(InputStream tables)throws IOException{
int LASTK=readTableData(tables);
generateSizeTable(LASTK);
generateCodeTable(LASTK);
orderCodes(LASTK);
}
private int readTableData(InputStream tables)throws IOException{ // [1] p.40
int m=0;
for(int i=0;i<16;i++){ // 16-byte list containing number of Huffman codes of each length
BITS[i]=tables.read(); // System.out.println(Integer.toString((BITS[i]<128)?BITS[i]:BITS[i]-256))+",");
m+=BITS[i];
}
HUFFVAL=new int[m];
for(int i=0;i<m;i++){
HUFFVAL[i]=tables.read(); // System.out.println(Integer.toString((HUFFVAL[i]<128)?HUFFVAL[i]:HUFFVAL[i]-256)+",");
}
return m;
}
private void generateSizeTable(int LASTK){ // [1] p.51
HUFFSIZE=new int[LASTK+1];
int k=0;
for(int i=0;i<16;i++){
for(int j=0;j<BITS[i];j++){
HUFFSIZE[k++]=i+1;
}
}
HUFFSIZE[k]=0;
}
private void generateCodeTable(int LASTK){ // [1] p.52
HUFFCODE=new int[LASTK];
int k=0,code=0;
int si=HUFFSIZE[0];
while(true){
do{
HUFFCODE[k]=code;
code++;k++;
}while(HUFFSIZE[k]==si);
if(HUFFSIZE[k]==0){break;}
do{
code<<=1;si++;
}while(HUFFSIZE[k]!=si);
}
}
private void orderCodes(int LASTK){ // [1] p.53
EHUFCO=new int[256];
EHUFSI=new int[256];
for(int k=0;k<LASTK;k++){
int i=HUFFVAL[k];
EHUFCO[i]=HUFFCODE[k];
EHUFSI[i]=HUFFSIZE[k];
}
}
public int getTableDataLength(){
return BITS.length+HUFFVAL.length;
}
public void writeTableData(OutputStream tables)throws IOException{
for(int i=0;i<BITS.length;i++){
tables.write(BITS[i]);
}
for(int i=0;i<HUFFVAL.length;i++){
tables.write(HUFFVAL[i]);
}
}
public void write(int b)throws IOException{
out.writeBits(EHUFCO[b],EHUFSI[b]);
}
public void writeBits(int code,int size)throws IOException{
out.writeBits(code,size);
}
public void flush()throws IOException{
out.flush();
}
}