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
    • Constructor Detail

      • TIFFCodec

        public TIFFCodec()
    • Method Detail

      • 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
      • 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
      • 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:
        getByteOrder()
      • 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
      • 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