Class TIFFCodec

All Implemented Interfaces:
TIFFConstants

public class TIFFCodec extends ImageCodec implements TIFFConstants
A codec to read Tagged Image File Format (TIFF) image files.

Usage example

Load an image from a TIFF file.
 TIFFCodec codec = new TIFFCodec();
 codec.setFile("image.tif", CodecMode.LOAD);
 codec.process();
 PixelImage loadedImage = codec.getImage();
 
Saving images is not supported by this codec.

Compression types

Reading

The TIFF package supports the following compression types when reading:
  • Uncompressed. Compression method number 1. Works with all types of image data. See TIFFDecoderUncompressed.
  • Packbits. Compression method number 32773. Works with all types of image data. See TIFFDecoderPackbits.
  • CCITT Group 3 1-Dimensional Modified Huffman runlength encoding. Compression method number 2. Works with bilevel image data only. See TIFFDecoderModifiedHuffman.
  • Deflated. Compression method number 8 or 32946. Works with all types of image data. See TIFFDecoderDeflated.
  • LogLuv RLE and LogLuv 24. Compression method numbers 34676 and 34677. Works only with LogLuv color data. See TIFFDecoderLogLuv.

Note that you can write your own decoder (extending TIFFDecoder) for any compression type you want.

Image types

Reading

The TIFF package supports the following image / color types when reading:
  • Black & white. JIU image data type BilevelImage.
  • Grayscale, 4 and 8 bits per pixel. JIU image data type Gray8Image.
  • TODO add other image types

Note that you can write your own decoder (extending TIFFDecoder) for any compression type you want.

Writing

Writing TIFFs is not supported. I don't know if or when it will be supported.

Strips and tiles

The early versions of TIFF considered an image to be a sequence of strips. Each strip was a rectangular part of the image, as wide as the complete image, and with a certain height defined by the rows per strip tag. So with a number of rows per strip of 10, and an image height of 200, you would have to store 20 strips. It was recommended that a strip should not be larger than 8 KB (RAM was tighter in those days). The rule of thumb to define the number of rows per strip was to see how many rows would fit into 8 KB.

Later, the concept of tiles was added to the TIFF specs. Tiled TIFFs are separated into rectangles that not only had a defineable height but also a defineable width (tile width and tile height are also stored in corresponding tags).

Obviously, strips are just a special case of tiles, with the tile width being equal to image width. That is why JIU internally only deals with tiles. The only difference: No row padding takes place for strips. In a tiled image with a tile height of 10 and an image height of 14, the image is two tiles high.

Number of images

TIFF allows for multiple images in a single file. This codec regards the image index, queries ImageCodec.getImageIndex() and skips to the correct image.

Bounds

The bounds concept of JIU is supported by this codec. So you can specify bounds of a rectangular part of an image that you want to load instead of loading the complete image.

Color spaces

The following color spaces are understood when reading truecolor TIFF files.
  • RGB - should cover most truecolor files.
  • CMYK - is supported, but colors may not be exactly right. CMYK data is converted to RGB on the fly, so the codec user never accesses CMYK data.
  • LogLuv - is supported, but not all flavors yet.

Physical resolution

DPI information can be stored in TIFF files. If that information is available, this codec retrieves it so that it can be queried using ImageCodec.getDpiX() and ImageCodec.getDpiY().

Background information on TIFF

TIFF is an important image file format for DTP (desktop publishing). The advantages of TIFF include its flexibility, availability of libraries to read and write TIFF files and its good support in existing software. The major disadvantage of TIFF is its complexity, which makes it hard for software to support all possible valid TIFF files.

TIFF was created by Aldus and now belongs to Adobe, who offer a specification document: TIFF (Tagged Image File Format) 6.0 Specification (updated on Web September, 20 1995, document dated June, 3 1992) (PDF: 385 KB / 121 pages).

Other good references include the homepage of libtiff, a free C library to read and write TIFF files and The Unofficial TIFF homepage by Niles Ritter. Also see the TIFF section of the Open Directory.

TIFF is used for various specialized tasks. As an example, see GeoTIFF (geographical data) or EXIF (digital camera metadata; this is actually a TIFF directory embedded in a JPEG header).

