/** * Returns the number of image directories (subimages) stored in a given TIFF file, represented by * a <code>SeekableStream</code>. */ public static int getNumDirectories(SeekableStream stream) throws IOException { long pointer = stream.getFilePointer(); // Save stream pointer stream.seek(0L); int endian = stream.readUnsignedShort(); if (!isValidEndianTag(endian)) { throw new IllegalArgumentException("TIFFDirectory1"); } boolean isBigEndian = (endian == 0x4d4d); int magic = readUnsignedShort(stream, isBigEndian); if (magic != 42) { throw new IllegalArgumentException("TIFFDirectory2"); } stream.seek(4L); long offset = readUnsignedInt(stream, isBigEndian); int numDirectories = 0; while (offset != 0L) { ++numDirectories; stream.seek(offset); long entries = readUnsignedShort(stream, isBigEndian); stream.skipFully(12 * entries); offset = readUnsignedInt(stream, isBigEndian); } stream.seek(pointer); // Reset stream pointer return numDirectories; }
/** * Constructs a TIFFDirectory from a SeekableStream. The directory parameter specifies which * directory to read from the linked list present in the stream; directory 0 is normally read but * it is possible to store multiple images in a single TIFF file by maintaing multiple * directories. * * @param stream a SeekableStream to read from. * @param directory the index of the directory to read. */ public TIFFDirectory(SeekableStream stream, int directory) throws IOException { long global_save_offset = stream.getFilePointer(); long ifd_offset; // Read the TIFF header stream.seek(0L); int endian = stream.readUnsignedShort(); if (!isValidEndianTag(endian)) { throw new IllegalArgumentException("TIFFDirectory1"); } isBigEndian = (endian == 0x4d4d); int magic = readUnsignedShort(stream); if (magic != 42) { throw new IllegalArgumentException("TIFFDirectory2"); } // Get the initial ifd offset as an unsigned int (using a long) ifd_offset = readUnsignedInt(stream); for (int i = 0; i < directory; i++) { if (ifd_offset == 0L) { throw new IllegalArgumentException("TIFFDirectory3"); } stream.seek(ifd_offset); long entries = readUnsignedShort(stream); stream.skipFully(12 * entries); ifd_offset = readUnsignedInt(stream); } stream.seek(ifd_offset); initialize(stream); stream.seek(global_save_offset); }