package uk.co.mmscomputing.imageio.tiff; import java.io.*; public class TIFFYCbCrOutputStream extends FilterOutputStream implements TIFFConstants{ protected int w,yf,xf,positioning; protected double LumaRed,LumaGreen,LumaBlue; protected double RfBY,RfBCb,RfBCr,RfWY,RfWCb,RfWCr; protected double RCr,BCb; protected byte[] red,green,blue; protected int col,off,max; protected boolean needToFlush; public TIFFYCbCrOutputStream(OutputStream out,int width,int yf,int xf){ super(out);this.w=width;this.yf=yf;this.xf=xf; col=0; off=0; max=yf*xf; red = new byte[max]; green = new byte[max]; blue = new byte[max]; needToFlush=false; } public void setPositioning(int positioning){ this.positioning=positioning; // todo. } public void setColourCoefficients(double LumaRed,double LumaGreen,double LumaBlue){ this.LumaRed=LumaRed;this.LumaGreen=LumaGreen;this.LumaBlue=LumaBlue; RCr=1/(2.0-2.0*LumaRed); BCb=1/(2.0-2.0*LumaBlue); } public void setRfBWY (double black,double white){RfBY =black;RfWY =white;} public void setRfBWCb(double black,double white){RfBCb=black;RfWCb=white;} public void setRfBWCr(double black,double white){RfBCr=black;RfWCr=white;} protected void writeDataUnit()throws IOException{ double cb=0,cr=0; for(int i=0;i<max;i++){ double R=(red[i] & 0x00FF)/255.0; double G=(green[i]& 0x00FF)/255.0; double B=(blue[i] & 0x00FF)/255.0; double Y = LumaRed*R+LumaGreen*G+LumaBlue*B; double Cb=(B-Y)*BCb*255.0; //if(Cb>255){Cb=255;} double Cr=(R-Y)*RCr*255.0; //if(Cr>255){Cr=255;} Y*=255.0; //if(Y>255) {Y=255;} // code = (FullRangeValue * (ReferenceWhite - ReferenceBlack) / CodingRange) + ReferenceBlack; Y = ( Y*(RfWY -RfBY )/255.0)+RfBY; Cb= (Cb*(RfWCb-RfBCb)/127.0)+RfBCb; Cr= (Cr*(RfWCr-RfBCr)/127.0)+RfBCr; //System.err.println("Y="+Y+" Cb="+Cb+" Cr="+Cr); if(Y>255.0) {Y=255.0;}out.write((int)Y); cb+=(Cb>255.0)?255.0:Cb; cr+=(Cr>255.0)?255.0:Cr; } out.write((int)(cb/max)); out.write((int)(cr/max)); needToFlush=false; } public void write(int b)throws IOException{ switch(col){ // per dataunit: case 0: red [off++]=(byte)b; break; // all red first case 1: green[off++]=(byte)b; break; // all green second case 2: blue [off++]=(byte)b; break; // all blue last } if(off==max){off=0;col++;} // next colour if(col==3){ // got all three colour arrays col=0;writeDataUnit(); // write data unit }else{ needToFlush=true; } } public void write1(int c)throws IOException{ double R=((c>>16)&0x00FF)/255.0; double G=((c>> 8)&0x00FF)/255.0; double B=((c )&0x00FF)/255.0; double Y = LumaRed*R+LumaGreen*G+LumaBlue*B; double Cb=((B-Y)/(2.0-2.0*LumaBlue))*255.0; //if(Cb>255){Cb=255;} double Cr=((R-Y)/(2.0-2.0*LumaRed))*255.0; //if(Cr>255){Cr=255;} Y*=255.0; //if(Y>255) {Y=255;} // code = (FullRangeValue * (ReferenceWhite - ReferenceBlack) / CodingRange) + ReferenceBlack; Y = ( Y*(RfWY -RfBY )/255)+RfBY; Cb= (Cb*(RfWCb-RfBCb)/127)+RfBCb; Cr= (Cr*(RfWCr-RfBCr)/127)+RfBCr; out.write((int)Y); out.write((int)Cb); out.write((int)Cr); } public void flush()throws IOException{ // System.err.println(getClass().getName()+".flush()"); // todo: repeat last value if(needToFlush){ writeDataUnit(); } col=0;off=0; super.flush(); } }