package uk.co.mmscomputing.imageio.jpeg;
import java.io.*;
import java.awt.image.*;
abstract public class JFIFOutputStream extends JPEGOutputStream{
protected int version=0x102; // 1.02
protected int units=0; // density unit = 0 => Only the aspect ratio is specified.
// density unit = 1 => Density in pixels per inch.
// density unit = 2 => Density in pixels per centimeter.
protected int xDensity=1,yDensity=1;
protected int xThumbnail=0,yThumbnail=0; // no support yet [2006-01-12]
protected int[] hv,q,sel;
// public JFIFOutputStream(OutputStream out){
// super(out);
// setTables();
// }
public JFIFOutputStream(OutputStream out, int height, int width)throws IOException{
super(out); // SOI : start of image
System.out.println("3\b"+getClass().getName()+"\n\tMMSC-JPEG Encoder.");
app0(out); // APP0: straight after SOI
setTables(); // hv, q, sel
startOfFrame(height,width,hv,q); // SOF
startOfScan(sel); // SOS
}
abstract protected void setTables()throws IOException;
abstract public void writeInt(int c)throws IOException;
public void write(int[] buf, int off, int len)throws IOException{ // int[] : all samples per pixel in int
for(int i=0;i<len;i++){
writeInt(buf[off+i]);
}
}
public void write(int[] buf)throws IOException{
write(buf,0,buf.length);
}
public void setUnits(int units){this.units=units;}
public int getUnits(){return units;}
public void setXDensity(int xDensity){this.xDensity=xDensity;}
public int getXDensity(){return xDensity;}
public void setYDensity(int yDensity){this.yDensity=yDensity;}
public int getYDensity(){return yDensity;}
protected void app0(OutputStream out)throws IOException{ // 0xE0
ByteArrayOutputStream jfif =new ByteArrayOutputStream();
jfif.write('J'); // JFIF identifier
jfif.write('F');
jfif.write('I');
jfif.write('F');
jfif.write('\0');
jfif.write((version>>8)&0x000000FF); // version
jfif.write( version &0x000000FF);
jfif.write(units); // units
jfif.write((xDensity>>8)&0x000000FF); // Xdensity
jfif.write( xDensity &0x000000FF);
jfif.write((yDensity>>8)&0x000000FF); // Ydensity
jfif.write( yDensity &0x000000FF);
jfif.write(xThumbnail); // Xthumbnail
jfif.write(yThumbnail); // Ythumbnail
// to do thumbnail
byte[] data = jfif.toByteArray();
int len = data.length+2;
out.write(0xFF); // JFIF
out.write(JPEGConstants.APP0);
out.write((len>>8)&0x000000FF);
out.write( len &0x000000FF);
out.write(data);
}
/*
public void writeHeader(OutputStream out,int height, int width)throws IOException{
app0(out); // app0 straight after SOI
defineQuantizationTables(); // write QTs
defineHuffmanTables(); // write HTs
hv={0x22,0x11,0x11}; // (Hi<<4)|Vi
q={0,1,1}; // quantization table Y=0, Cb=Cr=1
startOfFrame(height,width,hv,q);
sel={0,1,1}; // DC,AC code table Y=0, Cb=Cr=1
startOfScan(sel);
}
*/
public void write(BufferedImage image)throws IOException{
DataBuffer buffer = image.getRaster().getDataBuffer();
if(buffer instanceof DataBufferByte){
write((byte[])((DataBufferByte)buffer).getData());
}else if(buffer instanceof DataBufferInt){
write((int[] )((DataBufferInt )buffer).getData());
}else{
throw new IllegalArgumentException(getClass().getName()+".write:\n\tCan only deal with byte[] and int[] arrays.");
}
}
}
// [1] JPEG File Interchange Format (JFIF)
// Version 1.02 [1992-09-01]
// http://www.jpeg.org/public/jfif.pdf [last accessed 2005-11-28]