net.sourceforge.jiu.codecs.tiff

Class TIFFCodec

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:

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:

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 TIFFCodec 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.

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 TIFFCodec and TIFFCodec.

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:

Author:
Marco Schmidt

Field Summary

static int
BYTE_ORDER_INTEL
static int
BYTE_ORDER_MOTOROLA
private static int
MAGIC_INTEL
private static int
MAGIC_MOTOROLA
private int
byteOrder
private static Hashtable
decoders
private int
nextIfdOffset

Fields inherited from class net.sourceforge.jiu.codecs.ImageCodec

boundsAvail, boundsHeight, boundsWidth, boundsX1, boundsX2, boundsY1, boundsY2, comments, din, dout, dpiX, dpiY, image, imageIndex, in, mode, out, raf

Fields inherited from class net.sourceforge.jiu.ops.Operation

abort, progressListeners

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

Method Summary

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.
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()
String[]
getMimeTypes()
static String
getTagName(int id)
Returns the name of a tag in English.
boolean
isLoadingSupported()
boolean
isSavingSupported()
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)
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, getFormatName, getImage, getImageIndex, getInputAsDataInput, getInputStream, getMimeTypes, getMode, getNumComments, getOutputAsDataOutput, getOutputStream, getRandomAccessFile, hasBounds, initModeFromIOObjects, isLoadingSupported, isRowRequired, isSavingSupported, isTileRequired, removeAllComments, removeBounds, setBounds, setBoundsIfNecessary, setDataInput, setDataOutput, setDpi, setFile, setFile, setImage, setImageIndex, setInputStream, setOutputStream, setRandomAccessFile, suggestFileExtension

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

addProgressListener, addProgressListeners, getAbort, process, removeProgressListener, setAbort, setProgress, setProgress

Field Details

BYTE_ORDER_INTEL

public static final int BYTE_ORDER_INTEL
Field Value:
1

BYTE_ORDER_MOTOROLA

public static final int BYTE_ORDER_MOTOROLA
Field Value:
0

MAGIC_INTEL

private static final int MAGIC_INTEL
Field Value:
1229531648

MAGIC_MOTOROLA

private static final int MAGIC_MOTOROLA
Field Value:
1296891946

byteOrder

private int byteOrder

decoders

private static Hashtable decoders

nextIfdOffset

private int nextIfdOffset

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

getByteOrder

public int getByteOrder()
Returns:
current byte order

getFormatName

public String getFormatName()
Overrides:
getFormatName in interface ImageCodec

getMimeTypes

public String[] getMimeTypes()
Overrides:
getMimeTypes in interface ImageCodec

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()
Overrides:
isLoadingSupported in interface ImageCodec

isSavingSupported

public boolean isSavingSupported()
Overrides:
isSavingSupported in interface ImageCodec

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 java.io.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 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:
UnsupportedTypeException - if the flavour of TIFF encountered in the input file is not supported yet
WrongFileFormatException -

load

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

process

public void process()
            throws MissingParameterException,
                   OperationFailedException
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 interface 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:
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

readInt

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

readShort

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

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

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

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)
Parameters:
newByteOrder - the new byte order to be set

setFile

public void setFile(String fileName,
                    CodecMode codecMode)
            throws IOException,
                   UnsupportedCodecModeException
Overrides:
setFile in interface ImageCodec

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:
InvalidFileStructureException - if there aren't enough image file directories