package uk.co.mmscomputing.imageio.jpeg; import java.io.*; public class JPEGComponentsOutputStream extends OutputStream implements JPEGConstants{ protected /*JPEGDCT*/OutputStream[] outs; protected byte[][] buffer; protected int[] H,V; protected int HMax,VMax; protected int xMCUStep,yMCUStep; protected int width,ww; protected int y,x,comp,spp; public JPEGComponentsOutputStream(/*JPEGDCT*/OutputStream[] outs,int[] HV,int width)throws IOException{ this.outs=outs; this.width=width; y=0;x=0;comp=0; spp=HV.length; H = new int[spp]; V = new int[spp]; HMax = 0; VMax = 0; for(int c=0;c<spp;c++){ H[c]=(HV[c]>>4)&0x0F; V[c]= HV[c] &0x0F; if(HMax<H[c]){HMax=H[c];} if(VMax<V[c]){VMax=V[c];} } xMCUStep=HMax*8; yMCUStep=VMax*8; ww=((width+xMCUStep-1)/xMCUStep)*xMCUStep; buffer = new byte[spp][ww*yMCUStep]; } protected void writeDataUnit(OutputStream out,byte[] buffer,int vv,int hh,int off)throws IOException{ int yStep=VMax-vv+1; int xStep=HMax-hh+1; for(int y=0;y<DCTSize*yStep;y+=yStep){ for(int x=0;x<DCTSize*xStep;x+=xStep){ int c=0; // subsampling for(int yy=0;yy<yStep;yy++){ for(int xx=0;xx<xStep;xx++){ c+=buffer[off+(y+yy)*ww+(x+xx)]&0x000000FF; } } c/=yStep*xStep; out.write(c); } } } /* protected void writeDataUnit(OutputStream out,byte[] buffer,int vv,int hh,int off)throws IOException{ int yStep=VMax-vv+1; int xStep=HMax-hh+1; for(int y=0;y<DCTSize*yStep;y+=yStep){ for(int x=0;x<DCTSize*xStep;x+=xStep){ int c=0; // subsampling for(int yy=0;yy<yStep;yy++){ for(int xx=0;xx<xStep;xx++){ c+=buffer[off+(y+yy)*ww+(x+xx)]&0x000000FF; } } c/=yStep*xStep; out.write(c); } } } */ protected void writeMCU(OutputStream out,byte[] buffer,int vv,int hh,int off)throws IOException{ for(int v=0;v<vv;v++){ int yy=v*DCTSize*ww; // row for(int h=0;h<hh;h++){ int xx=off+h*DCTSize; // col writeDataUnit(out,buffer,vv,hh,yy+xx); } } } protected void writeMCUs()throws IOException{ for(int x=0;x<ww;x+=xMCUStep){ for(int c=0;c<spp;c++){ writeMCU(outs[c],buffer[c],V[c],H[c],x); } } } public void write(int b)throws IOException{ buffer[comp++][y*ww+x]=(byte)b; // fill buffer if(comp==spp){comp=0;x++;} // next pixel if(x==width){ // next line if(x<ww){ // fill rest of line with end of line colour for(int c=0;c<spp;c++){ byte[] data=buffer[c]; byte val =data[y*ww+width-1]; for(int i=width;i<ww;i++){data[y*ww+i]=val;} } } x=0;y++; } if(y==yMCUStep){ // buffer full y=0;writeMCUs(); } } public void flush()throws IOException{ if(y>0){ for(int c=0;c<spp;c++){ // fill buffer with copy of last line byte[] data=buffer[c]; for(int k=y;k<yMCUStep;k++){ for(int i=0;i<ww;i++){ data[k*ww+i]=data[(y-1)*ww+i]; } } } writeMCUs(); } y=0;x=0;comp=0; } }