com.github.jaiimageio.impl.plugins.tiff.TIFFImageMetadata Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jai-imageio-core Show documentation
Show all versions of jai-imageio-core Show documentation
Java Advanced Imaging Image I/O Tools API core, but without the classes
involved with javax.media.jai dependencies, JPEG2000 or
codecLibJIIO, meaning that this library can be distributed under the
modified BSD license and should be GPL compatible.
The newest version!
/*
* $RCSfile: TIFFImageMetadata.java,v $
*
*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
* NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
* ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
* REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
* INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for
* use in the design, construction, operation or maintenance of any
* nuclear facility.
*
* $Revision: 1.11 $
* $Date: 2006/07/21 22:56:55 $
* $State: Exp $
*/
package com.github.jaiimageio.impl.plugins.tiff;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageInputStream;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.github.jaiimageio.plugins.tiff.BaselineTIFFTagSet;
import com.github.jaiimageio.plugins.tiff.EXIFParentTIFFTagSet;
import com.github.jaiimageio.plugins.tiff.TIFFField;
import com.github.jaiimageio.plugins.tiff.TIFFTag;
import com.github.jaiimageio.plugins.tiff.TIFFTagSet;
public class TIFFImageMetadata extends IIOMetadata {
// package scope
public static final String SUN_BaselineTIFFTagSetClassName =
"com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet" ;
public static final String THISJAI_BaselineTIFFTagSetClassName =
"com.github.jaiimageio.plugins.tiff.BaselineTIFFTagSet";
public static final String nativeMetadataFormatName =
"com_sun_media_imageio_plugins_tiff_image_1.0";
public static final String nativeMetadataFormatClassName =
"com.github.jaiimageio.impl.plugins.tiff.TIFFImageMetadataFormat";
List tagSets;
TIFFIFD rootIFD;
public TIFFImageMetadata(List tagSets) {
super(true,
nativeMetadataFormatName,
nativeMetadataFormatClassName,
null, null);
this.tagSets = tagSets;
this.rootIFD = new TIFFIFD(tagSets);
}
public TIFFImageMetadata(TIFFIFD ifd) {
super(true,
nativeMetadataFormatName,
nativeMetadataFormatClassName,
null, null);
this.tagSets = ifd.getTagSetList();
this.rootIFD = ifd;
}
public void initializeFromStream(ImageInputStream stream,
boolean ignoreUnknownFields)
throws IOException {
rootIFD.initialize(stream, ignoreUnknownFields);
}
public void addShortOrLongField(int tagNumber, int value) {
TIFFField field = new TIFFField(rootIFD.getTag(tagNumber), value);
rootIFD.addTIFFField(field);
}
// public void initializeFromImageType(ImageTypeSpecifier imageType) {
// SampleModel sampleModel = imageType.getSampleModel();
// ColorModel colorModel = imageType.getColorModel();
// int numBands = sampleModel.getNumBands();
// char[] bitsPerSample = new char[numBands];
// for (int i = 0; i < numBands; i++) {
// bitsPerSample[i] = (char)(sampleModel.getSampleSize(i));
// }
// TIFFField bitsPerSampleField =
// new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE),
// TIFFTag.TIFF_SHORT,
// numBands,
// bitsPerSample);
// rootIFD.addTIFFField(bitsPerSampleField);
// }
public boolean isReadOnly() {
return false;
}
private Node getIFDAsTree(TIFFIFD ifd,
String parentTagName, int parentTagNumber) {
IIOMetadataNode IFDRoot = new IIOMetadataNode("TIFFIFD");
if (parentTagNumber != 0) {
IFDRoot.setAttribute("parentTagNumber",
Integer.toString(parentTagNumber));
}
if (parentTagName != null) {
IFDRoot.setAttribute("parentTagName", parentTagName);
}
List tagSets = ifd.getTagSetList();
if (tagSets.size() > 0) {
Iterator iter = tagSets.iterator();
String tagSetNames = "";
while (iter.hasNext()) {
TIFFTagSet tagSet = (TIFFTagSet)iter.next();
tagSetNames += tagSet.getClass().getName();
if (iter.hasNext()) {
tagSetNames += ",";
}
}
IFDRoot.setAttribute("tagSets", tagSetNames);
}
Iterator iter = ifd.iterator();
while (iter.hasNext()) {
TIFFField f = (TIFFField)iter.next();
int tagNumber = f.getTagNumber();
TIFFTag tag = TIFFIFD.getTag(tagNumber, tagSets);
Node node = null;
if (tag == null) {
node = f.getAsNativeNode();
} else if (tag.isIFDPointer()) {
Object data = f.getData();
if (data instanceof TIFFIFD) {
TIFFIFD subIFD = (TIFFIFD) f.getData();
// Recurse
node = getIFDAsTree(subIFD, tag.getName(), tag.getNumber());
}
} else {
node = f.getAsNativeNode();
}
if (node != null) {
IFDRoot.appendChild(node);
}
}
return IFDRoot;
}
public Node getAsTree(String formatName) {
if (formatName.equals(nativeMetadataFormatName)) {
return getNativeTree();
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
return getStandardTree();
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
private Node getNativeTree() {
IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName);
Node IFDNode = getIFDAsTree(rootIFD, null, 0);
root.appendChild(IFDNode);
return root;
}
private static final String[] colorSpaceNames = {
"GRAY", // WhiteIsZero
"GRAY", // BlackIsZero
"RGB", // RGB
"RGB", // PaletteColor
"GRAY", // TransparencyMask
"CMYK", // CMYK
"YCbCr", // YCbCr
"Lab", // CIELab
"Lab", // ICCLab
};
public IIOMetadataNode getStandardChromaNode() {
IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
IIOMetadataNode node = null; // scratch node
TIFFField f;
// Set the PhotometricInterpretation and the palette color flag.
int photometricInterpretation = -1;
boolean isPaletteColor = false;
f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
if (f != null) {
photometricInterpretation = f.getAsInt(0);
isPaletteColor =
photometricInterpretation ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR;
}
// Determine the number of channels.
int numChannels = -1;
if(isPaletteColor) {
numChannels = 3;
} else {
f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
if (f != null) {
numChannels = f.getAsInt(0);
} else { // f == null
f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
if(f != null) {
numChannels = f.getCount();
}
}
}
if(photometricInterpretation != -1) {
if (photometricInterpretation >= 0 &&
photometricInterpretation < colorSpaceNames.length) {
node = new IIOMetadataNode("ColorSpaceType");
String csName;
if(photometricInterpretation ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK &&
numChannels == 3) {
csName = "CMY";
} else {
csName = colorSpaceNames[photometricInterpretation];
}
node.setAttribute("name", csName);
chroma_node.appendChild(node);
}
node = new IIOMetadataNode("BlackIsZero");
node.setAttribute("value",
(photometricInterpretation ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO)
? "FALSE" : "TRUE");
chroma_node.appendChild(node);
}
if(numChannels != -1) {
node = new IIOMetadataNode("NumChannels");
node.setAttribute("value", Integer.toString(numChannels));
chroma_node.appendChild(node);
}
f = getTIFFField(BaselineTIFFTagSet.TAG_COLOR_MAP);
if (f != null) {
// NOTE: The presence of hasAlpha is vestigial: there is
// no way in TIFF to represent an alpha component in a palette
// color image. See bug 5086341.
boolean hasAlpha = false;
node = new IIOMetadataNode("Palette");
int len = f.getCount()/(hasAlpha ? 4 : 3);
for (int i = 0; i < len; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("PaletteEntry");
entry.setAttribute("index", Integer.toString(i));
int r = (f.getAsInt(i)*255)/65535;
int g = (f.getAsInt(len + i)*255)/65535;
int b = (f.getAsInt(2*len + i)*255)/65535;
entry.setAttribute("red", Integer.toString(r));
entry.setAttribute("green", Integer.toString(g));
entry.setAttribute("blue", Integer.toString(b));
if (hasAlpha) {
int alpha = 0;
entry.setAttribute("alpha", Integer.toString(alpha));
}
node.appendChild(entry);
}
chroma_node.appendChild(node);
}
return chroma_node;
}
public IIOMetadataNode getStandardCompressionNode() {
IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
IIOMetadataNode node = null; // scratch node
TIFFField f;
f = getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION);
if (f != null) {
String compressionTypeName = null;
int compression = f.getAsInt(0);
boolean isLossless = true; // obligate initialization.
if(compression == BaselineTIFFTagSet.COMPRESSION_NONE) {
compressionTypeName = "None";
isLossless = true;
} else {
int[] compressionNumbers = TIFFImageWriter.compressionNumbers;
for(int i = 0; i < compressionNumbers.length; i++) {
if(compression == compressionNumbers[i]) {
compressionTypeName =
TIFFImageWriter.compressionTypes[i];
isLossless =
TIFFImageWriter.isCompressionLossless[i];
break;
}
}
}
if (compressionTypeName != null) {
node = new IIOMetadataNode("CompressionTypeName");
node.setAttribute("value", compressionTypeName);
compression_node.appendChild(node);
node = new IIOMetadataNode("Lossless");
node.setAttribute("value", isLossless ? "TRUE" : "FALSE");
compression_node.appendChild(node);
}
}
node = new IIOMetadataNode("NumProgressiveScans");
node.setAttribute("value", "1");
compression_node.appendChild(node);
return compression_node;
}
private String repeat(String s, int times) {
if (times == 1) {
return s;
}
StringBuffer sb = new StringBuffer((s.length() + 1)*times - 1);
sb.append(s);
for (int i = 1; i < times; i++) {
sb.append(" ");
sb.append(s);
}
return sb.toString();
}
public IIOMetadataNode getStandardDataNode() {
IIOMetadataNode data_node = new IIOMetadataNode("Data");
IIOMetadataNode node = null; // scratch node
TIFFField f;
boolean isPaletteColor = false;
f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
if (f != null) {
isPaletteColor =
f.getAsInt(0) ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR;
}
f = getTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION);
String planarConfiguration = "PixelInterleaved";
if (f != null &&
f.getAsInt(0) == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) {
planarConfiguration = "PlaneInterleaved";
}
node = new IIOMetadataNode("PlanarConfiguration");
node.setAttribute("value", planarConfiguration);
data_node.appendChild(node);
f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
if (f != null) {
int photometricInterpretation = f.getAsInt(0);
String sampleFormat = "UnsignedIntegral";
if (photometricInterpretation ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR) {
sampleFormat = "Index";
} else {
f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT);
if (f != null) {
int format = f.getAsInt(0);
if (format ==
BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
sampleFormat = "SignedIntegral";
} else if (format ==
BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER) {
sampleFormat = "UnsignedIntegral";
} else if (format ==
BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
sampleFormat = "Real";
} else {
sampleFormat = null; // don't know
}
}
}
if (sampleFormat != null) {
node = new IIOMetadataNode("SampleFormat");
node.setAttribute("value", sampleFormat);
data_node.appendChild(node);
}
}
f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
int[] bitsPerSample = null;
if(f != null) {
bitsPerSample = f.getAsInts();
} else {
f = getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION);
int compression = f != null ?
f.getAsInt(0) : BaselineTIFFTagSet.COMPRESSION_NONE;
if(getTIFFField(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER) !=
null ||
compression == BaselineTIFFTagSet.COMPRESSION_JPEG ||
compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG ||
getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) !=
null) {
f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
if(f != null &&
(f.getAsInt(0) ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO ||
f.getAsInt(0) ==
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO)) {
bitsPerSample = new int[] {8};
} else {
bitsPerSample = new int[] {8, 8, 8};
}
} else {
bitsPerSample = new int[] {1};
}
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bitsPerSample.length; i++) {
if (i > 0) {
sb.append(" ");
}
sb.append(Integer.toString(bitsPerSample[i]));
}
node = new IIOMetadataNode("BitsPerSample");
if(isPaletteColor) {
node.setAttribute("value", repeat(sb.toString(), 3));
} else {
node.setAttribute("value", sb.toString());
}
data_node.appendChild(node);
// SampleMSB
f = getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);
int fillOrder = f != null ?
f.getAsInt(0) : BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT;
sb = new StringBuffer();
for (int i = 0; i < bitsPerSample.length; i++) {
if (i > 0) {
sb.append(" ");
}
int maxBitIndex = bitsPerSample[i] == 1 ?
7 : bitsPerSample[i] - 1;
int msb =
fillOrder == BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT ?
maxBitIndex : 0;
sb.append(Integer.toString(msb));
}
node = new IIOMetadataNode("SampleMSB");
if(isPaletteColor) {
node.setAttribute("value", repeat(sb.toString(), 3));
} else {
node.setAttribute("value", sb.toString());
}
data_node.appendChild(node);
return data_node;
}
private static final String[] orientationNames = {
null,
"Normal",
"FlipH",
"Rotate180",
"FlipV",
"FlipHRotate90",
"Rotate270",
"FlipVRotate90",
"Rotate90",
};
public IIOMetadataNode getStandardDimensionNode() {
IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
IIOMetadataNode node = null; // scratch node
TIFFField f;
long[] xres = null;
long[] yres = null;
f = getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION);
if (f != null) {
xres = (long[])f.getAsRational(0).clone();
}
f = getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
if (f != null) {
yres = (long[])f.getAsRational(0).clone();
}
if (xres != null && yres != null) {
node = new IIOMetadataNode("PixelAspectRatio");
// Compute (1/xres)/(1/yres)
// (xres_denom/xres_num)/(yres_denom/yres_num) =
// (xres_denom/xres_num)*(yres_num/yres_denom) =
// (xres_denom*yres_num)/(xres_num*yres_denom)
float ratio = (float)((double)xres[1]*yres[0])/(xres[0]*yres[1]);
node.setAttribute("value", Float.toString(ratio));
dimension_node.appendChild(node);
}
if (xres != null || yres != null) {
// Get unit field.
f = getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT);
// Set resolution unit.
int resolutionUnit = f != null ?
f.getAsInt(0) : BaselineTIFFTagSet.RESOLUTION_UNIT_INCH;
// Have size if either centimeters or inches.
boolean gotPixelSize =
resolutionUnit != BaselineTIFFTagSet.RESOLUTION_UNIT_NONE;
// Convert pixels/inch to pixels/centimeter.
if (resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH) {
// Divide xres by 2.54
if (xres != null) {
xres[0] *= 100;
xres[1] *= 254;
}
// Divide yres by 2.54
if (yres != null) {
yres[0] *= 100;
yres[1] *= 254;
}
}
if (gotPixelSize) {
if (xres != null) {
float horizontalPixelSize = (float)(10.0*xres[1]/xres[0]);
node = new IIOMetadataNode("HorizontalPixelSize");
node.setAttribute("value",
Float.toString(horizontalPixelSize));
dimension_node.appendChild(node);
}
if (yres != null) {
float verticalPixelSize = (float)(10.0*yres[1]/yres[0]);
node = new IIOMetadataNode("VerticalPixelSize");
node.setAttribute("value",
Float.toString(verticalPixelSize));
dimension_node.appendChild(node);
}
}
}
f = getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT);
int resolutionUnit = f != null ?
f.getAsInt(0) : BaselineTIFFTagSet.RESOLUTION_UNIT_INCH;
if(resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH ||
resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER) {
f = getTIFFField(BaselineTIFFTagSet.TAG_X_POSITION);
if(f != null) {
long[] xpos = (long[])f.getAsRational(0);
float xPosition = (float)xpos[0]/(float)xpos[1];
// Convert to millimeters.
if(resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH) {
xPosition *= 254F;
} else {
xPosition *= 10F;
}
node = new IIOMetadataNode("HorizontalPosition");
node.setAttribute("value",
Float.toString(xPosition));
dimension_node.appendChild(node);
}
f = getTIFFField(BaselineTIFFTagSet.TAG_Y_POSITION);
if(f != null) {
long[] ypos = (long[])f.getAsRational(0);
float yPosition = (float)ypos[0]/(float)ypos[1];
// Convert to millimeters.
if(resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH) {
yPosition *= 254F;
} else {
yPosition *= 10F;
}
node = new IIOMetadataNode("VerticalPosition");
node.setAttribute("value",
Float.toString(yPosition));
dimension_node.appendChild(node);
}
}
f = getTIFFField(BaselineTIFFTagSet.TAG_ORIENTATION);
if (f != null) {
int o = f.getAsInt(0);
if (o >= 0 && o < orientationNames.length) {
node = new IIOMetadataNode("ImageOrientation");
node.setAttribute("value", orientationNames[o]);
dimension_node.appendChild(node);
}
}
return dimension_node;
}
public IIOMetadataNode getStandardDocumentNode() {
IIOMetadataNode document_node = new IIOMetadataNode("Document");
IIOMetadataNode node = null; // scratch node
TIFFField f;
node = new IIOMetadataNode("FormatVersion");
node.setAttribute("value", "6.0");
document_node.appendChild(node);
f = getTIFFField(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE);
if(f != null) {
int newSubFileType = f.getAsInt(0);
String value = null;
if((newSubFileType &
BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY) != 0) {
value = "TransparencyMask";
} else if((newSubFileType &
BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION) != 0) {
value = "ReducedResolution";
} else if((newSubFileType &
BaselineTIFFTagSet.NEW_SUBFILE_TYPE_SINGLE_PAGE) != 0) {
value = "SinglePage";
}
if(value != null) {
node = new IIOMetadataNode("SubimageInterpretation");
node.setAttribute("value", value);
document_node.appendChild(node);
}
}
f = getTIFFField(BaselineTIFFTagSet.TAG_DATE_TIME);
if (f != null) {
String s = f.getAsString(0);
// DateTime should be formatted as "YYYY:MM:DD hh:mm:ss".
if(s.length() == 19) {
node = new IIOMetadataNode("ImageCreationTime");
// Files with incorrect DateTime format have been
// observed so anticipate an exception from substring()
// and only add the node if the format is presumably
// correct.
boolean appendNode;
try {
node.setAttribute("year", s.substring(0, 4));
node.setAttribute("month", s.substring(5, 7));
node.setAttribute("day", s.substring(8, 10));
node.setAttribute("hour", s.substring(11, 13));
node.setAttribute("minute", s.substring(14, 16));
node.setAttribute("second", s.substring(17, 19));
appendNode = true;
} catch(IndexOutOfBoundsException e) {
appendNode = false;
}
if(appendNode) {
document_node.appendChild(node);
}
}
}
return document_node;
}
public IIOMetadataNode getStandardTextNode() {
IIOMetadataNode text_node = null;
IIOMetadataNode node = null; // scratch node
TIFFField f;
int[] textFieldTagNumbers = new int[] {
BaselineTIFFTagSet.TAG_DOCUMENT_NAME,
BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION,
BaselineTIFFTagSet.TAG_MAKE,
BaselineTIFFTagSet.TAG_MODEL,
BaselineTIFFTagSet.TAG_PAGE_NAME,
BaselineTIFFTagSet.TAG_SOFTWARE,
BaselineTIFFTagSet.TAG_ARTIST,
BaselineTIFFTagSet.TAG_HOST_COMPUTER,
BaselineTIFFTagSet.TAG_INK_NAMES,
BaselineTIFFTagSet.TAG_COPYRIGHT
};
for(int i = 0; i < textFieldTagNumbers.length; i++) {
f = getTIFFField(textFieldTagNumbers[i]);
if(f != null) {
String value = f.getAsString(0);
if(text_node == null) {
text_node = new IIOMetadataNode("Text");
}
node = new IIOMetadataNode("TextEntry");
node.setAttribute("keyword", f.getTag().getName());
node.setAttribute("value", value);
text_node.appendChild(node);
}
}
return text_node;
}
public IIOMetadataNode getStandardTransparencyNode() {
IIOMetadataNode transparency_node =
new IIOMetadataNode("Transparency");
IIOMetadataNode node = null; // scratch node
TIFFField f;
node = new IIOMetadataNode("Alpha");
String value = "none";
f = getTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES);
if(f != null) {
int[] extraSamples = f.getAsInts();
for(int i = 0; i < extraSamples.length; i++) {
if(extraSamples[i] ==
BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
value = "premultiplied";
break;
} else if(extraSamples[i] ==
BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA) {
value = "nonpremultiplied";
break;
}
}
}
node.setAttribute("value", value);
transparency_node.appendChild(node);
return transparency_node;
}
// Shorthand for throwing an IIOInvalidTreeException
private static void fatal(Node node, String reason)
throws IIOInvalidTreeException {
throw new IIOInvalidTreeException(reason, node);
}
private int[] listToIntArray(String list) {
StringTokenizer st = new StringTokenizer(list, " ");
ArrayList intList = new ArrayList();
while (st.hasMoreTokens()) {
String nextInteger = st.nextToken();
Integer nextInt = new Integer(nextInteger);
intList.add(nextInt);
}
int[] intArray = new int[intList.size()];
for(int i = 0; i < intArray.length; i++) {
intArray[i] = ((Integer)intList.get(i)).intValue();
}
return intArray;
}
private char[] listToCharArray(String list) {
StringTokenizer st = new StringTokenizer(list, " ");
ArrayList intList = new ArrayList();
while (st.hasMoreTokens()) {
String nextInteger = st.nextToken();
Integer nextInt = new Integer(nextInteger);
intList.add(nextInt);
}
char[] charArray = new char[intList.size()];
for(int i = 0; i < charArray.length; i++) {
charArray[i] = (char)((Integer)intList.get(i)).intValue();
}
return charArray;
}
private void mergeStandardTree(Node root)
throws IIOInvalidTreeException {
TIFFField f;
TIFFTag tag;
Node node = root;
if (!node.getNodeName()
.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
fatal(node, "Root must be " +
IIOMetadataFormatImpl.standardMetadataFormatName);
}
// Obtain the sample format and set the palette flag if appropriate.
String sampleFormat = null;
Node dataNode = getChildNode(root, "Data");
boolean isPaletteColor = false;
if(dataNode != null) {
Node sampleFormatNode = getChildNode(dataNode, "SampleFormat");
if(sampleFormatNode != null) {
sampleFormat = getAttribute(sampleFormatNode, "value");
isPaletteColor = sampleFormat.equals("Index");
}
}
// If palette flag not set check for palette.
if(!isPaletteColor) {
Node chromaNode = getChildNode(root, "Chroma");
if(chromaNode != null &&
getChildNode(chromaNode, "Palette") != null) {
isPaletteColor = true;
}
}
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
if (name.equals("Chroma")) {
String colorSpaceType = null;
String blackIsZero = null;
boolean gotPalette = false;
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("ColorSpaceType")) {
colorSpaceType = getAttribute(child, "name");
} else if (childName.equals("NumChannels")) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
int samplesPerPixel = isPaletteColor ?
1 : Integer.parseInt(getAttribute(child, "value"));
f = new TIFFField(tag, samplesPerPixel);
rootIFD.addTIFFField(f);
} else if (childName.equals("BlackIsZero")) {
blackIsZero = getAttribute(child, "value");
} else if (childName.equals("Palette")) {
Node entry = child.getFirstChild();
HashMap palette = new HashMap();
int maxIndex = -1;
while(entry != null) {
String entryName = entry.getNodeName();
if(entryName.equals("PaletteEntry")) {
String idx = getAttribute(entry, "index");
int id = Integer.parseInt(idx);
if(id > maxIndex) {
maxIndex = id;
}
char red =
(char)Integer.parseInt(getAttribute(entry,
"red"));
char green =
(char)Integer.parseInt(getAttribute(entry,
"green"));
char blue =
(char)Integer.parseInt(getAttribute(entry,
"blue"));
palette.put(new Integer(id),
new char[] {red, green, blue});
gotPalette = true;
}
entry = entry.getNextSibling();
}
if(gotPalette) {
int mapSize = maxIndex + 1;
int paletteLength = 3*mapSize;
char[] paletteEntries = new char[paletteLength];
Iterator paletteIter = palette.keySet().iterator();
while(paletteIter.hasNext()) {
Integer index = (Integer)paletteIter.next();
char[] rgb = (char[])palette.get(index);
int idx = index.intValue();
paletteEntries[idx] =
(char)((rgb[0]*65535)/255);
paletteEntries[mapSize + idx] =
(char)((rgb[1]*65535)/255);
paletteEntries[2*mapSize + idx] =
(char)((rgb[2]*65535)/255);
}
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_COLOR_MAP);
f = new TIFFField(tag, TIFFTag.TIFF_SHORT,
paletteLength, paletteEntries);
rootIFD.addTIFFField(f);
}
}
child = child.getNextSibling();
}
int photometricInterpretation = -1;
if((colorSpaceType == null || colorSpaceType.equals("GRAY")) &&
blackIsZero != null &&
blackIsZero.equalsIgnoreCase("FALSE")) {
photometricInterpretation =
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
} else if(colorSpaceType != null) {
if(colorSpaceType.equals("GRAY")) {
boolean isTransparency = false;
if(root instanceof IIOMetadataNode) {
IIOMetadataNode iioRoot = (IIOMetadataNode)root;
NodeList siNodeList =
iioRoot.getElementsByTagName("SubimageInterpretation");
if(siNodeList.getLength() == 1) {
Node siNode = siNodeList.item(0);
String value = getAttribute(siNode, "value");
if(value.equals("TransparencyMask")) {
isTransparency = true;
}
}
}
if(isTransparency) {
photometricInterpretation =
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK;
} else {
photometricInterpretation =
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
}
} else if(colorSpaceType.equals("RGB")) {
photometricInterpretation =
gotPalette ?
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR :
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
} else if(colorSpaceType.equals("YCbCr")) {
photometricInterpretation =
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR;
} else if(colorSpaceType.equals("CMYK")) {
photometricInterpretation =
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK;
} else if(colorSpaceType.equals("Lab")) {
photometricInterpretation =
BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB;
}
}
if(photometricInterpretation != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
f = new TIFFField(tag, photometricInterpretation);
rootIFD.addTIFFField(f);
}
} else if (name.equals("Compression")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("CompressionTypeName")) {
int compression = -1;
String compressionTypeName =
getAttribute(child, "value");
if(compressionTypeName.equalsIgnoreCase("None")) {
compression =
BaselineTIFFTagSet.COMPRESSION_NONE;
} else {
String[] compressionNames =
TIFFImageWriter.compressionTypes;
for(int i = 0; i < compressionNames.length; i++) {
if(compressionNames[i].equalsIgnoreCase(compressionTypeName)) {
compression =
TIFFImageWriter.compressionNumbers[i];
break;
}
}
}
if(compression != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_COMPRESSION);
f = new TIFFField(tag, compression);
rootIFD.addTIFFField(f);
// Lossless is irrelevant.
}
}
child = child.getNextSibling();
}
} else if (name.equals("Data")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("PlanarConfiguration")) {
String pc = getAttribute(child, "value");
int planarConfiguration = -1;
if(pc.equals("PixelInterleaved")) {
planarConfiguration =
BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY;
} else if(pc.equals("PlaneInterleaved")) {
planarConfiguration =
BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR;
}
if(planarConfiguration != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION);
f = new TIFFField(tag, planarConfiguration);
rootIFD.addTIFFField(f);
}
} else if (childName.equals("BitsPerSample")) {
String bps = getAttribute(child, "value");
char[] bitsPerSample = listToCharArray(bps);
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
if(isPaletteColor) {
f = new TIFFField(tag, TIFFTag.TIFF_SHORT, 1,
new char[] {bitsPerSample[0]});
} else {
f = new TIFFField(tag, TIFFTag.TIFF_SHORT,
bitsPerSample.length,
bitsPerSample);
}
rootIFD.addTIFFField(f);
} else if (childName.equals("SampleMSB")) {
// Add FillOrder only if lsb-to-msb (right to left)
// for all bands, i.e., SampleMSB is zero for all
// channels.
String sMSB = getAttribute(child, "value");
int[] sampleMSB = listToIntArray(sMSB);
boolean isRightToLeft = true;
for(int i = 0; i < sampleMSB.length; i++) {
if(sampleMSB[i] != 0) {
isRightToLeft = false;
break;
}
}
int fillOrder = isRightToLeft ?
BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT :
BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT;
tag =
rootIFD.getTag(BaselineTIFFTagSet.TAG_FILL_ORDER);
f = new TIFFField(tag, fillOrder);
rootIFD.addTIFFField(f);
}
child = child.getNextSibling();
}
} else if (name.equals("Dimension")) {
float pixelAspectRatio = -1.0f;
boolean gotPixelAspectRatio = false;
float horizontalPixelSize = -1.0f;
boolean gotHorizontalPixelSize = false;
float verticalPixelSize = -1.0f;
boolean gotVerticalPixelSize = false;
boolean sizeIsAbsolute = false;
float horizontalPosition = -1.0f;
boolean gotHorizontalPosition = false;
float verticalPosition = -1.0f;
boolean gotVerticalPosition = false;
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("PixelAspectRatio")) {
String par = getAttribute(child, "value");
pixelAspectRatio = Float.parseFloat(par);
gotPixelAspectRatio = true;
} else if (childName.equals("ImageOrientation")) {
String orientation = getAttribute(child, "value");
for (int i = 0; i < orientationNames.length; i++) {
if (orientation.equals(orientationNames[i])) {
char[] oData = new char[1];
oData[0] = (char)i;
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_ORIENTATION),
TIFFTag.TIFF_SHORT,
1,
oData);
rootIFD.addTIFFField(f);
break;
}
}
} else if (childName.equals("HorizontalPixelSize")) {
String hps = getAttribute(child, "value");
horizontalPixelSize = Float.parseFloat(hps);
gotHorizontalPixelSize = true;
} else if (childName.equals("VerticalPixelSize")) {
String vps = getAttribute(child, "value");
verticalPixelSize = Float.parseFloat(vps);
gotVerticalPixelSize = true;
} else if (childName.equals("HorizontalPosition")) {
String hp = getAttribute(child, "value");
horizontalPosition = Float.parseFloat(hp);
gotHorizontalPosition = true;
} else if (childName.equals("VerticalPosition")) {
String vp = getAttribute(child, "value");
verticalPosition = Float.parseFloat(vp);
gotVerticalPosition = true;
}
child = child.getNextSibling();
}
sizeIsAbsolute = gotHorizontalPixelSize ||
gotVerticalPixelSize;
// Fill in pixel size data from aspect ratio
if (gotPixelAspectRatio) {
if (gotHorizontalPixelSize && !gotVerticalPixelSize) {
verticalPixelSize =
horizontalPixelSize/pixelAspectRatio;
gotVerticalPixelSize = true;
} else if (gotVerticalPixelSize &&
!gotHorizontalPixelSize) {
horizontalPixelSize =
verticalPixelSize*pixelAspectRatio;
gotHorizontalPixelSize = true;
} else if (!gotHorizontalPixelSize &&
!gotVerticalPixelSize) {
horizontalPixelSize = pixelAspectRatio;
verticalPixelSize = 1.0f;
gotHorizontalPixelSize = true;
gotVerticalPixelSize = true;
}
}
// Compute pixels/centimeter
if (gotHorizontalPixelSize) {
float xResolution =
(sizeIsAbsolute ? 10.0f : 1.0f)/horizontalPixelSize;
long[][] hData = new long[1][2];
hData[0] = new long[2];
hData[0][0] = (long)(xResolution*10000.0f);
hData[0][1] = (long)10000;
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION),
TIFFTag.TIFF_RATIONAL,
1,
hData);
rootIFD.addTIFFField(f);
}
if (gotVerticalPixelSize) {
float yResolution =
(sizeIsAbsolute ? 10.0f : 1.0f)/verticalPixelSize;
long[][] vData = new long[1][2];
vData[0] = new long[2];
vData[0][0] = (long)(yResolution*10000.0f);
vData[0][1] = (long)10000;
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION),
TIFFTag.TIFF_RATIONAL,
1,
vData);
rootIFD.addTIFFField(f);
}
// Emit ResolutionUnit tag
char[] res = new char[1];
res[0] = (char)(sizeIsAbsolute ?
BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER :
BaselineTIFFTagSet.RESOLUTION_UNIT_NONE);
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT),
TIFFTag.TIFF_SHORT,
1,
res);
rootIFD.addTIFFField(f);
// Position
if(sizeIsAbsolute) {
if(gotHorizontalPosition) {
// Convert from millimeters to centimeters via
// numerator multiplier = denominator/10.
long[][] hData = new long[1][2];
hData[0][0] = (long)(horizontalPosition*10000.0f);
hData[0][1] = (long)100000;
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_X_POSITION),
TIFFTag.TIFF_RATIONAL,
1,
hData);
rootIFD.addTIFFField(f);
}
if(gotVerticalPosition) {
// Convert from millimeters to centimeters via
// numerator multiplier = denominator/10.
long[][] vData = new long[1][2];
vData[0][0] = (long)(verticalPosition*10000.0f);
vData[0][1] = (long)100000;
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_POSITION),
TIFFTag.TIFF_RATIONAL,
1,
vData);
rootIFD.addTIFFField(f);
}
}
} else if (name.equals("Document")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("SubimageInterpretation")) {
String si = getAttribute(child, "value");
int newSubFileType = -1;
if(si.equals("TransparencyMask")) {
newSubFileType =
BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY;
} else if(si.equals("ReducedResolution")) {
newSubFileType =
BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION;
} else if(si.equals("SinglePage")) {
newSubFileType =
BaselineTIFFTagSet.NEW_SUBFILE_TYPE_SINGLE_PAGE;
}
if(newSubFileType != -1) {
tag =
rootIFD.getTag(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE);
f = new TIFFField(tag, newSubFileType);
rootIFD.addTIFFField(f);
}
}
if (childName.equals("ImageCreationTime")) {
String year = getAttribute(child, "year");
String month = getAttribute(child, "month");
String day = getAttribute(child, "day");
String hour = getAttribute(child, "hour");
String minute = getAttribute(child, "minute");
String second = getAttribute(child, "second");
StringBuffer sb = new StringBuffer();
sb.append(year);
sb.append(":");
if(month.length() == 1) {
sb.append("0");
}
sb.append(month);
sb.append(":");
if(day.length() == 1) {
sb.append("0");
}
sb.append(day);
sb.append(" ");
if(hour.length() == 1) {
sb.append("0");
}
sb.append(hour);
sb.append(":");
if(minute.length() == 1) {
sb.append("0");
}
sb.append(minute);
sb.append(":");
if(second.length() == 1) {
sb.append("0");
}
sb.append(second);
String[] dt = new String[1];
dt[0] = sb.toString();
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_DATE_TIME),
TIFFTag.TIFF_ASCII,
1,
dt);
rootIFD.addTIFFField(f);
}
child = child.getNextSibling();
}
} else if (name.equals("Text")) {
Node child = node.getFirstChild();
String theAuthor = null;
String theDescription = null;
String theTitle = null;
while (child != null) {
String childName = child.getNodeName();
if(childName.equals("TextEntry")) {
int tagNumber = -1;
NamedNodeMap childAttrs = child.getAttributes();
Node keywordNode = childAttrs.getNamedItem("keyword");
if(keywordNode != null) {
String keyword = keywordNode.getNodeValue();
String value = getAttribute(child, "value");
if(!keyword.equals("") && !value.equals("")) {
if(keyword.equalsIgnoreCase("DocumentName")) {
tagNumber =
BaselineTIFFTagSet.TAG_DOCUMENT_NAME;
} else if(keyword.equalsIgnoreCase("ImageDescription")) {
tagNumber =
BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION;
} else if(keyword.equalsIgnoreCase("Make")) {
tagNumber =
BaselineTIFFTagSet.TAG_MAKE;
} else if(keyword.equalsIgnoreCase("Model")) {
tagNumber =
BaselineTIFFTagSet.TAG_MODEL;
} else if(keyword.equalsIgnoreCase("PageName")) {
tagNumber =
BaselineTIFFTagSet.TAG_PAGE_NAME;
} else if(keyword.equalsIgnoreCase("Software")) {
tagNumber =
BaselineTIFFTagSet.TAG_SOFTWARE;
} else if(keyword.equalsIgnoreCase("Artist")) {
tagNumber =
BaselineTIFFTagSet.TAG_ARTIST;
} else if(keyword.equalsIgnoreCase("HostComputer")) {
tagNumber =
BaselineTIFFTagSet.TAG_HOST_COMPUTER;
} else if(keyword.equalsIgnoreCase("InkNames")) {
tagNumber =
BaselineTIFFTagSet.TAG_INK_NAMES;
} else if(keyword.equalsIgnoreCase("Copyright")) {
tagNumber =
BaselineTIFFTagSet.TAG_COPYRIGHT;
} else if(keyword.equalsIgnoreCase("author")) {
theAuthor = value;
} else if(keyword.equalsIgnoreCase("description")) {
theDescription = value;
} else if(keyword.equalsIgnoreCase("title")) {
theTitle = value;
}
if(tagNumber != -1) {
f = new TIFFField(rootIFD.getTag(tagNumber),
TIFFTag.TIFF_ASCII,
1,
new String[] {value});
rootIFD.addTIFFField(f);
}
}
}
}
child = child.getNextSibling();
} // child != null
if(theAuthor != null &&
getTIFFField(BaselineTIFFTagSet.TAG_ARTIST) == null) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_ARTIST),
TIFFTag.TIFF_ASCII,
1,
new String[] {theAuthor});
rootIFD.addTIFFField(f);
}
if(theDescription != null &&
getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION) == null) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION),
TIFFTag.TIFF_ASCII,
1,
new String[] {theDescription});
rootIFD.addTIFFField(f);
}
if(theTitle != null &&
getTIFFField(BaselineTIFFTagSet.TAG_DOCUMENT_NAME) == null) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_DOCUMENT_NAME),
TIFFTag.TIFF_ASCII,
1,
new String[] {theTitle});
rootIFD.addTIFFField(f);
}
} else if (name.equals("Transparency")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("Alpha")) {
String alpha = getAttribute(child, "value");
f = null;
if (alpha.equals("premultiplied")) {
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES),
BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA);
} else if (alpha.equals("nonpremultiplied")) {
f = new TIFFField(
rootIFD.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES),
BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA);
}
if (f != null) {
rootIFD.addTIFFField(f);
}
}
child = child.getNextSibling();
}
}
node = node.getNextSibling();
}
// Set SampleFormat.
if(sampleFormat != null) {
// Derive the value.
int sf = -1;
if(sampleFormat.equals("SignedIntegral")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER;
} else if(sampleFormat.equals("UnsignedIntegral")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER;
} else if(sampleFormat.equals("Real")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT;
} else if(sampleFormat.equals("Index")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER;
}
if(sf != -1) {
// Derive the count.
int count = 1;
// Try SamplesPerPixel first.
f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
if(f != null) {
count = f.getAsInt(0);
} else {
// Try BitsPerSample.
f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
if(f != null) {
count = f.getCount();
}
}
char[] sampleFormatArray = new char[count];
Arrays.fill(sampleFormatArray, (char)sf);
// Add SampleFormat.
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT);
f = new TIFFField(tag, TIFFTag.TIFF_SHORT,
sampleFormatArray.length, sampleFormatArray);
rootIFD.addTIFFField(f);
}
}
}
private static String getAttribute(Node node, String attrName) {
NamedNodeMap attrs = node.getAttributes();
Node attr = attrs.getNamedItem(attrName);
return attr != null ? attr.getNodeValue() : null;
}
private Node getChildNode(Node node, String childName) {
Node childNode = null;
if(node.hasChildNodes()) {
NodeList childNodes = node.getChildNodes();
int length = childNodes.getLength();
for(int i = 0; i < length; i++) {
Node item = childNodes.item(i);
if(item.getNodeName().equals(childName)) {
childNode = item;
break;
}
}
}
return childNode;
}
public static TIFFIFD parseIFD(Node node) throws IIOInvalidTreeException {
if (!node.getNodeName().equals("TIFFIFD")) {
fatal(node, "Expected \"TIFFIFD\" node");
}
String tagSetNames = getAttribute(node, "tagSets");
List tagSets = new ArrayList(5);
if (tagSetNames != null) {
StringTokenizer st = new StringTokenizer(tagSetNames, ",");
while (st.hasMoreTokens()) {
String className = st.nextToken();
if(className != null) {
className = className.replace(SUN_BaselineTIFFTagSetClassName, THISJAI_BaselineTIFFTagSetClassName);
}
Object o = null;
try {
Class setClass = Class.forName(className);
Method getInstanceMethod =
setClass.getMethod("getInstance", (Class[])null);
o = getInstanceMethod.invoke(null, (Object[])null);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
if (!(o instanceof TIFFTagSet)) {
fatal(node, "Specified tag set class \"" +
className +
"\" is not an instance of TIFFTagSet");
} else {
tagSets.add((TIFFTagSet)o);
}
}
}
TIFFIFD ifd = new TIFFIFD(tagSets);
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
TIFFField f = null;
if (name.equals("TIFFIFD")) {
TIFFIFD subIFD = parseIFD(node);
String parentTagName = getAttribute(node, "parentTagName");
String parentTagNumber = getAttribute(node, "parentTagNumber");
TIFFTag tag = null;
if(parentTagName != null) {
tag = TIFFIFD.getTag(parentTagName, tagSets);
} else if(parentTagNumber != null) {
int tagNumber =
Integer.valueOf(parentTagNumber).intValue();
tag = TIFFIFD.getTag(tagNumber, tagSets);
}
if(tag == null) {
tag = new TIFFTag("unknown", 0, 0, null);
}
int type;
if (tag.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER)) {
type = TIFFTag.TIFF_IFD_POINTER;
} else {
type = TIFFTag.TIFF_LONG;
}
f = new TIFFField(tag, type, 1, subIFD);
} else if (name.equals("TIFFField")) {
int number = Integer.parseInt(getAttribute(node, "number"));
TIFFTagSet tagSet = null;
Iterator iter = tagSets.iterator();
while (iter.hasNext()) {
TIFFTagSet t = (TIFFTagSet)iter.next();
if (t.getTag(number) != null) {
tagSet = t;
break;
}
}
f = TIFFField.createFromMetadataNode(tagSet, node);
} else {
fatal(node,
"Expected either \"TIFFIFD\" or \"TIFFField\" node, got "
+ name);
}
ifd.addTIFFField(f);
node = node.getNextSibling();
}
return ifd;
}
private void mergeNativeTree(Node root) throws IIOInvalidTreeException {
Node node = root;
if (!node.getNodeName().equals(nativeMetadataFormatName)) {
fatal(node, "Root must be " + nativeMetadataFormatName);
}
node = node.getFirstChild();
if (node == null || !node.getNodeName().equals("TIFFIFD")) {
fatal(root, "Root must have \"TIFFIFD\" child");
}
TIFFIFD ifd = parseIFD(node);
List rootIFDTagSets = rootIFD.getTagSetList();
Iterator tagSetIter = ifd.getTagSetList().iterator();
while(tagSetIter.hasNext()) {
Object o = tagSetIter.next();
if(o instanceof TIFFTagSet && !rootIFDTagSets.contains(o)) {
rootIFD.addTagSet((TIFFTagSet)o);
}
}
Iterator ifdIter = ifd.iterator();
while(ifdIter.hasNext()) {
TIFFField field = (TIFFField)ifdIter.next();
rootIFD.addTIFFField(field);
}
}
public void mergeTree(String formatName, Node root)
throws IIOInvalidTreeException{
if (formatName.equals(nativeMetadataFormatName)) {
if (root == null) {
throw new IllegalArgumentException("root == null!");
}
mergeNativeTree(root);
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
if (root == null) {
throw new IllegalArgumentException("root == null!");
}
mergeStandardTree(root);
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
public void reset() {
rootIFD = new TIFFIFD(tagSets);
}
public TIFFIFD getRootIFD() {
return rootIFD;
}
public TIFFField getTIFFField(int tagNumber) {
return rootIFD.getTIFFField(tagNumber);
}
public void removeTIFFField(int tagNumber) {
rootIFD.removeTIFFField(tagNumber);
}
/**
* Returns a TIFFImageMetadata
wherein all fields in the
* root IFD from the BaselineTIFFTagSet
are copied by value
* and all other fields copied by reference.
*/
public TIFFImageMetadata getShallowClone() {
return new TIFFImageMetadata(rootIFD.getShallowClone());
}
}