/*
* TIFFImageFileDirectory
*
* Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Marco Schmidt.
* All rights reserved.
*/
package net.sourceforge.jiu.codecs.tiff;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Vector;
import net.sourceforge.jiu.codecs.InvalidFileStructureException;
import net.sourceforge.jiu.codecs.UnsupportedTypeException;
import net.sourceforge.jiu.codecs.tiff.TIFFConstants;
import net.sourceforge.jiu.codecs.tiff.TIFFTag;
import net.sourceforge.jiu.data.Palette;
import net.sourceforge.jiu.data.RGBIndex;
/**
* This class encapsulates all data of a TIFF image file directory (IFD).
* @author Marco Schmidt
*/
public class TIFFImageFileDirectory implements TIFFConstants
{
public static final int TYPE_BILEVEL_PACKED = 0;
public static final int TYPE_GRAY4 = 1;
public static final int TYPE_GRAY8 = 2;
public static final int TYPE_GRAY16 = 3;
public static final int TYPE_PALETTED4 = 4;
public static final int TYPE_PALETTED8 = 5;
public static final int TYPE_RGB24_INTERLEAVED = 6;
public static final int TYPE_RGB48_INTERLEAVED = 7;
public static final int TYPE_BILEVEL_BYTE = 8;
public static final int TYPE_CMYK32_INTERLEAVED = 9;
public static final int TYPE_CMYK32_PLANAR = 10;
public static final int TYPE_LOGLUV32_INTERLEAVED = 11;
public static final int TYPE_LOGL = 12;
private String artist;
private int[] bitsPerSample;
private int bitsPerPixel;
private int bitsPerRow;
private int bytesBetweenSamples;
private int[] bytesPerSample;
private int bytesPerRow;
private int compression;
private String copyright;
private Date date;
private String dateTime;
private int dpiX;
private int dpiY;
private int[] extraSamples;
private int height;
private int horizontalTiles;
private String hostComputer;
private String imageDescription;
private int imageType;
private boolean invertGraySamples;
private String make;
private String model;
private int numStrips;
private int numTiles;
private int orientation;
private Palette palette;
private int pixelsPerRow;
private int planarConfiguration;
private int photometricInterpretation;
private int predictor;
private int[] sampleTypes;
private int resolutionUnit;
private double resolutionX;
private double resolutionY;
private int rowsPerStrip;
private int samplesPerPixel;
private String software;
private Vector stripByteCounts;
private Vector stripOffsets;
private int t4Options;
private int t6Options;
private Vector tags;
private Vector tileByteCounts;
private Vector tileOffsets;
private TimeZone timeZone;
private int tileWidth;
private int tileHeight;
private int verticalTiles;
private int width;
/**
* Initializes all members to null or -1 and creates an internal list for
* the tags that will be make up this directory.
*/
public TIFFImageFileDirectory()
{
initMembers();
tags = new Vector();
}
/**
* Adds a tag to the end of the internal list of tags.
* @param tag the TIFFTag instance to be appended
*/
public void append(TIFFTag tag)
{
tags.addElement(tag);
}
private void checkContent() throws
InvalidFileStructureException,
UnsupportedTypeException
{
if (width < 1)
{
throw new InvalidFileStructureException("No valid width available.");
}
if (height < 1)
{
throw new InvalidFileStructureException("No valid width available.");
}
if (stripOffsets != null)
{
pixelsPerRow = width;
}
else
if (tileOffsets != null)
{
pixelsPerRow = tileWidth;
}
if (rowsPerStrip == -1 && stripOffsets != null && stripOffsets.size() == 1)
{
rowsPerStrip = height;
}
// do more checks based on color type
switch (photometricInterpretation)
{
case(PHOTOMETRIC_BLACK_IS_ZERO):
case(PHOTOMETRIC_WHITE_IS_ZERO):
{
if (bitsPerSample[0] == 1)
{
imageType = TYPE_BILEVEL_PACKED;
}
else
{
if (bitsPerSample[0] == 4)
{
imageType = TYPE_GRAY4;
}
else
if (bitsPerSample[0] == 8)
{
imageType = TYPE_GRAY8;
}
else
{
throw new UnsupportedTypeException("Only bit depths 1, 4 and 8 are supported for bilevel and grayscale images.");
}
}
break;
}
case(PHOTOMETRIC_PALETTED):
{
if (getPalette() == null)
{
throw new InvalidFileStructureException("No palette found in paletted image.");
}
break;
}
case(PHOTOMETRIC_TRUECOLOR_RGB):
{
if (planarConfiguration != PLANAR_CONFIGURATION_CHUNKY)
{
throw new UnsupportedTypeException("Cannot handle planar configuration other than chunky for RGB images.");
}
if (bitsPerSample.length != 3)
{
throw new UnsupportedTypeException("Found RGB truecolor image, but instead of three " + bitsPerSample.length + " component(s).");
}
if (bitsPerPixel == 24)
{
imageType = TYPE_RGB24_INTERLEAVED;
}
else
if (bitsPerPixel == 48)
{
imageType = TYPE_RGB48_INTERLEAVED;
}
else
{
throw new UnsupportedTypeException("Unsupported RGB truecolor image color depth: " + bitsPerPixel + ".");
}
break;
}
case(PHOTOMETRIC_TRUECOLOR_LOGLUV):
{
if (planarConfiguration == PLANAR_CONFIGURATION_CHUNKY)
{
imageType = TYPE_LOGLUV32_INTERLEAVED;
}
else
{
throw new UnsupportedTypeException("Cannot handle planar configuration other than chunky for RGB images.");
}
break;
}
case(PHOTOMETRIC_LOGL):
{
imageType = TYPE_LOGL;
break;
}
case(PHOTOMETRIC_TRUECOLOR_CMYK):
{
if (planarConfiguration == PLANAR_CONFIGURATION_CHUNKY)
{
imageType = TYPE_CMYK32_INTERLEAVED;
}
/*else
if (planarConfiguration == PLANAR_CONFIGURATION_PLANAR)
{
imageType = TYPE_CMYK32_PLANAR;
}*/
else
{
throw new UnsupportedTypeException("Cannot handle planar configuration other than chunky for CMYK images.");
}
break;
}
default:
{
throw new UnsupportedTypeException("Unsupported color type: " + photometricInterpretation + ".");
}
}
if (compression == COMPRESSION_CCITT_GROUP3_1D_MODIFIED_HUFFMAN)
{
if (bitsPerPixel != 1)
{
throw new UnsupportedTypeException("Number of bits per pixel must be 1 for " +
"compression type: " + getCompressionName(compression) + ".");
}
imageType = TYPE_BILEVEL_BYTE;
}
// TODO more validity checks
}
/**
* TODO: regard extra samples
*/
public int computeNumBytes(int numPixels)
{
if (bitsPerPixel == 1)
{
if (imageType == TYPE_BILEVEL_BYTE)
{
return numPixels;
}
else
{
return (numPixels + 7) / 8;
}
}
else
if (bitsPerPixel <= 4)
{
return (numPixels + 1) / 2;
}
else
if (bitsPerPixel <= 8)
{
return numPixels;
}
else
if (bitsPerPixel == 16)
{
return numPixels * 2;
}
else
if (bitsPerPixel == 24)
{
return numPixels * 3;
}
else
if (bitsPerPixel == 32)
{
return numPixels * 4;
}
else
if (bitsPerPixel == 48)
{
return numPixels * 6;
}
else
{
return -1;
}
}
/**
* Returns information on the person who created the image
* (as stored in tag {@link TIFFConstants#TAG_ARTIST}).
*/
public String getArtist()
{
return artist;
}
/**
* Returns the number of bits per pixel (not including transparency information).
*/
public int getBitsPerPixel()
{
return bitsPerPixel;
}
/**
* Returns the number of compressed byte for a given tile.
* Tile index must not be negative and must be smaller than the number of tiles.
* @param tileIndex zero-based index of tile or strip for which the number of compressed bytes is to be returned
*/
public int getByteCount(int tileIndex)
{
if (stripByteCounts != null)
{
return ((Number)stripByteCounts.elementAt(tileIndex)).intValue();
}
else
if (tileByteCounts != null)
{
return ((Number)tileByteCounts.elementAt(tileIndex)).intValue();
}
else
{
return 0;
}
}
public int getBytesPerRow()
{
return computeNumBytes(getTileWidth());
}
/**
* Returns the compression method, encoded as a number as found in
* {@link TIFFConstants} (more specifically, the COMPRESSION_xyz constants).
* Use {@link #getCompressionName(int)} to get the English name
* of this compression method.
* @return compression method
*/
public int getCompression()
{
return compression;
}
/**
* Returns the name of a TIFF compression method.
* If the name is unknown, <em>Unknown method</em> plus
* the method number is returned.
* This static method can be used in combination with the value from
* {@link #getCompression}.
* @param method the compression method number
* @return the compression method name
*/
public static String getCompressionName(int method)
{
switch(method)
{
case(COMPRESSION_CCITT_GROUP3_1D_MODIFIED_HUFFMAN): return "CCITT Group 3 1D Modified Huffman";
case(COMPRESSION_CCITT_T4): return "CCITT T.4";
case(COMPRESSION_CCITT_T6): return "CCITT T.6";
case(COMPRESSION_DEFLATED_INOFFICIAL): return "Deflated (inofficial, 32496)";
case(COMPRESSION_DEFLATED_OFFICIAL): return "Deflated (official, 8)";
case(COMPRESSION_LZW): return "LZW";
case(COMPRESSION_NONE): return "Uncompressed";
case(COMPRESSION_PACKBITS): return "Packbits";
case(6): return "JPEG (old style)";
case(7):return "JPEG (new style)";
case(103): return "Pegasus IMJ";
case(32766): return "NeXT 2-bit RLE";
case(32771): return "Uncompressed, word-aligned";
case(32809): return "Thunderscan RLE";
case(32895): return "IT8 CT with padding";
case(32896): return "IT8 Linework RLE";
case(32897): return "IT8 Monochrome picture";
case(32898): return "IT8 Binary line art";
case(32908): return "Pixar 10 bit LZW";
case(32909): return "Pixar 11 bit ZIP";
case(32947): return "Kodak DCS";
case(34661): return "ISO JBIG";
case(34676): return "SGI Log Luminance RLE";
case(34677): return "SGI Log 24-bit packed";
default: return "Unknown method (" + method + ")";
}
}
public String getCopyright()
{
return copyright;
}
/**
* If a date / time tag was found in this image file directory and
* {@link #initFromTags} was called already, it was attempted to
* create a {@link java.util.Date} object from it.
* This object (or <code>null</code>) is returned.
* Use {@link #setTimeZone} to provide a time zone before the date
* parsing is done.
* @see #getDateTimeString
*/
public Date getDateTime()
{
return date;
}
/**
* If there was a date / time tag in this IFD, its String value
* is returned.
* @see #getDateTime
*/
public String getDateTimeString()
{
return dateTime;
}
public int getDpiX()
{
return dpiX;
}
public int getDpiY()
{
return dpiY;
}
public int getHeight()
{
return height;
}
public String getHostComputer()
{
return hostComputer;
}
public String getImageDescription()
{
return imageDescription;
}
public int getImageType()
{
return imageType;
}
public String getModel()
{
return model;
}
public int getNumHorizontalTiles()
{
return horizontalTiles;
}
public int getNumStrips()
{
return numStrips;
}
public int getNumTiles()
{
return numTiles;
}
public int getNumVerticalTiles()
{
return verticalTiles;
}
public Palette getPalette()
{
return palette;
}
public int getPhotometricInterpretation()
{
return photometricInterpretation;
}
public int getPredictor()
{
return predictor;
}
public int getRowsPerStrip()
{
return rowsPerStrip;
}
public int getSamplesPerPixel()
{
return samplesPerPixel;
}
public String getSoftware()
{
return software;
}
public Vector getStripOffsets()
{
return stripOffsets;
}
public int getT4Options()
{
return t4Options;
}
public int getT6Options()
{
return t6Options;
}
public int getTileHeight()
{
return tileHeight;
}
public long getTileOffset(int tileIndex)
{
if (stripOffsets != null)
{
Number number = (Number)stripOffsets.elementAt(tileIndex);
return number.longValue();
}
else
if (tileOffsets != null)
{
Number number = (Number)tileOffsets.elementAt(tileIndex);
return number.longValue();
}
else
{
throw new IllegalArgumentException("Tile index invalid: " + tileIndex);
}
}
public int getTileWidth()
{
return tileWidth;
}
public int getTileX1(int tileIndex)
{
if (tileIndex < 0 || tileIndex >= getNumTiles())
{
throw new IllegalArgumentException("Not a valid tile index: " + tileIndex);
}
else
{
return (tileIndex % getNumHorizontalTiles()) * getTileWidth();
}
}
public int getTileX2(int tileIndex)
{
if (tileIndex < 0 || tileIndex >= getNumTiles())
{
throw new IllegalArgumentException("Not a valid tile index: " + tileIndex);
}
else
{
return ((tileIndex % getNumHorizontalTiles()) + 1) * getTileWidth() - 1;
}
}
public int getTileY1(int tileIndex)
{
if (tileIndex < 0 || tileIndex >= getNumTiles())
{
throw new IllegalArgumentException("Not a valid tile index: " + tileIndex);
}
else
{
return (tileIndex % getNumVerticalTiles()) * getTileHeight();
}
}
public int getTileY2(int tileIndex)
{
if (tileIndex < 0 || tileIndex >= getNumTiles())
{
throw new IllegalArgumentException("Not a valid tile index: " + tileIndex);
}
else
{
int result = ((tileIndex % getNumVerticalTiles()) + 1) * getTileHeight() - 1;
if (result >= height)
{
result = height - 1;
}
return result;
}
}
public int getWidth()
{
return width;
}
public void initMembers()
{
bitsPerPixel = -1;
bitsPerSample = null;
compression = -1;
height = -1;
horizontalTiles = -1;
invertGraySamples = false;
numStrips = -1;
numTiles = -1;
orientation = 1;
photometricInterpretation = -1;
planarConfiguration = -1;
resolutionUnit = 2;
resolutionX = -1.0;
resolutionY = -1.0;
rowsPerStrip = -1;
stripOffsets = null;
tags = null;
tileOffsets = null;
tileWidth = -1;
tileHeight = -1;
verticalTiles = -1;
width = -1;
}
public void initFromTags(boolean check) throws
InvalidFileStructureException,
UnsupportedTypeException
{
int index = 0;
while (index < tags.size())
{
TIFFTag tag = (TIFFTag)tags.elementAt(index++);
int id = tag.getId();
int count = tag.getCount();
int type = tag.getType();
boolean isNotInt = !tag.isInt();
switch(id)
{
case(TAG_ARTIST):
{
artist = tag.getString();
break;
}
case(TAG_BITS_PER_SAMPLE):
{
if (isNotInt)
{
throw new InvalidFileStructureException("Bits per " +
"sample value(s) must be byte/short/long; type=" +
type);
}
if (count == 1)
{
bitsPerSample = new int[1];
bitsPerSample[0] = tag.getOffset();
bitsPerPixel = bitsPerSample[0];
}
else
{
bitsPerPixel = 0;
bitsPerSample = new int[count];
for (int i = 0; i < count; i++)
{
bitsPerSample[i] = tag.getElementAsInt(i);
if (bitsPerSample[i] < 1)
{
throw new InvalidFileStructureException("Bits per " +
"sample value #" + i + " is smaller than 1.");
}
bitsPerPixel += bitsPerSample[i];
}
}
break;
}
case(TAG_COLOR_MAP):
{
if ((count % 3) != 0)
{
throw new InvalidFileStructureException("Number of palette entries must be divideable by three without rest; " + count);
}
if (count < 3 || count > 768)
{
throw new UnsupportedTypeException("Unsupported number of palette entries: " + count + ".");
}
if (type != TAG_TYPE_SHORT)
{
throw new UnsupportedTypeException("Unsupported number type for palette entries: " + type);
}
int numEntries = count / 3;
palette = new Palette(numEntries, 255);
int vectorIndex = 0;
for (int paletteIndex = 0; paletteIndex < numEntries; paletteIndex++)
{
palette.putSample(RGBIndex.INDEX_RED, paletteIndex, tag.getElementAsInt(vectorIndex++) >> 8);
}
for (int paletteIndex = 0; paletteIndex < numEntries; paletteIndex++)
{
palette.putSample(RGBIndex.INDEX_GREEN, paletteIndex, tag.getElementAsInt(vectorIndex++) >> 8);
}
for (int paletteIndex = 0; paletteIndex < numEntries; paletteIndex++)
{
palette.putSample(RGBIndex.INDEX_BLUE, paletteIndex, tag.getElementAsInt(vectorIndex++) >> 8);
}
break;
}
case(TAG_COMPRESSION):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
" single byte/short/long value for compression " +
"(count=" + count + ", type=" + type + ").");
}
compression = tag.getOffset();
break;
}
case(TAG_DATE_TIME):
{
dateTime = tag.getString();
if (dateTime != null)
{
dateTime = dateTime.trim();
}
if (dateTime != null)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
if (timeZone != null)
{
format.setCalendar(new GregorianCalendar(timeZone));
}
try
{
date = format.parse(dateTime);
}
catch (ParseException pe)
{
date = null;
}
}
break;
}
case(TAG_HOST_COMPUTER):
{
hostComputer = tag.getString();
break;
}
case(TAG_IMAGE_DESCRIPTION):
{
imageDescription = tag.getString();
break;
}
case(TAG_IMAGE_WIDTH):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for image width " +
"(count=" + count + ", type=" + type + ").");
}
width = tag.getOffset();
break;
}
case(TAG_IMAGE_LENGTH):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for image height " +
"(count=" + count + ", type=" + type + ").");
}
height = tag.getOffset();
break;
}
case(TAG_MAKE):
{
make = tag.getString();
break;
}
case(TAG_MODEL):
{
model = tag.getString();
break;
}
case(TAG_ORIENTATION):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for image height " +
"(count=" + count + ", type=" + type + ").");
}
orientation = tag.getOffset();
break;
}
case(TAG_PHOTOMETRIC_INTERPRETATION):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for photometric interpretation.");
}
photometricInterpretation = tag.getOffset();
break;
}
case(TAG_RESOLUTION_UNIT):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for planar configuration.");
}
resolutionUnit = tag.getOffset();
break;
}
case(TAG_RESOLUTION_X):
{
if (count != 1 || type != TAG_TYPE_RATIONAL)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for planar configuration.");
}
Object o = tag.getObject(0);
if (o != null && o instanceof TIFFRational)
{
TIFFRational rational = (TIFFRational)o;
resolutionX = rational.getAsDouble();
}
break;
}
case(TAG_RESOLUTION_Y):
{
if (count != 1 || type != TAG_TYPE_RATIONAL)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for planar configuration.");
}
Object o = tag.getObject(0);
if (o != null && o instanceof TIFFRational)
{
TIFFRational rational = (TIFFRational)o;
resolutionY = rational.getAsDouble();
}
break;
}
case(TAG_PLANAR_CONFIGURATION):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for planar configuration.");
}
planarConfiguration = tag.getOffset();
break;
}
case(TAG_ROWS_PER_STRIP):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for image height.");
}
rowsPerStrip = tag.getOffset();
break;
}
case(TAG_SAMPLES_PER_PIXEL):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for samples per pixel.");
}
samplesPerPixel = tag.getOffset();
break;
}
case(TAG_SOFTWARE):
{
software = tag.getString();
break;
}
case(TAG_STRIP_BYTE_COUNTS):
{
if (count < 1)
{
throw new InvalidFileStructureException("Need at least one strip offset.");
}
if (count == 1)
{
if (isNotInt)
{
throw new InvalidFileStructureException("There is " +
"only one strip offset, but its type is not integer.");
}
stripByteCounts = new Vector();
stripByteCounts.addElement(new Long(tag.getOffset()));
}
else
{
stripByteCounts = tag.getVector();
}
break;
}
case(TAG_STRIP_OFFSETS):
{
if (count < 1)
{
throw new InvalidFileStructureException("Need at least one strip offset.");
}
if (count == 1)
{
if (isNotInt)
{
throw new InvalidFileStructureException("There is " +
"only one strip offset, but its type is not integer.");
}
stripOffsets = new Vector();
stripOffsets.addElement(new Long(tag.getOffset()));
}
else
{
stripOffsets = tag.getVector();
}
numStrips = count;
numTiles = count;
horizontalTiles = 1;
verticalTiles = count;
break;
}
case(TAG_T4_OPTIONS):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for T4 Options.");
}
t4Options = tag.getOffset();
break;
}
case(TAG_T6_OPTIONS):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for T6 Options.");
}
t6Options = tag.getOffset();
break;
}
case(TAG_TILE_HEIGHT):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for image height " +
"(count=" + count + ", type=" + type + ").");
}
tileHeight = tag.getOffset();
if (tileHeight < 1)
{
throw new InvalidFileStructureException("Tile height must be one or larger.");
}
verticalTiles = height / tileHeight;
if ((height % tileHeight) != 0)
{
verticalTiles++;
}
break;
}
case(TAG_TILE_OFFSETS):
{
if (count < 1)
{
throw new InvalidFileStructureException("Need at least one tile offset.");
}
if (count == 1)
{
if (isNotInt)
{
throw new InvalidFileStructureException("There is " +
"only one tile offset, but its type is not integer.");
}
tileOffsets = new Vector();
tileOffsets.addElement(new Long(tag.getOffset()));
}
else
{
tileOffsets = tag.getVector();
}
numStrips = count;
numTiles = count;
horizontalTiles = 1;
verticalTiles = count;
break;
}
case(TAG_TILE_WIDTH):
{
if (count != 1 || isNotInt)
{
throw new InvalidFileStructureException("Expected " +
"single byte/short/long value for image height " +
"(count=" + count + ", type=" + type + ").");
}
tileWidth = tag.getOffset();
if (tileWidth < 1)
{
throw new InvalidFileStructureException("Tile width must be one or larger.");
}
horizontalTiles = width / tileWidth;
if ((width % tileWidth) != 0)
{
horizontalTiles++;
}
break;
}
}
}
if (planarConfiguration == -1)
{
planarConfiguration = PLANAR_CONFIGURATION_CHUNKY;
}
if (photometricInterpretation == TIFFConstants.PHOTOMETRIC_PALETTED)
{
if (bitsPerPixel == 4)
{
imageType = TYPE_PALETTED4;
}
else
if (bitsPerPixel == 8)
{
imageType = TYPE_PALETTED8;
}
else
{
throw new UnsupportedTypeException("Only paletted images with 4 or 8 bits per sample are supported.");
}
}
if (resolutionUnit == 2 && resolutionX > 0.0 && resolutionY > 0.0)
{
dpiX = (int)resolutionX;
dpiY = (int)resolutionY;
}
if (isStriped())
{
tileWidth = width;
if (numStrips == 1 && rowsPerStrip == -1)
{
rowsPerStrip = height;
}
tileHeight = rowsPerStrip;
}
if (check)
{
checkContent();
}
}
public boolean isGrayscale()
{
return getBitsPerPixel() > 1 &&
(photometricInterpretation == PHOTOMETRIC_BLACK_IS_ZERO ||
photometricInterpretation == PHOTOMETRIC_WHITE_IS_ZERO);
}
public boolean isPaletted()
{
return (photometricInterpretation == PHOTOMETRIC_PALETTED);
}
/**
* Returns <code>true</code> if the image belonging to this IFD
* is stored as strips, <code>false</code> otherwise.
* @see #isTiled
*/
public boolean isStriped()
{
return (stripOffsets != null);
}
/**
* Returns <code>true</code> if the image belonging to this IFD
* is stored as tiles, <code>false</code> otherwise.
* @see #isStriped
*/
public boolean isTiled()
{
return (tileOffsets != null);
}
/**
* Sets the time zone to be used when trying to interpret dates
* found in a {@link #TAG_DATE_TIME} tag.
* Example call:
* <code>setTimeZone(TimeZone.getTimeZone("America/New_York");</code>.
* @param tz TimeZone object
*/
public void setTimeZone(TimeZone tz)
{
timeZone = tz;
}
}