See: Description
Reading Images
Writing Images
Native Stream Metadata Format
Native Image Metadata Format
ImageReader
which may be
controlled by its public interface as well as via a supplied
TIFFImageReadParam
.
TIFFDecompressor
object may be
supplied via
TIFFImageReadParam.setTIFFDecompressor()
.
If a TIFFDecompressor
is specified
in this manner it will be used and will supersede any internal decompressor
which might otherwise have been used for a known compression type. This
mechanism allows for compression types to be handled by user-defined
decompressors whether or not that compression type is known to the plug-in.
TIFFColorConverter
object may be
supplied via
TIFFImageReadParam.setColorConverter()
.
If a TIFFColorConverter
is specified
in this manner it will be used and will supersede any internal color converter
which might otherwise have been used. This color converter will be used to
convert the source image data to an RGB color space.
If no user-supplied color converter is available, the source image data have photometric type CIE L*a*b* or YCbCr, and the destination color space type is RGB, then the source image data will be automatically converted to RGB using an internal color converter.
ImageTypeSpecifier
, will be
the first among the following which applies:
The normalized color coordinate transformations used for the default CMYK color space are defined as follows:
R = (1 - K)*(1 - C) G = (1 - K)*(1 - M) B = (1 - K)*(1 - Y)
K = min{1 - R, 1 - G, 1 - B} if(K != 1) { C = (1 - R - K)/(1 - K) M = (1 - G - K)/(1 - K) Y = (1 - B - K)/(1 - K) } else { C = M = Y = 0 }
The generic color space used when no other color space can be inferred is provided merely to enable the data to be loaded. It is not intended to provide accurate conversions of any kind.
If the data are known to be in a color space not correctly handled by the
foregoing, then an ImageTypeSpecifier
should be supplied
to the reader and should be derived from a color space which is correct for
the data in question.
BaselineTIFFTagSet.TAG_ICC_PROFILE
,
tag number 34675), an attempt will be made to use it to create the color space
of the loaded image. It will be used if the data layout is of component type
and the number of samples per pixel equals or is one greater than the number
of components described by the ICC profile. If the ICC profile is not used
then the color space will be inferred in one of the subsequent steps described
above.
If for some reason the embedded ICC profile is not used automatically, then it may be used manually by following this procedure:
ImageReader.getImageMetadata(int)
ICC_ColorSpace
from an
ICC_Profile
created from the ICC profile field data
using ICC_Profile.getInstance(byte[])
.ImageTypeSpecifier
from the new color
space using one of its factory methods which accepts an
ICC_ColorSpace
.
ImageReadParam
and set the
ImageTypeSpecifier
using
ImageReadParam.setDestinationType(javax.imageio.ImageTypeSpecifier)
.read
method.If the inferred color space not based on the ICC Profile field is compatible
with the ICC profile-based color space, then a second
ImageTypeSpecifier
derived from this inferred color
space will be included in the Iterator
returned by
ImageReader.getImageTypes(int)
. If the iterator contains
more than one type, the first one will be based on the ICC profile and the
second on the inferred color space.
ignoreMetadata
parameter of
javax.imageio.ImageReader.setInput()
. It is
informed of which TIFFTag
s to
recognize or not to recognize via
TIFFImageReadParam.addAllowedTagSet()
and
TIFFImageReadParam.removeAllowedTagSet()
.
If ignoreMetadata
is true
, then the reader will
load into the native image metadata object only those fields which have a
TIFFTag
contained in the one of the allowed
TIFFTagSet
s.
Use of a TIFFDirectory
object
may simplify gaining access to metadata values. An instance of
TIFFDirectory
may be created from the IIOMetadata
object returned by the TIFF reader using the
TIFFDirectory.createFromMetadata()
method.
javax_imageio_1.0
elements from TIFF native image metadata is given
in the following table.
Standard Metadata Element | Derivation from TIFF Fields |
---|---|
/Chroma/ColorSpaceType@name | PhotometricInterpretation: WhiteIsZero, BlackIsZero, TransparencyMask = "GRAY"; RGB, PaletteColor => "RGB"; CMYK => "CMYK"; YCbCr => "YCbCr"; CIELab, ICCLab => "Lab". |
/Chroma/NumChannels@value | SamplesPerPixel |
/Chroma/BlackIsZero@value | "TRUE" <=> PhotometricInterpretation => WhiteIsZero |
/Chroma/Palette | ColorMap |
/Compression/CompressionTypeName@value | Compression: Uncompressed => "none"; CCITT 1D => "CCITT RLE"; Group 3 Fax => "CCITT T.4"; Group 4 Fax => "CCITT T.6"; LZW => "LZW"; JPEG => "Old JPEG"; New JPEG => "JPEG"; Zlib =>> "ZLib"; PackBits => "PackBits"; Deflate => "Deflate"; EXIF JPEG => "JPEG". |
/Compression/Lossless@value | Compression: JPEG or New JPEG => "FALSE"; otherwise "TRUE". |
/Data/PlanarConfiguration@value | Chunky => "PixelInterleaved"; Planar => "PlaneInterleaved". |
/Data/SampleFormat@value | PhotometricInterpretation PaletteColor => "Index"; SampleFormat unsigned integer data => "UnsignedIntegral"; SampleFormat two's complement signed integer data => "SignedIntegral"; SampleFormat IEEE floating point data => "Real"; otherwise element not emitted. |
/Data/BitsPerSample@value | BitsPerSample as a space-separated list. |
/Data/SampleMSB@value | FillOrder: left-to-right => space-separated list of BitsPerSample-1; right-to-left => space-separated list of 0s. |
/Dimension/PixelAspectRatio@value | (1/XResolution)/(1/YResolution) |
/Dimension/ImageOrientation@value | Orientation |
/Dimension/HorizontalPixelSize@value | 1/XResolution in millimeters if ResolutionUnit is not None. |
/Dimension/VerticalPixelSize@value | 1/YResolution in millimeters if ResolutionUnit is not None. |
/Dimension/HorizontalPosition@value | XPosition in millimeters if ResolutionUnit is not None. |
/Dimension/VerticalPosition@value | YPosition in millimeters if ResolutionUnit is not None. |
/Document/FormatVersion@value | 6.0 |
/Document/SubimageInterpretation@value | NewSubFileType: transparency => "TransparencyMask"; reduced-resolution => "ReducedResolution"; single page => "SinglePage". |
/Document/ImageCreationTime@value | DateTime |
/Text/TextEntry | DocumentName, ImageDescription, Make, Model, PageName, Software,
Artist, HostComputer, InkNames, Copyright:
/Text/TextEntry@keyword = field name,
/Text/TextEntry@value = field value. Example: TIFF Software field => /Text/TextEntry@keyword = "Software", /Text/TextEntry@value = Name and version number of the software package(s) used to create the image. |
/Transparency/Alpha@value | ExtraSamples: associated alpha => "premultiplied"; unassociated alpha => "nonpremultiplied". |
ImageReader
methods may be used to read the image
data and metadata:
ImageReader tiffReader;
ImageInputStream input;
ImageReadParam readParam;
tiffReader.setInput(input);
// Read primary image and IFD.
BufferedImage image = tiffReader.read(0, readParam);
IIOMetadata primaryIFD = tiffReader.getImageMetadata(0);
// Read thumbnail and IFD if present.
BufferedImage thumbnail = null;
IIOMetadata thumbnailIFD = null;
if(tiffReader.getNumImages(true) > 1) {
thumbnail = tiffReader.read(1, readParam);
thumbnailIFD = tiffReader.getImageMetadata(1);
}
Note that the EXIF thumbnail is treated as a separate page in the TIFF
stream and not as a thumbnail, i.e.,
tiffReader.hasThumbnails(0)
will return false
.
{'E', 'x', 'i', 'f', 0x00, 0x00}
followed
by a complete TIFF stream. The embedded TIFF stream contains a primary IFD
describing the JPEG image optionally followed by a thumbnail IFD and
compressed or uncompressed thumbnail image data. Note that the embedded TIFF
stream does not contain any image data associated with the primary IFD
nor any descriptive fields which duplicate information found in the JPEG
stream itself.
The parameter content of the APP1 marker segment may be obtained
from the user object of the associated Node
in a
javax_imageio_jpeg_image_1.0 native image metadata tree extracted
from the image metadata object returned by the JPEG reader. This node will
have name unknown and an attribute named MarkerTag with
integral value 0xE1
(String
value
"225"
). The primary IFD and the thumbnail IFD and image may be
read from the user object by the usual ImageReader
methods:
ImageReader tiffReader;
ImageReadParam readParam;
IIOMetadataNode app1EXIFNode;
// Set up input skipping EXIF ID 6-byte sequence.
byte[] app1Params = (byte[])app1EXIFNode.getUserObject();
MemoryCacheImageInputStream app1EXIFInput =
new MemoryCacheImageInputStream(new ByteArrayInputStream(app1Params, 6,
app1Params.length - 6));
tiffReader.setInput(app1EXIFInput);
// Read primary IFD.
IIOMetadata primaryIFD = tiffReader.getImageMetadata(0);
// Read thumbnail and IFD if present.
BufferedImage thumbnail = null;
IIOMetadata thumbnailIFD = null;
if(tiffReader.getNumImages(true) > 1) {
thumbnail = tiffReader.read(1, readParam);
thumbnailIFD = tiffReader.getImageMetadata(1);
}
Note that tiffReader.getNumImages(true)
returns the number of
IFDs in the embedded TIFF stream including those corresponding to empty
images. Calling tiffReader.read(0, readParam)
will throw
an exception as the primary image in the embedded TIFF stream is always
empty; the primary image should be obtained using the JPEG reader itself.
ImageWriter
which may be
controlled by its public interface as well as via a supplied
TIFFImageWriteParam
. The TIFF
writer supports many optional capabilities including writing tiled images,
inserting images, writing or inserting empty images, and replacing image
data. Pixels may be replaced in either empty or non-empty images but if and
only if the data are not compressed.
TIFFCompressor
object may be
supplied via
TIFFImageWriteParam.setTIFFCompressor()
.
If a TIFFCompressor
is specified
in this manner it will be used and will supersede any internal compressor
which might otherwise have been used for a known compression type. This
mechanism allows for compression types to be handled by user-defined
compressors whether or not that compression type is known to the plug-in.
TIFFColorConverter
object may be
supplied via
TIFFImageWriteParam.setColorConverter()
.
If a TIFFColorConverter
is specified
in this manner it will be used and will supersede any internal color converter
which might otherwise have been used. This color converter will be used to
convert from RGB to the color space of the output image.
If no user-supplied color converter is available, the source image data color space type is RGB, and the destination photometric type is CIE L*a*b* or YCbCr, then the source image data will be automatically converted from RGB using an internal color converter.
IIOMetadata
instance supplied to the writer,
orColorSpace
of the destination
ImageTypeSpecifier
is an instance of
ICC_ColorSpace
which is not one of the standard
color spaces defined by the CS_* constants in the
ColorSpace
class. The destination type is set via
ImageWriteParam.setDestinationType()
and defaults to the
ImageTypeSpecifier
of the image being written.
For bilevel images, the FillOrder, and T4Options
fields affect the output data. The data will be filled right-to-left if
FillOrder is present with a value of 2
(BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT
)
and will be filled left-to-right otherwise. The value of T4Options
specifies whether the data should be 1D- or 2D-encoded and whether EOL
padding should be used.
For all images the value of the RowsPerStrip field is used to the set the number of rows per strip if the image is not tiled. The default number of rows per strip is either 8 or the number of rows which would fill no more than 8 kilobytes, whichever is larger.
For all images the tile dimensions may be set using the TileWidth
and TileLength field values if the tiling mode is
ImageWriteParam.MODE_COPY_FROM_METADATA
. If this mode
is set but the fields are not, their respective default values are the image
width and height.
When using JPEG-in-TIFF compression, a JPEGTables field will be written to the IFD and abbreviated JPEG streams to each strip or tile if and only if a JPEGTables field is contained in the metadata object provided to the writer. If the contents of the JPEGTables field is a valid tables-only JPEG stream, then it will be used; otherwise the contents of the field will be replaced with default visually lossless tables. If no such JPEGTables field is present in the metadata, then no JPEGTables field will be written to the output and each strip or tile will be written as a separate, self-contained JPEG stream.
When using Deflate/ZLib or LZW compression, if the image has 8 bits per
sample, a horizontal differencing predictor will be used if the
Predictor field is present with a value of 2
(BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING
). If prediction is so requested but the image does not have
8 bits per sample the field will be reset to have the value 1
(BaselineTIFFTagSet.PREDICTOR_NONE
).
Some fields may be added or modified:
TIFFColorConverter
.Some fields may be removed:
Other fields present in the supplied metadata are uninterpreted and will be written as supplied.
If an EXIF image is being written, the set of fields present and their values will be modified such that the result is in accord with the EXIF 2.2 specification.
Setting up the image metadata to write to a TIFF stream may be simplified
by using the TIFFDirectory
class
which represents a TIFF IFD. A field in a TIFF IFD is represented by an
instance of TIFFField
. For each
field to be written a TIFFField
may be added to the
TIFFDirectory
and the latter converted to an
IIOMetadata
object by invoking
TIFFDirectory.getAsMetadata()
. The
IIOMetadata
object so obtained may then be passed to the TIFF
writer.
javax_imageio_1.0
is
given in the following table.
TIFF Field | Derivation from Standard Metadata Elements |
---|---|
PhotometricInterpretation | /Chroma/ColorSpaceType@name: "GRAY" and /Chroma/BlackIsZero@value = "FALSE" => WhiteIsZero; "GRAY" and /Document/SubimageInterpretation@value = "TransparencyMask" => TransparencyMask; "RGB" and /Chroma/Palette present => PaletteColor; "GRAY" => BlackIsZero; "RGB" => RGB; "YCbCr" => YCbCr; "CMYK" => CMYK; "Lab" => CIELab. |
SamplesPerPixel | /Chroma/NumChannels@value |
ColorMap | /Chroma/Palette |
Compression | /Compression/CompressionTypeName@value: "none" => Uncompressed; "CCITT RLE" => CCITT 1D; "CCITT T.4" => Group 3 Fax; "CCITT T.6" => Group 4 Fax; "LZW" => LZW; "Old JPEG" => JPEG; "JPEG" => New JPEG; "ZLib" => ZLib; "PackBits" => PackBits; "Deflate" => Deflate. |
PlanarConfiguration | /Data/PlanarConfiguration@value: "PixelInterleaved" => Chunky; "PlaneInterleaved" => Planar. |
SampleFormat | /Data/SampleFormat@value: "SignedIntegral" => two's complement signed integer data; "UnsignedIntegral" => unsigned integer data; "Real" => IEEE floating point data; "Index" => unsigned integer data. |
BitsPerSample | /Data/BitsPerSample@value: space-separated list parsed to char array. |
FillOrder | /Data/SampleMSB@value: if all values in space-separated list are 0s => right-to-left; otherwise => left-to-right. |
XResolution | (10 / /Dimension/HorizontalPixelSize@value) or (10 / (/Dimension/VerticalPixelSize@value * /Dimension/PixelAspectRatio@value)) |
YResolution | (10 / /Dimension/VerticalPixelSize@value) or (10 / (/Dimension/HorizontalPixelSize@value / /Dimension/PixelAspectRatio@value)) |
ResolutionUnit | Centimeter if XResolution or YResolution set; otherwise None. |
Orientation | /Dimension/ImageOrientation@value |
XPosition | /Dimension/HorizontalPosition@value / 10 |
YPosition | /Dimension/VerticalPosition@value / 10 |
NewSubFileType | /Document/SubimageInterpretation@value: "TransparencyMask" => transparency mask; "ReducedResolution" => reduced-resolution; "SinglePage" => single page. |
DateTime | /Document/ImageCreationTime@value |
DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright | /Text/TextEntry: if /Text/TextEntry@keyword is the name of any of the TIFF Fields, e.g., "Software", then the field is added with content /Text/TextEntry@value and count 1. |
ExtraSamples | /Transparency/Alpha@value: "premultiplied" => associated alpha, count 1; "nonpremultiplied" => unassociated alpha, count 1. |
ImageWriter tiffWriter;
ImageOutputStream output;
ImageWriteParam writeParam;
IIOMetadata streamMetadata;
BufferedImage image;
BufferedImage thumbnail;
IIOMetadata primaryIFD;
IIOMetadata thumbnailIFD;
tiffWriter.setOutput(output);
if(thumbnail != null) {
// Write the TIFF header.
tiffWriter.prepareWriteSequence(streamMetadata);
// Append the primary IFD.
tiffWriter.prepareInsertEmpty(-1, // append
new ImageTypeSpecifier(image),
image.getWidth(),
image.getHeight(),
primaryIFD,
null, // thumbnails
writeParam);
tiffWriter.endInsertEmpty();
// Append the thumbnail IFD and image data.
tiffWriter.writeToSequence(new IIOImage(thumbnail, null, null),
writeParam);
// Append the primary image data.
tiffWriter.prepareReplacePixels(0, new Rectangle(image.getWidth(),
image.getHeight()));
tiffWriter.replacePixels(image, writeParam);
tiffWriter.endReplacePixels();
// End writing.
tiffWriter.endWriteSequence();
} else {
// Write only the primary IFD and image data.
tiffWriter.write(streamMetadata,
new IIOImage(image, null, primaryIFD),
writeParam);
}
ImageWriter tiffWriter;
ImageWriteParam writeParam;
boolean isThumbnailCompressed;
IIOMetadata streamMetadata;
BufferedImage image;
BufferedImage thumbnail;
IIOMetadata primaryIFD;
IIOMetadata thumbnailIFD;
// Set up the output.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MemoryCacheImageOutputStream app1EXIFOutput = new MemoryCacheImageOutputStream(baos);
tiffWriter.setOutput(app1EXIFOutput);
// Set compression.
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType("EXIF JPEG");
if(thumbnail != null) {
// Write the TIFF header.
tiffWriter.prepareWriteSequence(streamMetadata);
// Append the primary IFD.
tiffWriter.prepareInsertEmpty(-1, // append
new ImageTypeSpecifier(image),
image.getWidth(),
image.getHeight(),
primaryIFD,
null, // thumbnails
writeParam);
tiffWriter.endInsertEmpty();
// Change compression type if uncompressed.
if(!isThumbnailCompressed) {
writeParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
}
// Append the thumbnail IFD and image data.
tiffWriter.writeToSequence(new IIOImage(thumbnail, null,
thumbnailIFD),
writeParam);
// End writing.
tiffWriter.endWriteSequence();
} else {
// Write only the primary IFD.
tiffWriter.prepareWriteEmpty(streamMetadata,
new ImageTypeSpecifier(image),
image.getWidth(),
image.getHeight(),
primaryIFD,
null, // thumbnails
writeParam);
tiffWriter.endWriteEmpty();
}
// Flush data into byte stream.
app1EXIFOutput.flush();
// Create APP1 parameter array.
byte[] app1Parameters = new byte[6 + baos.size()];
// Add EXIF APP1 ID bytes.
app1Parameters[0] = (byte)'E';
app1Parameters[1] = (byte)'x';
app1Parameters[2] = (byte)'i';
app1Parameters[3] = (byte)'f';
app1Parameters[4] = app1Parameters[5] = (byte)0;
// Append TIFF stream to APP1 parameters.
System.arraycopy(baos.toByteArray(), 0, app1Parameters, 6, baos.size());
// Create the APP1 EXIF node to be added to native JPEG image metadata.
IIOMetadataNode app1Node = new IIOMetadataNode("unknown");
app1Node.setAttribute("MarkerTag", (new Integer(0xE1)).toString());
app1Node.setUserObject(app1Parameters);
The "unknown"
node created above would be appended to the
"markerSequence"
node of the native JPEG image metadata
and written to the JPEG stream when the primary image is written using
the JPEG writer.
<!DOCTYPE "com_sun_media_imageio_plugins_tiff_stream_1.0" [ <!ELEMENT "com_sun_media_imageio_plugins_tiff_stream_1.0" (ByteOrder)> <!ELEMENT "ByteOrder" EMPTY> <!-- The stream byte order --> <!ATTLIST "ByteOrder" "value" #CDATA #REQUIRED> <!-- One of "BIG_ENDIAN" or "LITTLE_ENDIAN" --> <!-- Data type: String --> ]>
<!DOCTYPE "com_sun_media_imageio_plugins_tiff_image_1.0" [ <!ELEMENT "com_sun_media_imageio_plugins_tiff_image_1.0" (TIFFIFD)*> <!ELEMENT "TIFFIFD" (TIFFField | TIFFIFD)*> <!-- An IFD (directory) containing fields --> <!ATTLIST "TIFFIFD" "tagSets" #CDATA #REQUIRED> <!-- Data type: String --> <!ATTLIST "TIFFIFD" "parentTagNumber" #CDATA #IMPLIED> <!-- The tag number of the field pointing to this IFD --> <!-- Data type: Integer --> <!ATTLIST "TIFFIFD" "parentTagName" #CDATA #IMPLIED> <!-- A mnemonic name for the field pointing to this IFD, if known --> <!-- Data type: String --> <!ELEMENT "TIFFField" (TIFFBytes | TIFFAsciis | TIFFShorts | TIFFSShorts | TIFFLongs | TIFFSLongs | TIFFRationals | TIFFSRationals | TIFFFloats | TIFFDoubles | TIFFUndefined)> <!-- A field containing data --> <!ATTLIST "TIFFField" "number" #CDATA #REQUIRED> <!-- The tag number asociated with the field --> <!-- Data type: String --> <!ATTLIST "TIFFField" "name" #CDATA #IMPLIED> <!-- A mnemonic name associated with the field, if known --> <!-- Data type: String --> <!ELEMENT "TIFFBytes" (TIFFByte)*> <!-- A sequence of TIFFByte nodes --> <!ELEMENT "TIFFByte" EMPTY> <!-- An integral value between 0 and 255 --> <!ATTLIST "TIFFByte" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFByte" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFAsciis" (TIFFAscii)*> <!-- A sequence of TIFFAscii nodes --> <!ELEMENT "TIFFAscii" EMPTY> <!-- A String value --> <!ATTLIST "TIFFAscii" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ELEMENT "TIFFShorts" (TIFFShort)*> <!-- A sequence of TIFFShort nodes --> <!ELEMENT "TIFFShort" EMPTY> <!-- An integral value between 0 and 65535 --> <!ATTLIST "TIFFShort" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFShort" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFSShorts" (TIFFSShort)*> <!-- A sequence of TIFFSShort nodes --> <!ELEMENT "TIFFSShort" EMPTY> <!-- An integral value between -32768 and 32767 --> <!ATTLIST "TIFFSShort" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFSShort" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFLongs" (TIFFLong)*> <!-- A sequence of TIFFLong nodes --> <!ELEMENT "TIFFLong" EMPTY> <!-- An integral value between 0 and 4294967295 --> <!ATTLIST "TIFFLong" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFLong" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFSLongs" (TIFFSLong)*> <!-- A sequence of TIFFSLong nodes --> <!ELEMENT "TIFFSLong" EMPTY> <!-- An integral value between -2147483648 and 2147482647 --> <!ATTLIST "TIFFSLong" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFSLong" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFRationals" (TIFFRational)*> <!-- A sequence of TIFFRational nodes --> <!ELEMENT "TIFFRational" EMPTY> <!-- A rational value consisting of an unsigned numerator and denominator --> <!ATTLIST "TIFFRational" "value" #CDATA #IMPLIED> <!-- The numerator and denominator, separated by a slash --> <!-- Data type: String --> <!ELEMENT "TIFFSRationals" (TIFFSRational)*> <!-- A sequence of TIFFSRational nodes --> <!ELEMENT "TIFFSRational" EMPTY> <!-- A rational value consisting of a signed numerator and denominator --> <!ATTLIST "TIFFSRational" "value" #CDATA #IMPLIED> <!-- The numerator and denominator, separated by a slash --> <!-- Data type: String --> <!ELEMENT "TIFFFloats" (TIFFFloat)*> <!-- A sequence of TIFFFloat nodes --> <!ELEMENT "TIFFFloat" EMPTY> <!-- A single-precision floating-point value --> <!ATTLIST "TIFFFloat" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ELEMENT "TIFFDoubles" (TIFFDouble)*> <!-- A sequence of TIFFDouble nodes --> <!ELEMENT "TIFFDouble" EMPTY> <!-- A double-precision floating-point value --> <!ATTLIST "TIFFDouble" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ELEMENT "TIFFUndefined" EMPTY> <!-- Uninterpreted byte data --> <!ATTLIST "TIFFUndefined" "value" #CDATA #IMPLIED> <!-- A list of comma-separated byte values --> <!-- Data type: String --> ]>
Copyright © 2017 Open Microscopy Environment