Package net.sourceforge.jiu.codecs.tiff

# Class TIFFCodec

java.lang.Object
net.sourceforge.jiu.ops.Operation
net.sourceforge.jiu.codecs.ImageCodec
net.sourceforge.jiu.codecs.tiff.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 Summary

Fields
Modifier and Type
Field
Description
`static final int`
`BYTE_ORDER_INTEL`
`static final int`
`BYTE_ORDER_MOTOROLA`
`private int`
`byteOrder`
`private static Hashtable`
`decoders`
`private static final int`
`MAGIC_INTEL`
`private static final int`
`MAGIC_MOTOROLA`
`private int`
`nextIfdOffset`

### Fields inherited from interface net.sourceforge.jiu.codecs.tiff.TIFFConstants

`COMPRESSION_CCITT_GROUP3_1D_MODIFIED_HUFFMAN, COMPRESSION_CCITT_T4, COMPRESSION_CCITT_T6, COMPRESSION_DEFLATED_INOFFICIAL, COMPRESSION_DEFLATED_OFFICIAL, COMPRESSION_JBIG, COMPRESSION_JBIG2, COMPRESSION_JPEG_6_0, COMPRESSION_JPEG_POST_6_0, COMPRESSION_LZW, COMPRESSION_NEXT, COMPRESSION_NONE, COMPRESSION_NONE_WORD_ALIGNED, COMPRESSION_PACKBITS, COMPRESSION_SGI_LOG_24_PACKED, COMPRESSION_SGI_LOG_RLE, COMPRESSION_THUNDERSCAN, PHOTOMETRIC_BLACK_IS_ZERO, PHOTOMETRIC_LOGL, PHOTOMETRIC_PALETTED, PHOTOMETRIC_TRUECOLOR_CMYK, PHOTOMETRIC_TRUECOLOR_LOGLUV, PHOTOMETRIC_TRUECOLOR_RGB, PHOTOMETRIC_WHITE_IS_ZERO, PLANAR_CONFIGURATION_CHUNKY, PLANAR_CONFIGURATION_PLANAR, TAG_ARTIST, TAG_BAD_FAX_LINES, TAG_BITS_PER_SAMPLE, TAG_CELL_LENGTH, TAG_CELL_WIDTH, TAG_CLEAN_FAX_DATA, TAG_COLOR_MAP, TAG_COMPRESSION, TAG_CONSECUTIVE_BAD_FAX_LINES, TAG_COPYRIGHT, TAG_DATE_TIME, TAG_DOCUMENT_NAME, TAG_EXTRA_SAMPLES, TAG_FILL_ORDER, TAG_FREE_BYTE_COUNTS, TAG_FREE_OFFSETS, TAG_GRAY_RESPONSE_CURVE, TAG_GRAY_RESPONSE_UNIT, TAG_HOST_COMPUTER, TAG_IMAGE_DESCRIPTION, TAG_IMAGE_LENGTH, TAG_IMAGE_WIDTH, TAG_LENGTH, TAG_MAKE, TAG_MAX_SAMPLE_VALUE, TAG_MIN_SAMPLE_VALUE, TAG_MODEL, TAG_NEW_SUBFILE_TYPE, TAG_ORIENTATION, TAG_PHOTOMETRIC_INTERPRETATION, TAG_PHOTOSHOP_IMAGE_RESOURCES, TAG_PLANAR_CONFIGURATION, TAG_PREDICTOR, TAG_RESOLUTION_UNIT, TAG_RESOLUTION_X, TAG_RESOLUTION_Y, TAG_ROWS_PER_STRIP, TAG_SAMPLES_PER_PIXEL, TAG_SOFTWARE, TAG_STRIP_BYTE_COUNTS, TAG_STRIP_OFFSETS, TAG_T4_OPTIONS, TAG_T6_OPTIONS, TAG_TILE_BYTE_COUNTS, TAG_TILE_HEIGHT, TAG_TILE_OFFSETS, TAG_TILE_WIDTH, TAG_TYPE_ASCII, TAG_TYPE_BYTE, TAG_TYPE_DOUBLE, TAG_TYPE_FLOAT, TAG_TYPE_LONG, TAG_TYPE_RATIONAL, TAG_TYPE_SBYTE, TAG_TYPE_SHORT, TAG_TYPE_SLONG, TAG_TYPE_SRATIONAL, TAG_TYPE_SSHORT, TAG_TYPE_UNDEFINED`

## Constructor Summary

