package uk.co.mmscomputing.imageio.tiff; import java.io.*; import java.util.*; import java.awt.image.*; import javax.imageio.stream.*; class IFD extends Vector implements TIFFConstants{ // Image File Directory public IFD(){ } public long read(ImageInputStream in, long pos)throws IOException{ in.seek(pos); int len=in.readUnsignedShort(); // no of entries for(int i=0;i<len;i++){ add(DEFactory.read(in)); // directory entries } return in.readUnsignedInt(); // offset to next IFD or 0 } public DE getDE(int tag){ Enumeration e=elements(); while(e.hasMoreElements()){ DE de=((DE)e.nextElement()); if(tag==de.getTag()){ return de; } } throw new IllegalArgumentException(getClass().getName()+"getIntValue:\n\tIFD does not feature DE with Tag "+tag); } public long getIntValue(int tag){ DE de=getDE(tag); if(de.getCount()!=1){ // check for type not implemented throw new IllegalArgumentException(getClass().getName()+"getIntValue:\n\tExpect Count=1 for Tag "+tag); } return de.getValue(); } public int getNewSubfileType(){ // 254 try{ return (int)getIntValue(NewSubfileType); }catch(IllegalArgumentException iae){ return DEFactory.NewSubfileTypeDE.getDefault(); } } public int getWidth(){ // 256 return (int)getIntValue(ImageWidth); } public int getHeight(){ // 257 return (int)getIntValue(ImageLength); } public int getLength(){ // 257 return (int)getIntValue(ImageLength); } public int getBitsPerSample(int index){ try{ return ((DEFactory.BitsPerSampleDE)getDE(BitsPerSample)).getBits(index); }catch(IllegalArgumentException iae){ return 1; // default: 1 } } public long[] getBitsPerSample(){ try{ return ((DEFactory.BitsPerSampleDE)getDE(BitsPerSample)).getBits(); }catch(IllegalArgumentException iae){ long[] bitsPerSample=new long[1]; bitsPerSample[0]=1; return bitsPerSample; // default: 1 } } public int getCompression(){ // 259 try{ return (int)getIntValue(Compression); }catch(IllegalArgumentException iae){ return 1; // default: no compression } } public int getPhotometricInterpretation(){ // 262 try{ return (int)getIntValue(PhotometricInterpretation); }catch(IllegalArgumentException iae){ return 1; // default: black is zero } } public int getFillOrder(){ // 266 try{ return (int)getIntValue(FillOrder); }catch(IllegalArgumentException iae){ return 1; // default: 1 = pixel with low column value => high bits } } public int getSamplesPerPixel(){ // 277 try{ return (int)getIntValue(SamplesPerPixel); }catch(IllegalArgumentException iae){ return 1; // default: 1 } } public int getRowsPerStrip(){ // 278 return (int)getIntValue(RowsPerStrip); } public DEFactory.ColorMapDE getColorMap(){ // 320 return (DEFactory.ColorMapDE)getDE(ColorMap); } public IndexColorModel getColorModel(){ // 320 return ((DEFactory.ColorMapDE)getDE(ColorMap)).getColorModel(); } public int getExtraSamplesLength(){ // 338 try{ return ((DEFactory.ExtraSamplesDE)getDE(ExtraSamples)).getExtraSamples().length; }catch(IllegalArgumentException iae){ return 0; // default: 0; no extra samples } } public int getExtraSample(int index){ // 338 return ((DEFactory.ExtraSamplesDE)getDE(ExtraSamples)).getExtraSample(index); } public int getSampleFormat(){ // 339 try{ return (int)getIntValue(SampleFormat); }catch(IllegalArgumentException iae){ return DEFactory.SampleFormatDE.getDefault(); } } public byte[] getJPEGTables(){ // 347 return ((DEFactory.JPEGTablesDE)getDE(JPEGTables)).getData(); } public int getT4Options(){ // required, if compression=3 (rfc2306 p.9) try{ return (int)getIntValue(T4Options); }catch(IllegalArgumentException iae){ return 0; // default: 1-dimensional MH, non-byte aligned } } public int getT6Options(){ // required, if compression=4 (rfc2306 p.??) try{ return (int)getIntValue(T4Options); }catch(IllegalArgumentException iae){ return 0; // default: 2-dimensional MMR, compressed } } public int getPlanarConfiguration(){ try{ return (int)getIntValue(PlanarConfiguration); }catch(IllegalArgumentException iae){ return 1; // default: chunky format } } public int getResolutionUnit(){ try{ return (int)getIntValue(ResolutionUnit); }catch(IllegalArgumentException iae){ return 2; // default: inch } } public long[] getStripOffsets(){ return ((DEFactory.StripOffsetsDE)getDE(StripOffsets)).getOffsets();} public long[] getStripByteCounts(){ return ((DEFactory.StripByteCountsDE)getDE(StripByteCounts)).getCounts();} public int getPredictor(){ try{ return (int)getIntValue(Predictor); }catch(IllegalArgumentException iae){ return DEFactory.PredictorDE.getDefault(); } } public double[] getYCbCrCoefficients(){ try{ return ((DEFactory.YCbCrCoefficientsDE)getDE(YCbCrCoefficients)).getCoefficients(); }catch(IllegalArgumentException iae){ double[] coeffs={299/1000,587/1000,114/1000}; return coeffs; } } public long[] getYCbCrSubSampling(){ try{ return ((DEFactory.YCbCrSubSamplingDE)getDE(YCbCrSubSampling)).getSubSampling(); }catch(IllegalArgumentException iae){ long[] ss={2,2}; return ss; } } public int getYCbCrPositioning(){ try{ return (int)getIntValue(YCbCrPositioning); }catch(IllegalArgumentException iae){ return 1; // default: centered } } public double[] getReferenceBlackWhite(){ try{ return ((DEFactory.ReferenceBlackWhiteDE)getDE(ReferenceBlackWhite)).getReference(); }catch(IllegalArgumentException iae){ long[] bps=getBitsPerSample(); double[] reference={0,(1<<bps[0])-1,0,(1<<bps[1])-1,0,(1<<bps[2])-1}; return reference; // default: [0/,NV/1, 0/1, NV/1, 0/1, NV/1] where NV = 2 ** BitsPerSample - 1. } } public long write(ImageOutputStream out, long lastIfdPosPtr)throws IOException{ Enumeration e;DE de; // Write content of IFD tags e=elements(); while(e.hasMoreElements()){ de=((DE)e.nextElement()); de.write(out); // write content if > 4 bytes save stream position to val } // Write IFD long pos=out.getStreamPosition(); while((pos%4)!=0){ // align to 32-bit boundary out.write(0);pos++; } out.mark(); out.seek(lastIfdPosPtr); // offset position for ptr to new ifd out.writeInt((int)pos); // set ifd offset to this ifd stream position out.reset(); int len=size(); out.writeShort(len); // no of entries e=elements(); while(e.hasMoreElements()){ de=((DE)e.nextElement()); de.writeEntry(out); // write value/address to content } pos=out.getStreamPosition(); // offset position for ptr to new ifd. (ifd linked list) out.writeInt(0); // no new ifd yet return pos; } }