Changeset 1213


Ignore:
Timestamp:
08/02/06 17:04:56 (14 years ago)
Author:
curtis
Message:

Fix some endianness bugs, and some bugs in overwriteIFDValue (but still buggy).

Location:
trunk/loci/formats
Files:
2 edited

Legend:

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

    r1195 r1213  
    4949  protected static final int RAF = 1; 
    5050  protected static final int ARRAY = 2; 
    51  
    5251 
    5352  // -- Fields -- 
     
    108107  } 
    109108 
     109  // -- RandomAccessStream API methods -- 
     110 
     111  /** Seeks to the given offset within the stream. */ 
     112  public void seek(long pos) throws IOException { afp = (int) pos; } 
     113 
     114  /** Alias for readByte(). */ 
     115  public int read() throws IOException { return (int) readByte(); } 
     116 
     117  /** Gets the number of bytes in the file. */ 
     118  public long length() throws IOException { return raf.length(); } 
     119 
     120  /** Gets the current (absolute) file pointer. */ 
     121  public int getFilePointer() { return afp; } 
     122 
     123  /** Closes the streams. */ 
     124  public void close() throws IOException { 
     125    if (raf != null) raf.close(); 
     126    raf = null; 
     127    if (dis != null) dis.close(); 
     128    dis = null; 
     129    fp = 0; 
     130    mark = 0; 
     131  } 
     132 
     133  /** Sets the endianness of the stream. */ 
     134  public void order(boolean little) { littleEndian = little; } 
     135 
     136  /** Gets the endianness of the stream. */ 
     137  public boolean isLittleEndian() { return littleEndian; } 
    110138 
    111139  // -- DataInput API methods -- 
     
    283311    afp += n; 
    284312    if (status == DIS) fp += n; 
    285   } 
    286  
    287  
    288   // -- Internal RandomAccessStream API methods -- 
    289  
    290   /** Seek to the given offset within the stream. */ 
    291   public void seek(long pos) throws IOException { 
    292     afp = (int) pos; 
    293   } 
    294  
    295   /** Alias for readByte(). */ 
    296   public int read() throws IOException { 
    297     return (int) readByte(); 
    298   } 
    299  
    300   /** Get the number of bytes in the file. */ 
    301   public long length() throws IOException { 
    302     return raf.length(); 
    303   } 
    304  
    305   /** Get the current (absolute) file pointer. */ 
    306   public int getFilePointer() { 
    307     return afp; 
    308   } 
    309  
    310   /** Close the streams. */ 
    311   public void close() throws IOException { 
    312     if (raf != null) raf.close(); 
    313     raf = null; 
    314     if (dis != null) dis.close(); 
    315     dis = null; 
    316     fp = 0; 
    317     mark = 0; 
    318   } 
    319  
    320   /** Set the endianness of the stream. */ 
    321   public void order(boolean little) { 
    322     littleEndian = little; 
    323313  } 
    324314 
  • trunk/loci/formats/TiffTools.java

    r1212 r1213  
    188188   */ 
    189189  public static boolean isValidHeader(byte[] block) { 
    190     if (block.length < 4) { return false; } 
     190    return checkHeader(block) != null; 
     191  } 
     192 
     193  /** 
     194   * Checks the TIFF header. 
     195   * @return true if little-endian, 
     196   *         false if big-endian, 
     197   *         or null if not a TIFF. 
     198   */ 
     199  public static Boolean checkHeader(byte[] block) { 
     200    if (block.length < 4) return null; 
    191201 
    192202    // byte order must be II or MM 
    193203    boolean littleEndian = block[0] == LITTLE && block[1] == LITTLE; // II 
    194204    boolean bigEndian = block[0] == BIG && block[1] == BIG; // MM 
    195     if (!littleEndian && !bigEndian) return false; 
     205    if (!littleEndian && !bigEndian) return null; 
    196206 
    197207    // check magic number (42) 
    198208    short magic = DataTools.bytesToShort(block, 2, littleEndian); 
    199     return magic == MAGIC_NUMBER; 
     209    if (magic != MAGIC_NUMBER) return null; 
     210 
     211    return new Boolean(littleEndian); 
    200212  } 
    201213 
     
    229241    Boolean result = checkHeader(in, globalOffset); 
    230242    if (result == null) return null; 
    231     boolean littleEndian = result.booleanValue(); 
    232  
    233     long offset = getFirstOffset(in, littleEndian); 
     243 
     244    long offset = getFirstOffset(in); 
    234245 
    235246    // compute maximum possible number of IFDs, for loop safety 
     
    241252    Vector v = new Vector(); 
    242253    for (long ifdNum=0; ifdNum<ifdMax; ifdNum++) { 
    243       Hashtable ifd = getIFD(in, ifdNum, globalOffset, offset, littleEndian); 
     254      Hashtable ifd = getIFD(in, ifdNum, globalOffset, offset); 
    244255      if (ifd.size() <= 1) break; 
    245256      v.add(ifd); 
     
    272283    Boolean result = checkHeader(in, globalOffset); 
    273284    if (result == null) return null; 
    274     boolean littleEndian = result.booleanValue(); 
    275  
    276     long offset = getFirstOffset(in, littleEndian); 
    277  
    278     return getIFD(in, 0, globalOffset, offset, littleEndian); 
     285 
     286    long offset = getFirstOffset(in); 
     287 
     288    return getIFD(in, 0, globalOffset, offset); 
    279289  } 
    280290 
     
    293303    in.seek((int) globalOffset); 
    294304 
    295     // determine byte order (II = little-endian, MM = big-endian) 
    296     byte[] order = new byte[2]; 
    297     in.read(order); 
    298     boolean littleEndian = order[0] == LITTLE && order[1] == LITTLE; // II 
    299     boolean bigEndian = order[0] == BIG && order[1] == BIG; // MM 
    300     if (!littleEndian && !bigEndian) return null; 
    301  
    302     // check magic number (42) 
    303     int magic = in.readShort(); 
    304     if (magic != MAGIC_NUMBER) return null; 
    305  
    306     return new Boolean(littleEndian); 
     305    byte[] header = new byte[4]; 
     306    in.readFully(header); 
     307    Boolean b = checkHeader(header); 
     308    if (b != null) in.order(b.booleanValue()); 
     309    return b; 
    307310  } 
    308311 
     
    311314   * Assumes the stream is positioned properly (checkHeader just called). 
    312315   */ 
    313   public static long getFirstOffset(RandomAccessStream in, boolean littleEndian) 
     316  public static long getFirstOffset(RandomAccessStream in) 
    314317    throws IOException 
    315318  { 
     
    320323  /** Gets the IFD stored at the given offset. */ 
    321324  public static Hashtable getIFD(RandomAccessStream in, 
    322     long ifdNum, long globalOffset, long offset, boolean littleEndian) 
    323     throws IOException 
     325    long ifdNum, long globalOffset, long offset) throws IOException 
    324326  { 
    325327    Hashtable ifd = new Hashtable(); 
    326328 
    327329    // save little-endian flag to internal LITTLE_ENDIAN tag 
    328     ifd.put(new Integer(LITTLE_ENDIAN), new Boolean(littleEndian)); 
     330    ifd.put(new Integer(LITTLE_ENDIAN), new Boolean(in.isLittleEndian())); 
    329331 
    330332    // read in directory entries for this IFD 
     
    728730    // get internal non-IFD entries 
    729731    boolean littleEndian = isLittleEndian(ifd); 
     732    in.order(littleEndian); 
    730733 
    731734    // get relevant IFD entries 
     
    16701673    } 
    16711674    boolean little = header[0] == LITTLE && header[1] == LITTLE; // II 
    1672     int offset = 4; // offset to the IFD 
    1673     short num = 0; // number of directory entries 
     1675    long offset = 4; // offset to the IFD 
     1676    int num = 0; // number of directory entries 
    16741677 
    16751678    // skip to the correct IFD 
    16761679    for (int i=0; i<=ifd; i++) { 
    1677       offset = raf.readInt(); 
     1680      offset = DataTools.read4UnsignedBytes(raf, little); 
    16781681      if (offset <= 0) { 
    16791682        throw new FormatException("No such IFD (" + ifd + " of " + i + ")"); 
    16801683      } 
    16811684      raf.seek(offset); 
    1682       num = raf.readShort(); 
     1685      num = DataTools.read2UnsignedBytes(raf, little); 
    16831686      if (i < ifd) raf.seek(offset + 2 + 12 * num); 
    16841687    } 
     
    17171720          if (DEBUG) debug("overwriteIFDValue: new entry is <= old entry"); 
    17181721        } 
    1719         else if (oldOffset + BYTES_PER_ELEMENT[oldTag] == raf.length()) { 
     1722        else if (oldOffset + BYTES_PER_ELEMENT[oldType] == raf.length()) { 
    17201723          // old entry was already at EOF; overwrite it 
    17211724          newOffset = oldOffset; 
     
    17371740          raf.write(extra); 
    17381741        } 
     1742        return; 
    17391743      } 
    17401744    } 
Note: See TracChangeset for help on using the changeset viewer.