package uk.co.mmscomputing.imageio.tiff; import java.io.*; import java.awt.image.*; import javax.imageio.stream.*; // TIFF 6.0 Specification 3 June 1992 class DEFactory implements TIFFConstants{ static public DE read(ImageInputStream in)throws IOException{ int tag=in.readUnsignedShort(); switch(tag){ case NewSubfileType: return new NewSubfileTypeDE(in); // 254 case ImageWidth: return new ImageWidthDE(in); // 256 case ImageLength: return new ImageLengthDE(in); // 257 case BitsPerSample: return new BitsPerSampleDE(in); // 258 case Compression: return new CompressionDE(in); // 259 case PhotometricInterpretation: return new PhotometricInterpretationDE(in); // 262 case FillOrder: return new FillOrderDE(in); // 266 case DocumentName: return new DocumentNameDE(in); // 269 case ImageDescription: return new ImageDescriptionDE(in); // 270 case StripOffsets: return new StripOffsetsDE(in); // 273 case Orientation: return new OrientationDE(in); // 274 case SamplesPerPixel: return new SamplesPerPixelDE(in); // 277 case RowsPerStrip: return new RowsPerStripDE(in); // 278 case StripByteCounts: return new StripByteCountsDE(in); // 279 case XResolution: return new XResolutionDE(in); // 282 case YResolution: return new YResolutionDE(in); // 283 case PlanarConfiguration: return new PlanarConfigurationDE(in); // 284 case T4Options: return new T4OptionsDE(in); // 292 case T6Options: return new T6OptionsDE(in); // 293 case ResolutionUnit: return new ResolutionUnitDE(in); // 296 case PageNumber: return new PageNumberDE(in); // 297 case Software: return new SoftwareDE(in); // 305 case DateTime: return new DateTimeDE(in); // 306 case Artist: return new ArtistDE(in); // 315 case Predictor: return new PredictorDE(in); // 317 case ColorMap: return new ColorMapDE(in); // 320 case ExtraSamples: return new ExtraSamplesDE(in); // 338 case SampleFormat: return new SampleFormatDE(in); // 339 case JPEGTables: return new JPEGTablesDE(in); // 347 case YCbCrCoefficients: return new YCbCrCoefficientsDE(in); // 529 case YCbCrSubSampling: return new YCbCrSubSamplingDE(in); // 530 case YCbCrPositioning: return new YCbCrPositioningDE(in); // 531 case ReferenceBlackWhite: return new ReferenceBlackWhiteDE(in); // 532 default: return new UnknownDE(tag,in); } } static public class UnknownDE extends DE{ public UnknownDE(int tag,ImageInputStream in)throws IOException{ super(tag);read(in); } } static public class NewSubfileTypeDE extends DE{ // 254 // Bit 0 is 1 if the image is a reduced-resolution version of another image in this TIFF file; else the bit is 0. // Bit 1 is 1 if the image is a single page of a multi-page image (see the PageNumber field description); else the bit is 0. // Bit 2 is 1 if the image defines a transparency mask for another image in this TIFF file. The PhotometricInterpretation value must be 4, designating a transparency mask. public NewSubfileTypeDE(ImageInputStream in)throws IOException{ super(NewSubfileType);read(in); } public NewSubfileTypeDE(int val)throws IOException{ super(NewSubfileType);setType(LONG);setCount(1);setValue(val); } static int getDefault(){return 0;} } static public class ImageWidthDE extends DE{ // 256 public ImageWidthDE(ImageInputStream in)throws IOException{ super(ImageWidth);read(in); } public ImageWidthDE(int val)throws IOException{ super(ImageWidth);setType(LONG);setCount(1);setValue(val); } } static public class ImageLengthDE extends DE{ // 257 public ImageLengthDE(ImageInputStream in)throws IOException{ super(ImageLength);read(in); } public ImageLengthDE(int val)throws IOException{ super(ImageLength);setType(LONG);setCount(1);setValue(val); } } static public class BitsPerSampleDE extends DE{ // 258 // BitsPerSample 258 SHORT Samples per pixel // read long[] bps; public BitsPerSampleDE(ImageInputStream in)throws IOException{ super(BitsPerSample); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); bps=readIntArray(in); } public int getBits(int index){return (int)bps[index];} public long[] getBits(){return bps;} // write public BitsPerSampleDE(int len)throws IOException{ super(BitsPerSample); bps=new long[len]; setType(SHORT); setCount(len); } public void setBitsPerSample(int index,long bits){ bps[index]=bits; } public void write(ImageOutputStream out)throws IOException{ writeIntArray(out,bps); } } static public class CompressionDE extends DE{ // 259 // 1,2,32773 mandatory public CompressionDE(ImageInputStream in)throws IOException{ super(Compression);read(in); } public CompressionDE(int val)throws IOException{ super(Compression);setType(SHORT);setCount(1);setValue(val); } } static public class PhotometricInterpretationDE extends DE{ // 262 // 0 = WhiteIsZero (Compression 2) // 1 = BlackIsZero // 2 = public PhotometricInterpretationDE(ImageInputStream in)throws IOException{ super(PhotometricInterpretation);read(in); } public PhotometricInterpretationDE(int val)throws IOException{ super(PhotometricInterpretation);setType(SHORT);setCount(1);setValue(val); } } static public class FillOrderDE extends DE{ // 266 // 1 = Most Significant Bit first // 2 = Least Significant Bit first public FillOrderDE(ImageInputStream in)throws IOException{ super(FillOrder);read(in); } public FillOrderDE(int val)throws IOException{ super(FillOrder);setType(SHORT);setCount(1);setValue(val); } } static public class DocumentNameDE extends DE{ // 269 String name; public DocumentNameDE(ImageInputStream in)throws IOException{ super(DocumentName); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); name=readString(in)[0]; } } static public class ImageDescriptionDE extends DE{ // 270 String name; public ImageDescriptionDE(ImageInputStream in)throws IOException{ super(ImageDescription); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); name=readString(in)[0]; } } static public class StripOffsetsDE extends DE{ // 273 private long[] offsets; // Tag length = StripsPerlmage for PlanarConfig = 1 // SamplesPerPixel * StripsPerlmage for PlanarConfig = 2 // read public StripOffsetsDE(ImageInputStream in)throws IOException{ super(StripOffsets);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); offsets=readIntArray(in); } public long[] getOffsets(){return offsets;} // write public StripOffsetsDE(int len)throws IOException{ super(StripOffsets); offsets=new long[len]; setType(LONG); setCount(len); } public void setOffset(int index,long offset){ offsets[index]=offset; } public void write(ImageOutputStream out)throws IOException{ writeIntArray(out,offsets); } } static public class OrientationDE extends DE{ // 274 public OrientationDE(ImageInputStream in)throws IOException{ super(Orientation);read(in); } public OrientationDE(int val)throws IOException{ super(Orientation);setType(SHORT);setCount(1);setValue(val); } } static public class SamplesPerPixelDE extends DE{ // 277 public SamplesPerPixelDE(ImageInputStream in)throws IOException{ super(SamplesPerPixel);read(in); } public SamplesPerPixelDE(int val)throws IOException{ super(SamplesPerPixel);setType(SHORT);setCount(1);setValue(val); } } static public class RowsPerStripDE extends DE{ // 278 public RowsPerStripDE(ImageInputStream in)throws IOException{ super(RowsPerStrip);read(in); } public RowsPerStripDE(int val)throws IOException{ super(RowsPerStrip);setType(LONG);setCount(1);setValue(val); } } static public class StripByteCountsDE extends DE{ // 279 private long counts[]; // read public StripByteCountsDE(ImageInputStream in)throws IOException{ super(StripByteCounts);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); counts=readIntArray(in); } public long[] getCounts(){return counts;} // write public StripByteCountsDE(int len)throws IOException{ super(StripByteCounts); counts=new long[len]; setType(LONG); setCount(len); } public void setCount(int index,long count){ counts[index]=count; } public void write(ImageOutputStream out)throws IOException{ writeIntArray(out,counts); } } static public class XResolutionDE extends DE{ // 282 double xres; public XResolutionDE(ImageInputStream in)throws IOException{ super(XResolution);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); xres=readReal(in); } public XResolutionDE(double val)throws IOException{ super(XResolution);setType(RATIONAL);setCount(1);xres=val; } public void write(ImageOutputStream out)throws IOException{ writeReal(out,xres); } } static public class YResolutionDE extends DE{ // 283 double yres; public YResolutionDE(ImageInputStream in)throws IOException{ super(YResolution);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); yres=readReal(in); } public YResolutionDE(double val)throws IOException{ super(YResolution);setType(RATIONAL);setCount(1);yres=val; } public void write(ImageOutputStream out)throws IOException{ writeReal(out,yres); } } static public class PlanarConfigurationDE extends DE{ // 284 public PlanarConfigurationDE(ImageInputStream in)throws IOException{ super(PlanarConfiguration);read(in); } } static public class T4OptionsDE extends DE{ // 292 // Bit 0: 0 = 1-Dimensional; 1 = 2-Dimensional (MR) // Bit 1: 0 = compressed; 1 = uncompressed mode (not allowed in rfc 2306) // Bit 2: 0 = non byte aligned EOLs; 1 = byte aligned EOLs public T4OptionsDE(ImageInputStream in)throws IOException{ super(T4Options);read(in); } public T4OptionsDE(int val)throws IOException{ super(T4Options);setType(LONG);setCount(1);setValue(val); } public boolean is1Dimensional(){return (val&0x00000001)==0;} public boolean is2Dimensional(){return (val&0x00000001)!=0;} public boolean isCompressed(){return (val&0x00000002)==0;} public boolean isByteAligned(){return (val&0x00000004) !=0;} } static public class T6OptionsDE extends DE{ // 293 // Bit 0: 0 = 2-Dimensional (MMR) // Bit 1: 0 = compressed; 1 = uncompressed mode (not allowed in rfc 2306) public T6OptionsDE(ImageInputStream in)throws IOException{ super(T6Options);read(in); } public T6OptionsDE(int val)throws IOException{ super(T6Options);setType(LONG);setCount(1);setValue(val); } public boolean is2Dimensional(){return (val&0x00000001)==0;} public boolean isCompressed(){return (val&0x00000002)==0;} } static public class ResolutionUnitDE extends DE{ // 296 // 1 = no unit // 2 = inch (default) // 3 = cm public ResolutionUnitDE(ImageInputStream in)throws IOException{ super(ResolutionUnit);read(in); } public ResolutionUnitDE(int val)throws IOException{ super(ResolutionUnit);setType(SHORT);setCount(1);setValue(val); } } static public class PageNumberDE extends DE{ // 297 // SHORT/SHORT <=> page number (0...)/page count (0=unknown) private long values[]; // read public PageNumberDE(ImageInputStream in)throws IOException{ super(PageNumber);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); values=readIntArray(in); } // write public PageNumberDE(int page,int count)throws IOException{ super(PageNumber); values=new long[2]; setType(SHORT); setCount(2); } public void setPage(int page){values[0]=page;} public int getPage(){return (int)values[0];} public void setPageCount(int pc){values[1]=pc;} public int getPageCount(){return (int)values[1];} public void write(ImageOutputStream out)throws IOException{ writeIntArray(out,values); } } static public class SoftwareDE extends DE{ // 305 String name; public SoftwareDE(ImageInputStream in)throws IOException{ super(Software); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); name=readString(in)[0]; } } static public class DateTimeDE extends DE{ // 306 String datetime; public DateTimeDE(ImageInputStream in)throws IOException{ super(DateTime); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); datetime=readString(in)[0]; } } static public class ArtistDE extends DE{ // 315 String name; public ArtistDE(ImageInputStream in)throws IOException{ super(Artist); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); name=readString(in)[0]; } } static public class PredictorDE extends DE{ // 317 // 1 = No prediction scheme used before coding. // 2 = Horizontal differencing. public PredictorDE(ImageInputStream in)throws IOException{ super(Predictor);read(in); } public PredictorDE(int val)throws IOException{ super(Predictor);setType(SHORT);setCount(1);setValue(val); } static int getDefault(){return 1;} } static public class ColorMapDE extends DE{ // 320 private IndexColorModel cm=null; public ColorMapDE(ImageInputStream in)throws IOException{ super(ColorMap);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); long[] map=readIntArray(in); int len=map.length/3; byte[] r=new byte[len]; byte[] g=new byte[len]; byte[] b=new byte[len]; for(int i=0;i<len;i++){ r[i]=(byte)(map[i]&0x000000FF); // first all red g[i]=(byte)(map[len+i]&0x000000FF); // then all green b[i]=(byte)(map[len+len+i]&0x000000FF); // and blue } int bits=0,l=len; while(l>1){bits++;l>>>=1;} // System.out.println("9\bBITS+"+bits); cm=new IndexColorModel(bits,len,r,g,b); } public IndexColorModel getColorModel(){return cm;} /* public int getColor(int index){ // 3*(2^BitsPerSample) int r=(int)(map[index]&0x000000FF); // first all red int g=(int)(map[len+index]&0x000000FF); // then all green int b=(int)(map[len+len+index]&0x000000FF); // and blue int col=(r<<16)|(g<<8)|b; return col; } */ } static public class ExtraSamplesDE extends DE{ // 338 // ExtraSamples 338 SHORT ExtraSamples // read long[] exs; public ExtraSamplesDE(ImageInputStream in)throws IOException{ super(ExtraSamples); read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); exs=readIntArray(in); } public int getExtraSample(int index){return (int)exs[index];} public long[] getExtraSamples(){return exs;} // write public ExtraSamplesDE(int len)throws IOException{ super(ExtraSamples); exs=new long[len]; setType(SHORT); setCount(len); } public void setExtraSample(int index,long value){ exs[index]=value; } public void write(ImageOutputStream out)throws IOException{ writeIntArray(out,exs); } } static public class SampleFormatDE extends DE{ // 339 // 1 = unsigned integer data // 2 = two s complement signed integer data // 3 = IEEE floating point data [IEEE] // 4 = undefined data format public SampleFormatDE(ImageInputStream in)throws IOException{ super(SampleFormat);read(in); } public SampleFormatDE(int val)throws IOException{ super(SampleFormat);setType(SHORT);setCount(1);setValue(val); } static int getDefault(){return 1;} } static public class JPEGTablesDE extends DE{ // 347 // "When the JPEGTables field is present, it shall contain a valid JPEG // 'abbreviated table specification' datastream." // from TIFFTechNote2 private byte[] jpegsegment; // read public JPEGTablesDE(ImageInputStream in)throws IOException{ super(JPEGTables);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); jpegsegment=readByteArray(in); } public byte[] getData(){return jpegsegment;} // write public JPEGTablesDE(byte[] js)throws IOException{ super(JPEGTables);setType(UNDEFINED);setCount(js.length); this.jpegsegment=js; } public void write(ImageOutputStream out)throws IOException{ writeByteArray(out,jpegsegment); } } static public class YCbCrCoefficientsDE extends DE{ // 529 double[] coefficients=null; // read public YCbCrCoefficientsDE(ImageInputStream in)throws IOException{ super(YCbCrCoefficients);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); coefficients=readRealArray(in); } public double[] getCoefficients(){ return coefficients; } // write public YCbCrCoefficientsDE()throws IOException{ super(YCbCrCoefficients); coefficients=new double[3]; setType(RATIONAL); setCount(3); } public void setLumaRed (double value){coefficients[0]=value;} public void setLumaGreen(double value){coefficients[1]=value;} public void setLumaBlue (double value){coefficients[2]=value;} public void write(ImageOutputStream out)throws IOException{ writeRealArray(out,coefficients); } } static public class YCbCrSubSamplingDE extends DE{ // 530 long[] subSampling; // read public YCbCrSubSamplingDE(ImageInputStream in)throws IOException{ super(YCbCrSubSampling);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); subSampling=readIntArray(in); } public int getSubSampling(int index){return (int)subSampling[index];} public long[] getSubSampling(){return subSampling;} // write public YCbCrSubSamplingDE()throws IOException{ super(YCbCrSubSampling); subSampling=new long[2]; setType(SHORT); setCount(2); } public void setHoriz(int value){subSampling[0]=value;} public void setVert (int value){subSampling[1]=value;} public void write(ImageOutputStream out)throws IOException{ writeIntArray(out,subSampling); } } static public class YCbCrPositioningDE extends DE{ // 531 public YCbCrPositioningDE(ImageInputStream in)throws IOException{ super(YCbCrPositioning);read(in); } } static public class ReferenceBlackWhiteDE extends DE{ // 532 double[] reference; public ReferenceBlackWhiteDE(ImageInputStream in)throws IOException{ super(ReferenceBlackWhite);read(in); } public void read(ImageInputStream in)throws IOException{ super.read(in); reference=readRealArray(in); } public double getReference(int index){return (int)reference[index];} public double[] getReference(){return reference;} // write public ReferenceBlackWhiteDE()throws IOException{ super(ReferenceBlackWhite); reference=new double[6]; setType(RATIONAL); setCount(6); } public void setY (double black,double white){reference[0]=black;reference[1]=white;} public void setCb(double black,double white){reference[2]=black;reference[3]=white;} public void setCr(double black,double white){reference[4]=black;reference[5]=white;} public void write(ImageOutputStream out)throws IOException{ writeRealArray(out,reference); } } }