Changeset 3269
- Timestamp:
- 10/11/07 15:17:49 (12 years ago)
- Location:
- trunk/loci/formats
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/loci/formats/TiffTools.java
r3268 r3269 55 55 public static final int BYTES_PER_ENTRY = 12; 56 56 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 57 60 // non-IFD tags (for internal use) 58 61 public static final int LITTLE_ENDIAN = 0; 59 public static final int VALID_BITS= 1;62 public static final int BIG_TIFF = 1; 60 63 61 64 // IFD types … … 193 196 // TIFF header constants 194 197 public static final int MAGIC_NUMBER = 42; 198 public static final int BIG_TIFF_MAGIC_NUMBER = 43; 195 199 public static final int LITTLE = 0x49; 196 200 public static final int BIG = 0x4d; … … 226 230 // check magic number (42) 227 231 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; 229 233 230 234 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(); 231 241 } 232 242 … … 250 260 if (result == null) return null; 251 261 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); 253 266 254 267 // compute maximum possible number of IFDs, for loop safety … … 260 273 Vector v = new Vector(); 261 274 for (long ifdNum=0; ifdNum<ifdMax; ifdNum++) { 262 Hashtable ifd = getIFD(in, ifdNum, offset );275 Hashtable ifd = getIFD(in, ifdNum, offset, bigTiff); 263 276 if (ifd == null || ifd.size() <= 1) break; 264 277 v.add(ifd); 265 offset = in.readInt();278 offset = bigTiff ? in.readLong() : in.readInt(); 266 279 if (offset <= 0 || offset >= in.length()) break; 267 280 } … … 362 375 throws IOException 363 376 { 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); 366 398 } 367 399 368 400 /** Gets the IFD stored at the given offset. */ 369 401 public static Hashtable getIFD(RandomAccessStream in, 370 long ifdNum, long offset ) throws IOException402 long ifdNum, long offset, boolean bigTiff) throws IOException 371 403 { 372 404 Hashtable ifd = new Hashtable(); … … 374 406 // save little-endian flag to internal LITTLE_ENDIAN tag 375 407 ifd.put(new Integer(LITTLE_ENDIAN), new Boolean(in.isLittleEndian())); 408 ifd.put(new Integer(BIG_TIFF), new Boolean(bigTiff)); 376 409 377 410 // read in directory entries for this IFD … … 380 413 } 381 414 in.seek(offset); 382 int numEntries =in.readShort() & 0xffff;415 long numEntries = bigTiff ? in.readLong() : in.readShort() & 0xffff; 383 416 if (DEBUG) debug("getIFDs: " + numEntries + " directory entries to read"); 384 417 if (numEntries == 0 || numEntries == 1) return ifd; 385 418 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 386 423 for (int i=0; i<numEntries; i++) { 387 in.seek(offset + 2 + BYTES_PER_ENTRY* i);424 in.seek(offset + baseOffset + bytesPerEntry * i); 388 425 int tag = in.readShort() & 0xffff; 389 426 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(); 391 429 392 430 if (DEBUG) { … … 399 437 if (type == BYTE) { 400 438 // 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(); 403 441 in.seek(pointer); 404 442 } … … 417 455 // the last byte must be NUL (binary zero) 418 456 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(); 421 459 in.seek(pointer); 422 460 } … … 449 487 else if (type == SHORT) { 450 488 // 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(); 453 491 in.seek(pointer); 454 492 } … … 464 502 else if (type == LONG) { 465 503 // 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(); 468 506 in.seek(pointer); 469 507 } … … 480 518 // Two SLONG's: the first represents the numerator of a fraction, 481 519 // the second the denominator 482 long pointer = in.readInt();520 long pointer = bigTiff ? in.readLong() : in.readInt(); 483 521 in.seek(pointer); 484 522 if (count == 1) value = new TiffRational(in.readInt(), in.readInt()); … … 495 533 // UNDEFINED: An 8-bit byte that may contain anything, 496 534 // 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(); 499 537 in.seek(pointer); 500 538 } … … 508 546 else if (type == SSHORT) { 509 547 // 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(); 512 550 in.seek(pointer); 513 551 } … … 521 559 else if (type == SLONG) { 522 560 // 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(); 525 563 in.seek(pointer); 526 564 } … … 534 572 else if (type == FLOAT) { 535 573 // 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(); 538 576 in.seek(pointer); 539 577 } … … 547 585 else if (type == DOUBLE) { 548 586 // Double precision (8-byte) IEEE format 549 long pointer = in.readInt();587 long pointer = bigTiff ? in.readLong() : in.readInt(); 550 588 in.seek(pointer); 551 589 if (count == 1) value = new Double(in.readDouble()); … … 560 598 if (value != null) ifd.put(new Integer(tag), value); 561 599 } 562 in.seek(offset + 2 + BYTES_PER_ENTRY* numEntries);600 in.seek(offset + baseOffset + bytesPerEntry * numEntries); 563 601 564 602 return ifd; … … 1051 1089 1052 1090 // 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 //} 1056 1094 1057 1095 // use special color map for YCbCr -
trunk/loci/formats/in/NikonReader.java
r3197 r3269 275 275 276 276 Hashtable realImage = TiffTools.getIFD(in, 1, offset); 277 realImage.put(new Integer(TiffTools.VALID_BITS), new int[] {12, 12, 12});278 277 279 278 original = ifds[0];
Note: See TracChangeset
for help on using the changeset viewer.