Constructors
Constructor
Description
`TIFFCodec()`

## Method Summary

Modifier and Type
Method
Description
`private int`
`adjustInt(int value, int type)`
If the current byte order is `BYTE_ORDER_MOTOROLA` and the type argument is
invalid reference

    TiffConstants.TAG_TYPE_BYTE

or
invalid reference

    TiffConstants.TAG_TYPE_SHORT

, the value parameter must be adjusted by some bitshifting.
`private static TIFFDecoder`
`createDecoder(TIFFCodec codec, TIFFImageFileDirectory ifd, int tileIndex)`
`int`
`getByteOrder()`
Returns the current byte order, either `BYTE_ORDER_INTEL` or `BYTE_ORDER_MOTOROLA`.
`String`
`getFormatName()`
Returns the name of the file format supported by this codec.
`String[]`
`getMimeTypes()`
Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, or `null` if none are available.
`static String`
`getTagName(int id)`
Returns the name of a tag in English.
`boolean`
`isLoadingSupported()`
Returns if this codec is able to load images in the file format supported by this codec.
`boolean`
`isSavingSupported()`
Returns if this codec is able to save images in the file format supported by this codec.
`private void`
`load()`
Attempts to load an image from a file in the TIFF format.
`private void`
`load(TIFFImageFileDirectory ifd)`
`void`
`process()`
This method does the actual work of the operation.
`private void`
`readHeader()`
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.
`private TIFFImageFileDirectory`
`readImageFileDirectory()`
Reads a complete TIFF image file directory including all data that is pointed to using the offset components and returns it.
`private int`
`readInt()`
Reads a 32 bit signed integer value, regarding the current byte order.
`private short`
`readShort()`
Reads a 16 bit signed integer value, regarding the current byte order.
`private String`
`readString(int length)`
Loads a String of a given length from current position of input file.
`private TIFFTag`
`readTag()`
Reads a TIFF tag and all data belonging to it and returns a TIFFTag object.
`static void`
`registerDecoder(Class decoderClass)`
Register a `TIFFDecoder` class.
`private void`
`setByteOrder(int newByteOrder)`
Sets the byte order to the argument.
`void`
`setFile(String fileName, CodecMode codecMode)`
Gives a file name and codec mode to the codec which will then try to create the corresponding I/O object.
`private void`
`skipImageFileDirectories(int numDirectories)`
Skips a given number of image file directories in this TIFF files.

### Methods inherited from class net.sourceforge.jiu.codecs.ImageCodec

`appendComment, checkBounds, checkImageResolution, close, getBoundsHeight, getBoundsWidth, getBoundsX1, getBoundsX2, getBoundsY1, getBoundsY2, getComment, getDataInput, getDataOutput, getDpiX, getDpiY, getFileExtensions, getImage, getImageIndex, getInputAsDataInput, getInputStream, getMode, getNumComments, getOutputAsDataOutput, getOutputStream, getRandomAccessFile, hasBounds, initModeFromIOObjects, isRowRequired, isTileRequired, removeAllComments, removeBounds, setBounds, setBoundsIfNecessary, setDataInput, setDataOutput, setDpi, setFile, setImage, setImageIndex, setInputStream, setOutputStream, setRandomAccessFile, suggestFileExtension`

### Methods inherited from class net.sourceforge.jiu.ops.Operation

`addProgressListener, addProgressListeners, getAbort, removeProgressListener, setAbort, setProgress, setProgress`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Field Details

### BYTE_ORDER_MOTOROLA

public static final int BYTE_ORDER_MOTOROLA

See Also:
  - Constant Field Values

### BYTE_ORDER_INTEL

public static final int BYTE_ORDER_INTEL

See Also:
  - Constant Field Values

### MAGIC_INTEL

private static final int MAGIC_INTEL

See Also:
  - Constant Field Values

### MAGIC_MOTOROLA

private static final int MAGIC_MOTOROLA

See Also:
  - Constant Field Values

### 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
invalid reference

    TiffConstants.TAG_TYPE_BYTE

or
invalid reference

    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

private void load() throws InvalidFileStructureException, IOException, UnsupportedTypeException, WrongFileFormatException, WrongParameterException
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
  invalid reference

      #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

private void load(TIFFImageFileDirectory ifd) throws InvalidFileStructureException, IOException, UnsupportedTypeException, WrongFileFormatException, WrongParameterException

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
  `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:
  - `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

### readTag

private TIFFTag readTag() throws InvalidFileStructureException, IOException
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