All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jaiimageio.plugins.tiff.TIFFDirectory Maven / Gradle / Ivy

Go to download

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: TIFFDirectory.java,v $
 *
 * 
 * Copyright (c) 2006 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.4 $
 * $Date: 2006/08/25 00:16:49 $
 * $State: Exp $
 */
package com.github.jaiimageio.plugins.tiff;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;

import com.github.jaiimageio.impl.plugins.tiff.TIFFIFD;
import com.github.jaiimageio.impl.plugins.tiff.TIFFImageMetadata;

/**
 * A convenience class for simplifying interaction with TIFF native
 * image metadata. A TIFF image metadata tree represents an Image File
 * Directory (IFD) from a TIFF 6.0 stream. An IFD consists of a number of
 * IFD Entries each of which associates an identifying tag number with
 * a compatible value. A TIFFDirectory instance corresponds
 * to an IFD and contains a set of {@link TIFFField}s each of which
 * corresponds to an IFD Entry in the IFD.
 *
 * 

When reading, a TIFFDirectory may be created by passing * the value returned by {@link javax.imageio.ImageReader#getImageMetadata * ImageReader.getImageMetadata()} to {@link #createFromMetadata * createFromMetadata()}. The {@link TIFFField}s in the directory may then * be obtained using the accessor methods provided in this class.

* *

When writing, an {@link IIOMetadata} object for use by one of the * write() methods of {@link javax.imageio.ImageWriter} may be * created from a TIFFDirectory by {@link #getAsMetadata()}. * The TIFFDirectory itself may be created by construction or * from the IIOMetadata object returned by * {@link javax.imageio.ImageWriter#getDefaultImageMetadata * ImageWriter.getDefaultImageMetadata()}. The TIFFFields in the * directory may be set using the mutator methods provided in this class.

* *

A TIFFDirectory is aware of the tag numbers in the * group of {@link TIFFTagSet}s associated with it. When * a TIFFDirectory is created from a native image metadata * object, these tag sets are derived from the tagSets attribute * of the TIFFIFD node.

* *

A TIFFDirectory might also have a parent {@link TIFFTag}. * This will occur if the directory represents an IFD other than the root * IFD of the image. The parent tag is the tag of the IFD Entry which is a * pointer to the IFD represented by this TIFFDirectory. The * {@link TIFFTag#isIFDPointer} method of this parent TIFFTag * must return true. When a TIFFDirectory is * created from a native image metadata object, the parent tag set is set * from the parentTagName attribute of the corresponding * TIFFIFD node. Note that a TIFFDirectory instance * which has a non-null parent tag will be contained in the * data field of a TIFFField instance which has a tag field * equal to the contained directory's parent tag.

* *

As an example consider an EXIF image. The TIFFDirectory * instance corresponding to the EXIF IFD in the EXIF stream would have parent * tag {@link EXIFParentTIFFTagSet#TAG_EXIF_IFD_POINTER TAG_EXIF_IFD_POINTER} * and would include {@link EXIFTIFFTagSet} in its group of known tag sets. * The TIFFDirectory corresponding to this EXIF IFD will be * contained in the data field of a TIFFField which will in turn * be contained in the TIFFDirectory corresponding to the primary * IFD of the EXIF image which will itself have a null-valued * parent tag.

* *

Note that this implementation is not synchronized. If multiple * threads use a TIFFDirectory instance concurrently, and at * least one of the threads modifies the directory, for example, by adding * or removing TIFFFields or TIFFTagSets, it * must be synchronized externally.

* * @see IIOMetadata * @see TIFFField * @see TIFFTag * @see TIFFTagSet * * @since 1.1-beta */ // XXX doc: not thread safe public class TIFFDirectory implements Cloneable { /** The largest low-valued tag number in the TIFF 6.0 specification. */ private static final int MAX_LOW_FIELD_TAG_NUM = BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE; /** The TIFFTagSets associated with this directory. */ private List tagSets; /** The parent TIFFTag of this directory. */ private TIFFTag parentTag; /** * The fields in this directory which have a low tag number. These are * managed as an array for efficiency as they are the most common fields. */ private TIFFField[] lowFields = new TIFFField[MAX_LOW_FIELD_TAG_NUM + 1]; /** The number of low tag numbered fields in the directory. */ private int numLowFields = 0; /** * A mapping of Integer tag numbers to TIFFFields * for fields which are not low tag numbered. */ private Map highFields = new TreeMap(); /** * Creates a TIFFDirectory instance from the contents of * an image metadata object. The supplied object must support an image * metadata format supported by the TIFF {@link javax.imageio.ImageWriter} * plug-in. This will usually be either the TIFF native image metadata * format com_sun_media_imageio_plugins_tiff_1.0 or the Java * Image I/O standard metadata format javax_imageio_1.0. * * @param tiffImageMetadata A metadata object which supports a compatible * image metadata format. * * @return A TIFFDirectory populated from the contents of * the supplied metadata object. * * @throws IllegalArgumentException if tiffImageMetadata * is null. * @throws IllegalArgumentException if tiffImageMetadata * does not support a compatible image metadata format. * @throws IIOInvalidTreeException if the supplied metadata object * cannot be parsed. */ public static TIFFDirectory createFromMetadata(IIOMetadata tiffImageMetadata) throws IIOInvalidTreeException { if(tiffImageMetadata == null) { throw new IllegalArgumentException("tiffImageMetadata == null"); } TIFFImageMetadata tim; if(tiffImageMetadata instanceof TIFFImageMetadata) { tim = (TIFFImageMetadata)tiffImageMetadata; } else { // Create a native metadata object. ArrayList l = new ArrayList(1); l.add(BaselineTIFFTagSet.getInstance()); tim = new TIFFImageMetadata(l); // Determine the format name to use. String formatName = null; if(TIFFImageMetadata.nativeMetadataFormatName.equals (tiffImageMetadata.getNativeMetadataFormatName())) { formatName = TIFFImageMetadata.nativeMetadataFormatName; } else { String[] extraNames = tiffImageMetadata.getExtraMetadataFormatNames(); if(extraNames != null) { for(int i = 0; i < extraNames.length; i++) { if(TIFFImageMetadata.nativeMetadataFormatName.equals (extraNames[i])) { formatName = extraNames[i]; break; } } } if(formatName == null) { if(tiffImageMetadata.isStandardMetadataFormatSupported()) { formatName = IIOMetadataFormatImpl.standardMetadataFormatName; } else { throw new IllegalArgumentException ("Parameter does not support required metadata format!"); } } } // Set the native metadata object from the tree. tim.setFromTree(formatName, tiffImageMetadata.getAsTree(formatName)); } return tim.getRootIFD(); } /** * Converts a TIFFDirectory to a TIFFIFD. */ private static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) { if(dir instanceof TIFFIFD) { return (TIFFIFD)dir; } TIFFIFD ifd = new TIFFIFD(Arrays.asList(dir.getTagSets()), dir.getParentTag()); TIFFField[] fields = dir.getTIFFFields(); int numFields = fields.length; for(int i = 0; i < numFields; i++) { TIFFField f = fields[i]; TIFFTag tag = f.getTag(); if(tag.isIFDPointer()) { TIFFDirectory subIFD = getDirectoryAsIFD((TIFFDirectory)f.getData()); f = new TIFFField(tag, f.getType(), f.getCount(), subIFD); } ifd.addTIFFField(f); } return ifd; } /** * Constructs a TIFFDirectory which is aware of a given * group of {@link TIFFTagSet}s. An optional parent {@link TIFFTag} * may also be specified. * * @param tagSets The TIFFTagSets associated with this * directory. * @param parentTag The parent TIFFTag of this directory; * may be null. * @throws IllegalArgumentException if tagSets is * null. */ public TIFFDirectory(TIFFTagSet[] tagSets, TIFFTag parentTag) { if(tagSets == null) { throw new IllegalArgumentException("tagSets == null!"); } this.tagSets = new ArrayList(tagSets.length); int numTagSets = tagSets.length; for(int i = 0; i < numTagSets; i++) { this.tagSets.add(tagSets[i]); } this.parentTag = parentTag; } /** * Returns the {@link TIFFTagSet}s of which this directory is aware. * * @return The TIFFTagSets associated with this * TIFFDirectory. */ public TIFFTagSet[] getTagSets() { return (TIFFTagSet[])tagSets.toArray(new TIFFTagSet[tagSets.size()]); } /** * Adds an element to the group of {@link TIFFTagSet}s of which this * directory is aware. * * @param tagSet The TIFFTagSet to add. * @throws IllegalArgumentException if tagSet is * null. */ public void addTagSet(TIFFTagSet tagSet) { if(tagSet == null) { throw new IllegalArgumentException("tagSet == null"); } if(!tagSets.contains(tagSet)) { tagSets.add(tagSet); } } /** * Removes an element from the group of {@link TIFFTagSet}s of which this * directory is aware. * * @param tagSet The TIFFTagSet to remove. * @throws IllegalArgumentException if tagSet is * null. */ public void removeTagSet(TIFFTagSet tagSet) { if(tagSet == null) { throw new IllegalArgumentException("tagSet == null"); } if(tagSets.contains(tagSet)) { tagSets.remove(tagSet); } } /** * Returns the parent {@link TIFFTag} of this directory if one * has been defined or null otherwise. * * @return The parent TIFFTag of this * TIFFDiectory or null. */ public TIFFTag getParentTag() { return parentTag; } /** * Returns the {@link TIFFTag} which has tag number equal to * tagNumber or null if no such tag * exists in the {@link TIFFTagSet}s associated with this * directory. * * @param tagNumber The tag number of interest. * @return The corresponding TIFFTag or null. */ public TIFFTag getTag(int tagNumber) { return TIFFIFD.getTag(tagNumber, tagSets); } /** * Returns the number of {@link TIFFField}s in this directory. * * @return The number of TIFFFields in this * TIFFDirectory. */ public int getNumTIFFFields() { return numLowFields + highFields.size(); } /** * Determines whether a TIFF field with the given tag number is * contained in this directory. * * @return Whether a {@link TIFFTag} with tag number equal to * tagNumber is present in this TIFFDirectory. */ public boolean containsTIFFField(int tagNumber) { return (tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM && lowFields[tagNumber] != null) || highFields.containsKey(new Integer(tagNumber)); } /** * Adds a TIFF field to the directory. * * @param f The field to add. * @throws IllegalArgumentException if f is null. */ public void addTIFFField(TIFFField f) { if(f == null) { throw new IllegalArgumentException("f == null"); } int tagNumber = f.getTagNumber(); if(tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM) { if(lowFields[tagNumber] == null) { numLowFields++; } lowFields[tagNumber] = f; } else { highFields.put(new Integer(tagNumber), f); } } /** * Retrieves a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. * @return A TIFFField with the requested tag number of * null if no such field is present. */ public TIFFField getTIFFField(int tagNumber) { TIFFField f; if(tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM) { f = lowFields[tagNumber]; } else { f = (TIFFField)highFields.get(new Integer(tagNumber)); } return f; } /** * Removes a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. */ public void removeTIFFField(int tagNumber) { if(tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM) { if(lowFields[tagNumber] != null) { numLowFields--; lowFields[tagNumber] = null; } } else { highFields.remove(new Integer(tagNumber)); } } /** * Retrieves all TIFF fields from the directory. * * @return An array of all TIFF fields in order of numerically increasing * tag number. */ public TIFFField[] getTIFFFields() { // Allocate return value. TIFFField[] fields = new TIFFField[numLowFields + highFields.size()]; // Copy any low-index fields. int nextIndex = 0; for(int i = 0; i <= MAX_LOW_FIELD_TAG_NUM; i++) { if(lowFields[i] != null) { fields[nextIndex++] = lowFields[i]; if(nextIndex == numLowFields) break; } } // Copy any high-index fields. if(!highFields.isEmpty()) { Iterator keys = highFields.keySet().iterator(); while(keys.hasNext()) { fields[nextIndex++] = (TIFFField)highFields.get(keys.next()); } } return fields; } /** * Removes all TIFF fields from the directory. */ public void removeTIFFFields() { Arrays.fill(lowFields, (Object)null); numLowFields = 0; highFields.clear(); } /** * Converts the directory to a metadata object. * * @return A metadata instance initialized from the contents of this * TIFFDirectory. */ public IIOMetadata getAsMetadata() { return new TIFFImageMetadata(getDirectoryAsIFD(this)); } /** * Clones the directory and all the fields contained therein. * * @return A clone of this TIFFDirectory. */ public Object clone() { TIFFDirectory dir = new TIFFDirectory(getTagSets(), getParentTag()); TIFFField[] fields = getTIFFFields(); int numFields = fields.length; for(int i = 0; i < numFields; i++) { dir.addTIFFField(fields[i]); } return dir; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy