Changeset 3269


Ignore:
Timestamp:
10/11/07 15:17:49 (12 years ago)
Author:
melissa
Message:

Initial implementation of BigTIFF.

Location:
trunk/loci/formats
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/TiffTools.java

    r3268 r3269  
    5555  public static final int BYTES_PER_ENTRY = 12; 
    5656 
     57  /** The number of bytes in each IFD entry of a BigTIFF file. */ 
     58  public static final int BIG_TIFF_BYTES_PER_ENTRY = 20; 
     59 
    5760  // non-IFD tags (for internal use) 
    5861  public static final int LITTLE_ENDIAN = 0; 
    59   public static final int VALID_BITS = 1; 
     62  public static final int BIG_TIFF = 1; 
    6063 
    6164  // IFD types 
     
    193196  // TIFF header constants 
    194197  public static final int MAGIC_NUMBER = 42; 
     198  public static final int BIG_TIFF_MAGIC_NUMBER = 43; 
    195199  public static final int LITTLE = 0x49; 
    196200  public static final int BIG = 0x4d; 
     
    226230    // check magic number (42) 
    227231    short magic = DataTools.bytesToShort(block, 2, littleEndian); 
    228     if (magic != MAGIC_NUMBER) return null; 
     232    if (magic != MAGIC_NUMBER && magic != BIG_TIFF_MAGIC_NUMBER) return null; 
    229233 
    230234    return new Boolean(littleEndian); 
     235  } 
     236 
     237  /** Gets whether this is a BigTIFF IFD. */ 
     238  public static boolean isBigTiff(Hashtable ifd) throws FormatException { 
     239    return ((Boolean) 
     240      getIFDValue(ifd, BIG_TIFF, false, Boolean.class)).booleanValue(); 
    231241  } 
    232242 
     
    250260    if (result == null) return null; 
    251261 
    252     long offset = getFirstOffset(in); 
     262    in.seek(2); 
     263    boolean bigTiff = in.readShort() == BIG_TIFF_MAGIC_NUMBER; 
     264 
     265    long offset = getFirstOffset(in, bigTiff); 
    253266 
    254267    // compute maximum possible number of IFDs, for loop safety 
     
    260273    Vector v = new Vector(); 
    261274    for (long ifdNum=0; ifdNum<ifdMax; ifdNum++) { 
    262       Hashtable ifd = getIFD(in, ifdNum, offset); 
     275      Hashtable ifd = getIFD(in, ifdNum, offset, bigTiff); 
    263276      if (ifd == null || ifd.size() <= 1) break; 
    264277      v.add(ifd); 
    265       offset = in.readInt(); 
     278      offset = bigTiff ? in.readLong() : in.readInt(); 
    266279      if (offset <= 0 || offset >= in.length()) break; 
    267280    } 
     
    362375    throws IOException 
    363376  { 
    364     // get offset to first IFD 
    365     return in.readInt(); 
     377    return getFirstOffset(in, false); 
     378  } 
     379 
     380  /** 
     381   * Gets offset to the first IFD, or -1 if stream is not TIFF. 
     382   * Assumes the stream is positioned properly (checkHeader just called). 
     383   *  
     384   * @param bigTiff true if this is a BigTIFF file (8 byte pointers). 
     385   */ 
     386  public static long getFirstOffset(RandomAccessStream in, boolean bigTiff) 
     387    throws IOException 
     388  { 
     389    if (bigTiff) in.skipBytes(4); 
     390    return bigTiff ? in.readLong() : in.readInt(); 
     391  } 
     392 
     393  /** Gets the IFD stored at the given offset. */ 
     394  public static Hashtable getIFD(RandomAccessStream in, long ifdNum, 
     395    long offset) throws IOException 
     396  { 
     397    return getIFD(in, ifdNum, offset, false); 
    366398  } 
    367399 
    368400  /** Gets the IFD stored at the given offset. */ 
    369401  public static Hashtable getIFD(RandomAccessStream in, 
    370     long ifdNum, long offset) throws IOException 
     402    long ifdNum, long offset, boolean bigTiff) throws IOException 
    371403  { 
    372404    Hashtable ifd = new Hashtable(); 
     
    374406    // save little-endian flag to internal LITTLE_ENDIAN tag 
    375407    ifd.put(new Integer(LITTLE_ENDIAN), new Boolean(in.isLittleEndian())); 
     408    ifd.put(new Integer(BIG_TIFF), new Boolean(bigTiff)); 
    376409 
    377410    // read in directory entries for this IFD 
     
    380413    } 
    381414    in.seek(offset); 
    382     int numEntries = in.readShort() & 0xffff; 
     415    long numEntries = bigTiff ? in.readLong() : in.readShort() & 0xffff; 
    383416    if (DEBUG) debug("getIFDs: " + numEntries + " directory entries to read"); 
    384417    if (numEntries == 0 || numEntries == 1) return ifd; 
    385418 
     419    int bytesPerEntry = bigTiff ? BIG_TIFF_BYTES_PER_ENTRY : BYTES_PER_ENTRY; 
     420    int baseOffset = bigTiff ? 8 : 2; 
     421    int threshhold = bigTiff ? 8 : 4; 
     422 
    386423    for (int i=0; i<numEntries; i++) { 
    387       in.seek(offset + 2 + BYTES_PER_ENTRY * i); 
     424      in.seek(offset + baseOffset + bytesPerEntry * i); 
    388425      int tag = in.readShort() & 0xffff; 
    389426      int type = in.readShort() & 0xffff; 
    390       int count = in.readInt(); 
     427      // BigTIFF case is a slight hack 
     428      int count = bigTiff ? (int) (in.readLong() & 0xffffffff) : in.readInt(); 
    391429 
    392430      if (DEBUG) { 
     
    399437      if (type == BYTE) { 
    400438        // 8-bit unsigned integer 
    401         if (count > 4) { 
    402           long pointer = in.readInt(); 
     439        if (count > threshhold) { 
     440          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    403441          in.seek(pointer); 
    404442        } 
     
    417455        // the last byte must be NUL (binary zero) 
    418456        byte[] ascii = new byte[count]; 
    419         if (count > 4) { 
    420           long pointer = in.readInt(); 
     457        if (count > threshhold) { 
     458          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    421459          in.seek(pointer); 
    422460        } 
     
    449487      else if (type == SHORT) { 
    450488        // 16-bit (2-byte) unsigned integer 
    451         if (count > 2) { 
    452           long pointer = in.readInt(); 
     489        if (count > threshhold / 2) { 
     490          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    453491          in.seek(pointer); 
    454492        } 
     
    464502      else if (type == LONG) { 
    465503        // 32-bit (4-byte) unsigned integer 
    466         if (count > 1) { 
    467           long pointer = in.readInt(); 
     504        if (count > threshhold / 4) { 
     505          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    468506          in.seek(pointer); 
    469507        } 
     
    480518        // Two SLONG's: the first represents the numerator of a fraction, 
    481519        // the second the denominator 
    482         long pointer = in.readInt(); 
     520        long pointer = bigTiff ? in.readLong() : in.readInt(); 
    483521        in.seek(pointer); 
    484522        if (count == 1) value = new TiffRational(in.readInt(), in.readInt()); 
     
    495533        // UNDEFINED: An 8-bit byte that may contain anything, 
    496534        // depending on the definition of the field 
    497         if (count > 4) { 
    498           long pointer = in.readInt(); 
     535        if (count > threshhold) { 
     536          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    499537          in.seek(pointer); 
    500538        } 
     
    508546      else if (type == SSHORT) { 
    509547        // A 16-bit (2-byte) signed (twos-complement) integer 
    510         if (count > 2) { 
    511           long pointer = in.readInt(); 
     548        if (count > threshhold / 2) { 
     549          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    512550          in.seek(pointer); 
    513551        } 
     
    521559      else if (type == SLONG) { 
    522560        // A 32-bit (4-byte) signed (twos-complement) integer 
    523         if (count > 1) { 
    524           long pointer = in.readInt(); 
     561        if (count > threshhold / 4) { 
     562          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    525563          in.seek(pointer); 
    526564        } 
     
    534572      else if (type == FLOAT) { 
    535573        // Single precision (4-byte) IEEE format 
    536         if (count > 1) { 
    537           long pointer = in.readInt(); 
     574        if (count > threshhold / 4) { 
     575          long pointer = bigTiff ? in.readLong() : in.readInt(); 
    538576          in.seek(pointer); 
    539577        } 
     
    547585      else if (type == DOUBLE) { 
    548586        // Double precision (8-byte) IEEE format 
    549         long pointer = in.readInt(); 
     587        long pointer = bigTiff ? in.readLong() : in.readInt(); 
    550588        in.seek(pointer); 
    551589        if (count == 1) value = new Double(in.readDouble()); 
     
    560598      if (value != null) ifd.put(new Integer(tag), value); 
    561599    } 
    562     in.seek(offset + 2 + BYTES_PER_ENTRY * numEntries); 
     600    in.seek(offset + baseOffset + bytesPerEntry * numEntries); 
    563601 
    564602    return ifd; 
     
    10511089 
    10521090    // If the subsequent color maps are empty, use the first IFD's color map 
    1053     if (colorMap == null) { 
    1054       colorMap = getIFDIntArray(getFirstIFD(in), COLOR_MAP, false); 
    1055     } 
     1091    //if (colorMap == null) { 
     1092    //  colorMap = getIFDIntArray(getFirstIFD(in), COLOR_MAP, false); 
     1093    //} 
    10561094 
    10571095    // use special color map for YCbCr 
  • trunk/loci/formats/in/NikonReader.java

    r3197 r3269  
    275275 
    276276    Hashtable realImage = TiffTools.getIFD(in, 1, offset); 
    277     realImage.put(new Integer(TiffTools.VALID_BITS), new int[] {12, 12, 12}); 
    278277 
    279278    original = ifds[0]; 
Note: See TracChangeset for help on using the changeset viewer.