Here's a list of features that make TIFF quite complex:

  • More than one image can be stored in a TIFF file.
  • Integer values that are larger than one byte can be in either little or big endian byte order.
  • Various color types are supported (bilevel, gray, paletted, all kinds of color spaces (RGB / YCbCr / CMYK). It's easy to add new color types, so this list can grow.
  • The meta data (information that describes the image and how it is stored) can be distributed all over the file.
  • Image data is stored as packed bytes, 4-bit-nibbles, bytes and 16-bit-integers. Other types are possible as well.
  • Various compression types are supported; not all types can be used on all color types.
  • Image data can be stored in strips or tiles.
  • An arbitrary number of non-image-data samples can stored within the image data.
  • Color types with more than one sample per pixel can store data in an interleaved (chunky) way or in planes.
  • Different ways of defining black and white are possible with bilevel and grayscale images.
Author:
Marco Schmidt
  • Field Details

    • BYTE_ORDER_MOTOROLA

      public static final int BYTE_ORDER_MOTOROLA
      See Also:
    • BYTE_ORDER_INTEL

      public static final int BYTE_ORDER_INTEL
      See Also:
    • MAGIC_INTEL

      private static final int MAGIC_INTEL
      See Also:
    • MAGIC_MOTOROLA

      private static final int MAGIC_MOTOROLA
      See Also:
    • byteOrder

      private int byteOrder
    • nextIfdOffset

      private int nextIfdOffset
    • decoders

      private static Hashtable decoders
  • Constructor Details

    • TIFFCodec

      public TIFFCodec()
  • Method Details

    • adjustInt

      private int adjustInt(int value, int type)
      If the current byte order is BYTE_ORDER_MOTOROLA and the type argument is TiffConstants.TAG_TYPE_BYTE or TiffConstants.TAG_TYPE_SHORT, the value parameter must be adjusted by some bitshifting. If the above mentioned criteria are not met, the value argument is returned without any modifications.

      Why this is necessary remains a mystery to me. Marco

      Parameters:
      value - the int value which may have to be adjusted
      Returns:
      the value parameter which may have been modified
    • createDecoder

      private static TIFFDecoder createDecoder(TIFFCodec codec, TIFFImageFileDirectory ifd, int tileIndex) throws IOException, UnsupportedTypeException
      Throws:
      IOException
      UnsupportedTypeException
    • getByteOrder

      public int getByteOrder()
      Returns the current byte order, either BYTE_ORDER_INTEL or BYTE_ORDER_MOTOROLA.
      Returns:
      current byte order
    • getFormatName

      public String getFormatName()
      Description copied from class: ImageCodec
      Returns the name of the file format supported by this codec. All classes extending ImageCodec must override this method. When overriding, leave out any words in a particular language so that this format name can be understood by everyone. Usually it is enough to return the format creator plus a typical abbreviation, e.g. Microsoft BMP or Portable Anymap (PNM).
      Specified by:
      getFormatName in class ImageCodec
      Returns:
      name of the file format supported by this codec
    • getMimeTypes

      public String[] getMimeTypes()
      Description copied from class: ImageCodec
      Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, or null if none are available.
      Specified by:
      getMimeTypes in class ImageCodec
      Returns:
      MIME type strings or null
    • getTagName

      public static String getTagName(int id)
      Returns the name of a tag in English.
      Parameters:
      id - of the tag for which a name is to be returned
      Returns:
      tag name as String or a question mark ?
    • isLoadingSupported

      public boolean isLoadingSupported()
      Description copied from class: ImageCodec
      Returns if this codec is able to load images in the file format supported by this codec. If true is returned this does not necessarily mean that all files in this format can be read, but at least some.
      Specified by:
      isLoadingSupported in class ImageCodec
      Returns:
      if loading is supported
    • isSavingSupported

      public boolean isSavingSupported()
      Description copied from class: ImageCodec
      Returns if this codec is able to save images in the file format supported by this codec. If true is returned this does not necessarily mean that all types files in this format can be written, but at least some.
      Specified by:
      isSavingSupported in class ImageCodec
      Returns:
      if saving is supported
    • load

      Attempts to load an image from a file in the TIFF format. Some options can be given to this codec before the call to this load method.
      • You must provide a RandomAccessFile using #setInput(java.io.RandomAccessFile).
      • If there is more than one image in the input file, you can make the codec load it by calling ImageCodec.setImageIndex(int). The argument is the index of the image, the first being 0, the second 1 and so on. The default is 0.
      Throws:
      InvalidFileStructureException - if the TIFF file was corrupt in some way
      IOException - if there were errors reading from the input file
      UnsupportedTypeException - if the flavour of TIFF encountered in the input file is not supported yet
      WrongFileFormatException
      WrongParameterException
    • load

      Throws:
      InvalidFileStructureException
      IOException
      UnsupportedTypeException
      WrongFileFormatException
      WrongParameterException
    • process

      public void process() throws MissingParameterException, OperationFailedException
      Description copied from class: Operation
      This method does the actual work of the operation. It must be called after all parameters have been given to the operation object.
      Overrides:
      process in class Operation
      Throws:
      MissingParameterException - if any mandatory parameter was not given to the operation
      WrongParameterException - if at least one of the input parameters was not initialized appropriately (values out of the valid interval, etc.)
      OperationFailedException
    • readHeader

      private void readHeader() throws IOException, WrongFileFormatException
      Reads the first eight bytes from the input file, checks if this is a valid TIFF file and stores byte order and offset of the first image file directory.
      Throws:
      IOException - if there were reading errors
      WrongFileFormatException - if this is not a valid TIFF file
    • readImageFileDirectory

      private TIFFImageFileDirectory readImageFileDirectory() throws InvalidFileStructureException, IOException
      Reads a complete TIFF image file directory including all data that is pointed to using the offset components and returns it.
      Returns:
      the image file directory data or null on failure
      Throws:
      InvalidFileStructureException
      IOException
    • readInt

      private int readInt() throws IOException
      Reads a 32 bit signed integer value, regarding the current byte order.
      Returns:
      the loaded value
      Throws:
      IOException
      See Also:
    • readShort

      private short readShort() throws IOException
      Reads a 16 bit signed integer value, regarding the current byte order.
      Returns:
      the loaded value
      Throws:
      IOException
    • readString

      private String readString(int length) throws IOException
      Loads a String of a given length from current position of input file. Characters are one-byte ASCII. Non-text characters are dropped.
      Parameters:
      length - number of characters in a row to be loaded
      Returns:
      loaded String
      Throws:
      IOException - if there were reading errors or an unexpected end of file
    • readTag

      Reads a TIFF tag and all data belonging to it and returns a TIFFTag object. The additional data is somewhere in the TIFF file. The current position will be stored, the method will seek to the offset position and load the data.
      Returns:
      TIFFTag containing information on the tag
      Throws:
      InvalidFileStructureException
      IOException
    • registerDecoder

      public static void registerDecoder(Class decoderClass)
      Register a TIFFDecoder class. TIFF knows many compression types, and JIU only supports some of them. To register an external TIFFDecoder class with TIFFCodec, call this method with the class field of your decoder. As an example, for your TIFFDecoderMyCompression class, call TIFFCodec.registerDecoder(TIFFDecoderMyCompression.class). It will be checked if decoderClass.newInstance() instanceof TIFFDecoder is true and, if so, the class will be added to an internal list. Whenever a TIFF file is to be decoded, the correct decoder is determined (each decoder knows about the compression types it supports via the getCompressionTypes method) and for each tile or strip such a decoder object will be created.
    • setByteOrder

      private void setByteOrder(int newByteOrder)
      Sets the byte order to the argument. The byte order in a TIFF file is either BYTE_ORDER_INTEL or BYTE_ORDER_MOTOROLA.
      Parameters:
      newByteOrder - the new byte order to be set
      Throws:
      IllegalArgumentException - if the argument is not one of the above mentioned constants
    • setFile

      public void setFile(String fileName, CodecMode codecMode) throws IOException, UnsupportedCodecModeException
      Description copied from class: ImageCodec
      Gives a file name and codec mode to the codec which will then try to create the corresponding I/O object. The default implementation in ImageCodec creates a DataInputStream object wrapped around a BufferedInputStream wrapped around a FileInputStream for CodecMode.LOAD. Similar for CodecMode.SAVE: a DataOutputStream around a BufferedOutputStream object around a FileOutputStream object. Codecs that need different I/O objects must override this method (some codecs may need random access and thus require a RandomAccessFile object).
      Overrides:
      setFile in class ImageCodec
      Parameters:
      fileName - name of the file to be used for loading or saving
      codecMode - defines whether file is to be used for loading or saving
      Throws:
      IOException
      UnsupportedCodecModeException
    • skipImageFileDirectories

      private void skipImageFileDirectories(int numDirectories) throws InvalidFileStructureException, IOException
      Skips a given number of image file directories in this TIFF files. Throws an exception if there were errors or not enough image file directories.
      Parameters:
      numDirectories - the number of directories to be skipped, should be non-negative
      Throws:
      IllegalArgumentException - if argument is negative
      InvalidFileStructureException - if there aren't enough image file directories
      IOExceptions - if there were errors reading or skipping data
      IOException