1178N/A<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
0N/ACopyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. 0N/ADO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/AThis code is free software; you can redistribute it and/or modify it 0N/Aunder the terms of the GNU General Public License version 2 only, as 0N/Apublished by the Free Software Foundation. Oracle designates this 0N/Aparticular file as subject to the "Classpath" exception as provided 0N/Aby Oracle in the LICENSE file that accompanied this code. 0N/AThis code is distributed in the hope that it will be useful, but WITHOUT 0N/AANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/AFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/Aversion 2 for more details (a copy is included in the LICENSE file that 2362N/AYou should have received a copy of the GNU General Public License version 1178N/A2 along with this work; if not, write to the Free Software Foundation, 1178N/AInc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 0N/APlease contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1178N/A<
title>JPEG Metadata Format Specification and Usage Notes</
title>
0N/A<
body bgcolor="white">
1178N/AJPEG Metadata Format Specification and Usage Notes
0N/A<
a href=#
metadata>JPEG Metadata</
a><
br>
0N/A<
a href=#
abbrev>Abbreviated Streams</
a><
br>
0N/A<
a href=#
tables>Sources of Tables</
a><
br>
0N/A<
a href=#
color>Colorspace Transformations and Conventional Markers</
a><
br>
0N/A<
a href=#
thumbs>Thumbnail Images</
a><
br>
0N/A<
a href=#
prog>Progressive Encoding</
a><
br>
0N/A<
a href=#
tree>Native Metadata Format Tree Structure and Editing</
a><
br>
0N/A<
a href=#
image>Image Metadata DTD</
a><
br>
0N/A<
a href=#
stream>Stream Metadata DTD</
a>
0N/A<
bold>NOTE</
bold>: It is important to call <
code>dispose()</
code>
0N/Aon the JPEG reader and writer objects when they are no longer needed, as
1178N/Athey consume significant native resources which are not adequately recovered
0N/Aby garbage collection. Both reader and writer call <
code>dispose()</
code>
0N/Ain their finalizers, but those finalizers may not be called before the native
0N/Acode has exhausted native memory.
0N/AThe JPEG writer does not support replacing pixels.
1178N/A<
a name=metadata>JPEG Metadata</
a>
0N/AJPEG metadata consists of the data contained in marker segments in a JPEG
0N/Astream. The image metadata object returned from a read describes the
0N/Acontents of the marker segments between the <
code>SOI</
code> marker and
0N/Athe <
code>EOI</
code> marker for that image. The image metadata object
0N/Apassed into a write determines the contents of the stream between the
0N/A<
code>SOI</
code> marker and the <
code>EOI</
code> marker for that image,
0N/Asubject to the controls in any <
code>ImageWriteParam</
code>.
0N/AStream metadata is used only for tables-only images found (or to be
0N/Aplaced) at the beginning of a stream containing abbreviated images.
0N/ATables-only images are not treated as images and do not consume an
0N/Aimage index. The stream metadata object returned from a read describes the
0N/Acontents of the marker segments between the <
code>SOI</
code> marker and
0N/Athe <
code>EOI</
code> marker for the single tables-only image at the
1178N/Abeginning of the stream, if one is present. If no tables-only image is
0N/Apresent at the front of the stream, the <
code>getStreamMetadata</
code>
0N/Amethod of <
code>ImageReader</
code> returns <
code>null</
code>. If
0N/Astream metadata is provided to the writer, a single tables-only image
0N/Acontaining the tables from the stream metadata object will be written at
0N/Athe beginning of the stream. If the stream metadata object contains no
0N/Atables, default tables will be written. As the sole purpose of stream
0N/Ametadata is for specifying tables-only images at the front of abbreviated
0N/Astreams, the stream metadata argument is useful only on the
0N/Aobject containing the tables from the <
code>ImageWriteParam</
code> argument,
0N/Aif it is a <
code>JPEGImageWriteParam</
code> and contains tables. Otherwise,
0N/Athe returned object will contain default tables.
0N/Ametadata object containing <
bold>no</
bold> tables if the
0N/A<
code>ImageWriteParam</
code> argument contains tables. Otherwise the
0N/Areturned metadata object will contain default visually lossless tables.
0N/AOf course, only a <
code>JPEGImageWriteParam</
code> may contain tables.
0N/AIf <
code>ignoreMetadata</
code> is set to <
code>true</
code> when the input
0N/Ais set on the reader, stream metadata will not be available, but image
0N/A<
a name=abbrev>Abbreviated Streams</
a>
0N/ABoth the reader and the writer retain their tables from one operation to the
0N/Anext, thus permitting the use of abbreviated streams quite naturally, with a
0N/Afew minor restrictions:
0N/A <
li> Abbreviated streams may contain only one tables-only image, which must
0N/A come first in the stream. Subsequent tables-only images will cause
0N/A undefined behavior.</
li>
0N/A <
li> Abbreviated streams must be read fully and in order. No random access
0N/A is allowed, in either direction. The same image may be read multiple
0N/A times. If a call is made with an image index that is not the same as
0N/A or one greater than the most recent call (or 0 if no calls have been
0N/A made), then an <
code>IllegalArgumentException</
code> is thrown.</
li>
0N/AThese restrictions mean that streams may contain abbreviated images
0N/Ainterspersed with images containing tables. As required by JPEG, any tables
0N/Aappearing in the stream override previous tables, regardless of the source
0N/Aof the previous tables.
0N/ANote that once a tables-only image has been read, it's contents is available
0N/Aas stream metadata from the reader until either another tables-only image
0N/Ais read from another stream or the reader is reset. Changing the input does
0N/Anot reset the stream metadata. This is useful for reading the tables from
0N/Aone file, then changing the input to read an abbreviated stream containing
0N/Aa sequence of images. The tables will be used automatically, and will remain
0N/Aavailable as "stream" metadata.
0N/AAbbreviated streams are written using the sequence methods of
1178N/A<
code>ImageWriter</
code>. Stream metadata is used to write a tables-only
0N/Aimage at the beginning of the stream, and the tables are set up for use, using
1178N/Atables-only image is written. If stream metadata containing no tables is
0N/Aimage containing default visually lossless tables is written.
0N/A<
a name=tables>Sources of Tables</
a>
0N/AImages are written with tables if tables are present in their metadata objects
0N/Aor without them if no tables are present in their metadata objects. If no
0N/Ametadata object is present then the tables are written. The tables used for
1178N/Acompression are taken from one of the following sources, which are consulted
0N/A <
li> If there is an <
code>ImageWriteParam</
code> and the compression mode is
0N/A set to <
code>EXPLICIT</
code>, default tables constructed using the
0N/A quality setting are used. They are written only if the metadata
0N/A contains tables or if there is no metadata, but they replace the
0N/A tables in the metadata.</
li>
0N/A <
li> If there is an <
code>ImageWriteParam</
code> and the compression mode is
0N/A set to <
code>DEFAULT</
code>, default visually lossles tables are used.
0N/A They are written only if the metadata contains tables or if
0N/A there is no metadata, but they replace the tables in the
0N/A <
li> Otherwise the compression mode on the <
code>ImageWriteParam</
code> must
1178N/A be MODE_COPY_FROM_<
code>METADATA</
code>, in which case the following
0N/A <
li> the tables in the image metadata, if present</
li>
0N/A <
li> the tables in the stream metadata, if present</
li>
1178N/A <
li> the tables in the <
code>JPEGImageWriteParam</
code>, if present</
li>
0N/A <
li> default visually lossless tables</
li>
0N/A </
ol> Tables are written only if they are taken from image metadata.
1178N/AThis ordering implements the design intention that tables should be included
0N/Ain <
code>JPEGImageWriteParam</
code>s only as a means of specifying tables
0N/Awhen no other source is available, and this can occur only when writing to an
1178N/Aabbreviated stream without tables using known non-standard tables for
0N/AWhen reading, tables in a <
code>JPEGImageReadParam</
code> are consulted only
0N/Aif tables have not been set by any previous read. Tables set from a
0N/A<
code>JPEGImageReadParam</
code> are overridden by any tables present in the
0N/ANote that if no image metadata object is specified for a particular image, a
0N/Adefault object is used, which includes default tables.
0N/A<
a name=color>Colorspace Transformations and Conventional Markers</
a>
0N/AColorspace transformations are controlled by the destination type for
0N/Aboth reading and writing of images. When <
code>Raster</
code>s are
0N/Aread, no colorspace transformation is performed, and any destination type
0N/Ais ignored. A warning is sent to any listeners if a destination type is
0N/Aspecified in this case. When <
code>Raster</
code>s are written, any
0N/Adestination type is used to interpret the bands. This might result in a
0N/AJFIF or Adobe header being written, or different component ids being written
0N/Ato the frame and scan headers. If values present in a metadata object do not
0N/Amatch the destination type, the destination type is used and a warning is sent
0N/AWhen reading, the contents of the stream are interpreted by the usual
0N/AJPEG conventions, as follows:
1178N/A <
li> If a JFIF <
code>APP0</
code> marker segment is present, the colorspace
1178N/A is known to be either grayscale or YCbCr. If an <
code>APP2</
code>
0N/A marker segment containing an embedded ICC profile is also present, then
0N/A the YCbCr is converted to RGB according to the formulas given in the
0N/A JFIF spec, and the ICC profile is assumed to refer to the resulting RGB
1178N/A <
li> If an Adobe <
code>APP14</
code> marker segment is present, the
0N/A colorspace is determined by consulting the <
code>transform</
code> flag.
0N/A The <
code>transform</
code> flag takes one of three values:
0N/A <
li> 2 - The image is encoded as YCCK (implicitly converted from
0N/A <
li> 1 - The image is encoded as YCbCr (implicitly converted from RGB
0N/A <
li> 0 - Unknown. 3-channel images are assumed to be RGB, 4-channel
1178N/A images are assumed to be CMYK.
1178N/A <
li> If neither marker segment is present, the following procedure is
0N/A followed: Single-channel images are assumed to be grayscale, and
0N/A 2-channel images are assumed to be grayscale with an alpha channel.
1178N/A For 3- and 4-channel images, the component ids are consulted. If these
0N/A values are 1-3 for a 3-channel image, then the image is assumed to be
0N/A YCbCr. If these values are 1-4 for a 4-channel image, then the image
0N/A is assumed to be YCbCrA. If these values are > 4, they are checked
0N/A against the ASCII codes for 'R', 'G', 'B', 'A', 'C', 'c'. These can
0N/A encode the following colorspaces:
0N/A <
br>YCC (as 'Y','C','c'), assumed to be PhotoYCC
0N/A <
br>YCCA (as 'Y','C','c','A'), assumed to be PhotoYCCA
0N/A Otherwise, 3-channel subsampled images are assumed to be YCbCr,
0N/A 3-channel non-subsampled images are assumed to be RGB, 4-channel
0N/A subsampled images are assumed to be YCCK, and 4-channel, non-subsampled
1178N/A images are assumed to be CMYK.
0N/A <
li> All other images are declared uninterpretable and an exception is
0N/A thrown if an attempt is made to read one as a
0N/A <
code>BufferedImage</
code>. Such an image may be read only as a
1178N/A <
code>Raster</
code>. If an image is interpretable but there is no Java
0N/A <
code>ColorSpace</
code> available corresponding to the encoded
0N/A colorspace (<
italic>
e.g.</
italic> YCbCr), then
0N/AOnce an encoded colorspace is determined, then the target colorspace is
0N/Adetermined as follows:
0N/A <
li> If a destination type is not set, then the following default
0N/A transformations take place after upsampling: YCbCr (and YCbCrA) images
0N/A are converted to RGB (and RGBA) using the conversion provided by the
0N/A underlying IJG library and either the built-in sRGB
0N/A <
code>ColorSpace</
code> or a custom RGB <
code>ColorSpace</
code> object
0N/A based on an embedded ICC profile is used to create the output
0N/A <
code>ColorModel</
code>. PhotoYCC and PhotoYCCA images are not
0N/A converted. CMYK and YCCK images are currently not supported.</
li>
1178N/A <
li> If a destination image or type is set, it is used as follows:
1178N/A If the IJG library provides an appropriate conversion, it is used.
0N/A Otherwise the default library conversion is followed by a colorspace
0N/A conversion in Java.</
li>
0N/A <
li> Bands are selected AFTER any library colorspace conversion. If a
0N/A subset of either source or destination bands is used, then the default
0N/A library conversions are used with no further conversion in Java,
0N/A regardless of any destination type.</
li>
0N/A <
li> An exception is thrown if an attempt is made to read an image in an
0N/A unsupported jpeg colorspace as a <
code>BufferedImage</
code>
1178N/A (<
italic>
e.g.</
italic> CMYK). Such images may be read as
0N/A <
code>Raster</
code>s. If an image colorspace is unsupported or
0N/A return an empty <
code>Iterator</
code>. If a subset of the raw bands
0N/A are required, a <
code>Raster</
code> must be obtained first and the
0N/A bands obtained from that. </
li>
0N/AFor writing, the color transformation to apply is determined as
0N/AIf a subset of the source bands is to be written, no color conversion is
0N/Aperformed. Any destination, if set, must match the number of bands that will
0N/Abe written, and serves as an interpretation of the selected bands, rather than
0N/Aa conversion request. This behavior is identical to that for
0N/A<
code>Raster</
code>s. If all the bands are to be written and an image
0N/A(as opposed to a <
code>Raster</
code>) is being written, any destination type
0N/Ais ignored and a warning is sent to any listeners.
0N/AIf a destination type is used and any aspect of the metadata object, if there
1178N/Ais one, is not compatible with that type, the destination type is used, the
0N/Ametadata written is modified from that provided, and a warning is sent to
0N/Alisteners. This includes the <
code>app0JFIF</
code> and
0N/A<
code>app14Adobe</
code> nodes. The component ids in the <
code>sof</
code> and
0N/A<
code>sos</
code> nodes are not modified, however, as unless a
0N/A<
code>app0JFIF</
code> node is present, any values may be used.
0N/AWhen a full image is written, a destination colorspace will be
0N/Achosen based on the image contents and the metadata settings, according to
0N/Athe following algorithm:
1178N/AIf no metadata object is specified, then the following defaults apply:
0N/A <
li> Grayscale images are written with a JFIF <
code>APP0</
code> marker
0N/A segment. Grayscale images with alpha are written with no special
0N/A marker. As required by JFIF, the component ids in the frame and
0N/A scan header is set to 1.
0N/A <
li> RGB images are converted to YCbCr, subsampled in the chrominance
0N/A channels by half both vertically and horizontally, and written with a
0N/A JFIF <
code>APP0</
code> marker segment. If the <
code>ColorSpace</
code>
0N/A of the image is based on an <
code>ICCProfile</
code> (it is an instance
0N/A of <
code>ICC_ColorSpace</
code>, but is not one of the standard built-in
1178N/A <
code>ColorSpaces</
code>), then that profile is embedded in an
0N/A <
code>APP2</
code> marker segment. As required by JFIF, the
0N/A component ids in the frame and scan headers are set to 1, 2, and 3.
0N/A <
li> RGBA images are converted to YCbCrA, subsampled in the
0N/A chrominance channels by half both vertically and horizontally, and
0N/A written without any special marker segments. The component ids
1178N/A in the frame and scan headers are set to 1, 2, 3, and 4.
0N/A <
li> PhotoYCC and YCCAimages are subsampled by half in the chrominance
0N/A channels both vertically and horizontally and written with an
0N/A Adobe <
code>APP14</
code> marker segment and 'Y','C', and 'c' (and
1178N/A 'A' if an alpha channel is present) as component ids in the frame
0N/ADefault metadata objects for these image types will reflect these settings.
1178N/AIf a metadata object is specified, then the number of channels in the
0N/Aframe and scan headers must always match the number of bands to be
0N/Awritten, or an exception is thrown. <
code>app0JFIF</
code> and
0N/A<
code>app14Adobe</
code> nodes may appear in the same metadata object only
0N/Aif the <
code>app14Adobe</
code> node indicates YCbCr, and the component ids
are JFIF compatible (0-2). The various image types are processed in the
(All multi-channel images are subsampled according to the sampling factors
in the frame header node of the metadata object, regardless of color space.)
<
li> If an <
code>app0JFIF</
code> node is present in the metadata object,
a JFIF <
code>APP0</
code> marker segment is written.
<
li> If an <
code>app14Adobe</
code> node is present in the metadata
object, it is checked for validity (<
code>transform</
code> must be
<
code>UNKNOWN</
code>) and written.
<
li> If neither node is present in the metadata object, no special
marker segment is written.
<
li> Grayscale Images with an Alpha Channel:
<
li> If an <
code>app0JFIF</
code> node is present in the metadata object,
it is ignored and a warning is sent to listeners, as JFIF does not
support 2-channel images.
<
li> If an <
code>app14Adobe</
code> node is present in the metadata
object, it is checked for validity (<
code>transform</
code> must be
<
code>UNKNOWN</
code>) and written. If <
code>transform</
code> is
not <
code>UNKNOWN</
code>, a warning is sent to listeners and the
correct transform is written.
<
li> If neither node is present in the metadata object, no special
marker segment is written.
<
li> If an <
code>app0JFIF</
code> node is present in the metadata object,
the image is converted to YCbCr and written with a JFIF
<
code>APP0</
code> marker segment. If the <
code>ColorSpace</
code>
of the image is based on a non-standard ICC Profile, then that
profile is embedded in an <
code>APP2</
code> marker segment. If the
<
code>ColorSpace</
code> is not based on a non-standard ICC Profile,
but an <
code>app2ICC</
code> node appears in the metadata, then an
<
code>APP2</
code> marker segment is written with the appropriate
standard profile. Note that the profile must specify an RGB color
space, as the file must be JFIF compliant.
<
li> If an <
code>app14Adobe</
code> node is present in the metadata
object, the image is converted according to the color transform
setting and written with an Adobe <
code>APP14</
code> marker
segment. Component ids are written just as they appear in the
frame and scan headers. The color transform must be either YCbCr
or <
code>UNKNOWN</
code>. If it is <
code>UNKNOWN</
code>, the image
<
li> If neither node is present, the component ids in the frame
header are consulted. If these indicate a colorspace as described
above, then the image is converted to that colorspace if possible.
If the component ids do not indicate a colorspace, then the
sampling factors are consulted. If the image is to be subsampled,
it is converted to YCbCr first. If the image is not to be
subsampled, then no conversion is applied. No special marker
<
li> If an <
code>app0JFIF</
code> node is present in the metadata object,
it is ignored and a warning is sent to listeners, as JFIF does not
support 4-channel images.
<
li> If an <
code>app14Adobe</
code> node is present in the metadata
object, the image is written with an Adobe <
code>APP14</
code> marker
segment. No colorspace conversion is performed. Component ids
are written just as they appear in the frame and scan headers.
The color transform must be <
code>UNKNOWN</
code>. If it is
not, a warning is sent to listeners.
<
li> If no <
code>app14Adobe</
code> node is present, the component ids in
the frame header are consulted. If these indicate a colorspace as
described above, then the image is converted to that colorspace if
possible. If the component ids do not indicate a colorspace, then
the sampling factors are consulted. If the image is to be
subsampled, it is converted to YCbCrA. If the image is not to be
subsampled, then no conversion is applied. No special marker
<
li> If an <
code>app0JFIF</
code> node is present in the metadata object,
the image is converted to sRGB, and then to YCbCr during encoding,
and a JFIF <
code>APP0</
code> marker segment is written.
<
li> If an <
code>app14Adobe</
code> node is present in the metadata
object, no conversion is applied, and an Adobe <
code>APP14</
code>
marker segment is written. The color transform must be YCC. If it
is not, a warning is sent to listeners.
<
li> If neither node is present in the metadata object, no conversion
is applied, and no special marker segment is written.
<
li> If an <
code>app0JFIF</
code> node is present in the metadata object,
it is ignored and a warning is sent to listeners, as JFIF does not
support 4-channel images.
<
li> If an <
code>app14Adobe</
code> node is present in the metadata
object, no conversion is applied, and an Adobe <
code>APP14</
code>
marker segment is written. The color transform must be
<
code>UNKNOWN</
code>. If it is not, a warning is sent to
<
li> If neither node is present in the metadata object, no conversion
is applied, and no special marker segment is written.
<
a name=thumbs>Thumbnail Images</
a>
Thumbnails are supported by the use of JFIF and JFIF extension marker segments.
Thumbnails provided on the write methods determine the thumbnails that will be
included. <
code>app0JFIF</
code> and <
code>app0JFXX</
code> nodes present in
the metadata do not contain any thumbnail pixel data. However, the kinds of
thumbnails written depend on the contents of the metadata object, as follows.
Any thumbnail which is to be written as an indexed or RGB image and which is
larger than 255 by 255 will be clipped, not scaled, to 255 by 255. Thumbnails
written as JPEG images may be any size. A warning is sent to any listeners
whenever a thumbnail is clipped.
<
li> If there is a single thumbnail, it is processed as follows:
<
li> If the thumbnail image is an RGB palette image, it is processed as
<
li> If no <
code>app0JFXX</
code> node is present in the metadata, or
the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbPalette</
code> element, a
palette thumbnail is written in a JFXX <
code>APP0</
code> marker
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains another thumbnail form (RGB or JPEG), the palette
image is expanded to RGB and the indicated thumbnail form is
<
li> If the thumbnail image is an RGB image, it is processed as follows:
<
li> If no <
code>app0JFXX</
code> node is present in the metadata,
the thumbnail is written as part of the JFIF <
code>APP0</
code>
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbRGB</
code> element, an
RGB thumbnail is written in a JFXX <
code>APP0</
code> marker
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbJPEG</
code> element, a
JPEG thumbnail is written in a JFXX <
code>APP0</
code> marker
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbPalette</
code> element, an
RGB thumbnail is written in a JFXX <
code>APP0</
code> marker
segment and a warning is sent to any listeners.
<
li> If the thumbnail image is a grayscale image, it is processed as
<
li> If no <
code>app0JFXX</
code> node is present in the metadata,
the thumbnail is expanded to RGB and written as part of the
JFIF <
code>APP0</
code> marker segment.
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbRGB</
code> element, the thumbnail is
expanded to RGB and written in a separate <
code>JFXX</
code> RGB
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbJPEG</
code> element, a
JPEG thumbnail is written in a JFXX <
code>APP0</
code> marker
<
li> If the first <
code>app0JFXX</
code> node present in the metadata
contains a <
code>JFIFthumbPalette</
code> element, a
JPEG thumbnail is written in a JFXX <
code>APP0</
code> marker
segment and a warning is sent to any listeners.
<
li> Any other thumbnail image types are ignored and a warning is sent
<
li> If there are multiple thumbnails, each one is processed as above, except
that no thumbnail is placed in the JFIF <
code>APP0</
code> segment, and
the <
code>app0JFXX</
code> node consulted for each thumbnail is the
<
code>app0JFXX</
code> node from the metadata that occurs in the same
sequence as the thumbnail. <
italic>
I.e.</
italic> the first
<
code>app0JFXX</
code> node applies to the first thumbnail, the second
node to the second thumbnail, and so on. If there are fewer
<
code>app0JFXX</
code> nodes in the metadata than thumbnails, then
those thumbnails are considered to have no matching
<
code>app0JFXX</
code> node. An RGB thumbnail with no matching
<
code>app0JFXX</
code> node is written in a JFXX <
code>APP0</
code> marker
segment. A grayscale thumbnail with no matching
<
code>app0JFXX</
code> node is written as a JPEG image to a JFXX
<
code>APP0</
code> marker segment.
Note that as the only mechanism for storing thumbnails is via the
JFIF or JFIF extension marker segments, only grayscale or RGB images
may have thumbnails. If thumbnails are present when writing any other type
of image, the thumbnails are ignored and a warning is sent to any warning
<
a name=prog>Progressive Encoding</
a>
Progressive encoding must be enabled on the <
code>ImageWriteParam</
code>
passed in to a write operation, or the image will be written sequentially,
regardless of the scan headers included in the metadata object. If
progressive encoding is enabled and set to copy from metadata, then
the sequence of scan headers from the metadata is used to write the
image. If progressive encoding is enabled and set to use a default,
then the scans in the metadata are ignored and a default set of scans
is used. Progressive encoding always forces optimized Huffman tables to
be used. Any Huffman tables present in the metadata will be ignored,
and a warning will be sent to any warning listeners.
If Huffman-table optimization is requested on the <
code>ImageWriteParam</
code>,
all Huffman tables in the metadata or in the <
code>ImageWriteParam</
code>
itself are ignored, and a warning will be sent to any warning listeners if
any such tables are present.
<
a name=tree>Native Metadata Format Tree Structure and Editing</
a>
The DTDs below describe just the trees of metadata objects actually returned
by the <
code>IIOMetadata</
code> object. They do not include nodes
corresponding to <
code>SOI</
code>, <
code>EOI</
code>, or <
code>RST</
code>
markers, as these parsing delimiters do not carry any meaningful metadata.
The first node is always a <
code>JPEGvariety</
code> node. In the
<
code>javax_imageio_jpeg_image_1.0</
code> version of the JPEG metadata
format, this node may have one child, an <
code>app0JFIF</
code> node,
indicating that the JPEG stream contains a JFIF marker segment and related
data, or no children, indicating that the stream contains no JFIF marker.
In future versions of the JPEG metadata format, other varieties of JPEG
metadata may be supported (
e.g. Exif) by defining other types of nodes
which may appear as a child of the <
code>JPEGvariety</
code> node.
(Note that an application wishing to interpret Exif metadata given
a metadata tree structure in the <
code>javax_imageio_jpeg_image_1.0</
code>
format must check for an <
code>unknown</
code> marker segment with a tag
indicating an <
code>APP1</
code> marker and containing data identifying it
as an Exif marker segment. Then it may use application-specific code to
interpret the data in the marker segment. If such an application were
to encounter a metadata tree formatted according to a future version of
the JPEG metadata format, the Exif marker segment might not be
<
code>unknown</
code> in that format - it might be structured as a
child node of the <
code>JPEGvariety</
code> node. Thus, it is important
for an application to specify which version to use by passing the string
<
code>IIOMetadata</
code> object.)
On reading, <
code>JFXX</
code> and <
code>app2ICC</
code> nodes occur as
children of an <
code>app0JFIF</
code> node.
This is true regardless of where the JFXX <
code>APP0</
code> and
<
code>APP2</
code> marker segments actually occur in the stream. The ordering
of nodes within the <
code>markerSequence</
code> node corresponds to the
ordering of marker segments found in the JPEG stream.
On writing, any <
code>JFXX</
code> and <
code>app2ICC</
code> nodes must
occur as children of an <
code>app0JFIF</
code> node, itself a child of a
<
code>JPEGvariety</
code> node, which must always be the first node.
(If the stream is not to be JFIF compliant, no <
code>app0JFIF</
code> node
should be provided, and the <
code>JPEGvariety</
code> node should have no
JFIF <
code>APP0</
code>, JFXX <
code>APP0</
code>, and <
code>APP2</
code> marker
segments are written first, followed by all Adobe <
code>APP14</
code>,
<
code>APPn</
code>, <
code>COM</
code> and unknown segments in the
order in which their corresponding nodes appear in the
<
code>markerSequence</
code> node, followed by <
code>DQT</
code> (and
<
code>DHT</
code> for non-progressive writes) marker segments, followed by the
<
code>SOF</
code> and <
code>SOS</
code> marker segments. For progressive writes
using metadata to control progression, the <
code>SOS</
code> segments are used
in the order in which their corresponding nodes occur in the
<
code>markerSequence</
code> node.
The <
code>reset</
code>, <
code>mergeTree</
code> and <
code>setFromTree</
code>
operations have the following semantics for the JPEG plug-in metadata object:
<
p> <
code>reset</
code> - A call to <
code>reset</
code> will restore the
metadata object to the same state it had immediately after creation, whether
this came about from reading a stream or by obtaining a default object from
the <
code>ImageWriter</
code>. This is true regardless of how many times the
metadata object has been modified since creation.
<
p> <
code>mergeTree</
code> - Native Format
<
br> The <
code>mergeTree</
code> operation accepts valid trees conforming to
the DTD below, and merges the nodes using the following ordering rules. In
all cases, only data present in the new node is changed in a corresponding
existing node, if any. This means that nodes cannot be removed using
<
code>mergeTree</
code>. To remove nodes, use <
code>setFromTree</
code>. The
tree must consist of <
code>IIOMetadataNode</
code>s.
<
li> <
code>app0JFIF</
code>
<
li> If an <
code>app0JFIF</
code> node already exists, the contents
of the new one modify the existing one.
<
li> If there is no such node, a new one is created and inserted in
the appropriate position.
<
li> If there already exist <
code>dqt</
code> nodes in the sequence,
then each table in the node replaces the first table, in any
<
code>dqt</
code> node, with the same table id.
<
li> If none of the existing <
code>dqt</
code> nodes contain a table
with the same id, then the table is added to the last existing
<
li> If there are no <
code>dqt</
code> nodes, then a new one is
created and added as follows:
<
li> If there are <
code>dht</
code> nodes, the new
<
code>dqt</
code> node is inserted before the first one.
<
li> If there are no <
code>dht</
code> nodes, the new
<
code>dqt</
code> node is inserted before an
<
code>sof</
code> node, if there is one.
<
li> If there is no <
code>sof</
code> node, the new
<
code>dqt</
code> node is inserted before the first
<
code>sos</
code> node, if there is one.
<
li> If there is no <
code>sos</
code> node, the new
<
code>dqt</
code> node is added to the end of the sequence.
<
li> If there already exist <
code>dht</
code> nodes in the sequence,
then each table in the node replaces the first table, in any
<
code>dht</
code> node, with the same table class and table id.
<
li> If none of the existing <
code>dht</
code> nodes contain a table
with the same class and id, then the table is added to the last
existing <
code>dht</
code> node.
<
li> If there are no <
code>dht</
code> nodes, then a new one is
created and added as follows:
<
li> If there are <
code>dqt</
code> nodes, the new
<
code>dht</
code> node is inserted immediately following the
last <
code>dqt</
code> node.
<
li> If there are no <
code>dqt</
code> nodes, the new
<
code>dht</
code> node is inserted before an
<
code>sof</
code> node, if there is one.
<
li> If there is no <
code>sof</
code> node, the new
<
code>dht</
code> node is inserted before the first
<
code>sos</
code> node, if there is one.
<
li> If there is no <
code>sos</
code> node, the new
<
code>dht</
code> node is added to the end of the sequence.
<
li> If there already exists a <
code>dri</
code> node, the restart
interval value is updated.
<
li> If there is no <
code>dri</
code> node, then a new one is created
<
li> If there is an <
code>sof</
code> node, the new
<
code>dri</
code> node is inserted before it.
<
li> If there is no <
code>sof</
code> node, the new
<
code>dri</
code> node is inserted before the first
<
code>sos</
code> node, if there is one.
<
li> If there is no <
code>sos</
code> node, the new
<
code>dri</
code> node is added to the end of the sequence.
<
br> A new <
code>com</
code> node is created and inserted as follows:
<
li> If there already exist <
code>com</
code> nodes, the new one is
inserted after the last one.
<
li> If there are no <
code>com</
code> nodes, the new
<
code>com</
code> node is inserted after the
<
code>app14Adobe</
code> node, if there is one.
<
li> If there is no <
code>app14Adobe</
code> node, the new
<
code>com</
code> node is inserted at the beginning of the
<
li> <
code>app14Adobe</
code>
<
li> If there already exists an <
code>app14Adobe</
code> node, then
its attributes are updated from the node.
<
li> If there is no <
code>app14Adobe</
code> node, then a new one is
created and added as follows:
<
li> The new <
code>app14Adobe</
code> node is inserted after the
last <
code>unknown</
code> node, if there are any.
<
li> If there are no <
code>unknown</
code> nodes, the new
<
code>app14Adobe</
code> node is inserted at the beginning
<
li> <
code>unknown</
code>
<
br> A new <
code>unknown</
code> node is created and added to the
<
li> If there already exist <
code>unknown</
code> marker nodes, the
new one is inserted after the last one.
<
li> If there are no <
code>unknown</
code> nodes, the new
<
code>unknown</
code> node is inserted before the
<
code>app14Adobe</
code> node, if there is one.
<
li> If there is no <
code>app14Adobe</
code> node, the new
<
code>unknown</
code> node is inserted at the beginning of the
<
li> If there already exists an <
code>sof</
code> node in the
sequence, then its values are updated from the node.
<
li> If there is no <
code>sof</
code> node, then a new one is created
<
li> If there are any <
code>sos</
code> nodes, the new
<
code>sof</
code> node is inserted before the first one.
<
li> If there is no <
code>sos</
code> node, the new
<
code>sof</
code> node is added to the end of the sequence.
<
li> If there already exists a single <
code>sos</
code> node, then
the values are updated from the node.
<
li> If there are more than one existing <
code>sos</
code> nodes,
then an <
code>IIOInvalidTreeException</
code> is thrown, as
<
code>sos</
code> nodes cannot be merged into a set of
<
li> If there are no <
code>sos</
code> nodes, a new one is created
and added to the end of the sequence.
<
p> <
code>mergeTree</
code> - Standard Format
The <
code>mergeTree</
code> operation, when given a tree in the standard
format, will modify the native tree in the following ways:
<
li> <
code>Chroma</
code> - The <
code>ColorSpaceType</
code> subnode of a
<
code>Chroma</
code> node may change the target colorspace of the
compressed image. The selection of a new colorspace can cause a number
of changes, in keeping with the algorithms described above:
<
code>app0JFIF</
code> and <
code>app14Adobe</
code> nodes may be added
or removed, subsampling may be added or removed, component ids may
be changed, and <
code>sof</
code> and <
code>sos</
code> nodes will be
updated accordingly. If necessary, additional quantization and
huffman tables are added. In the case of quantization tables, the
default will be scaled to match the quality level of any existing
tables. No tables are added to metadata that does not already contain
tables. If the existing metadata specifies progressive encoding, then
the number of channels must not change. Any <
code>Transparency</
code>
node is also taken into account, as an explicit value of
<
code>none</
code> for the <
code>Alpha</
code> subnode can cause the
removal of an alpha channel, and anything other than <
code>none</
code>
can cause the addition of an alpha channel.
<
li> <
code>Dimension</
code> - A <
code>PixelAspectRatio</
code> specification
can cause the contents of an <
code>app0JFIF</
code> node to change, if
there is one present, or the addition of an <
code>app0JFIF</
code> node
containing appropriate values, if there can be one. An appropriate
pair of integers is computed from the floating-point ratio for
<
li> <
code>Text</
code> - Each uncompressed text item is converted to a
<
code>com</
code> node and inserted according to the rules above for
merging <
code>com</
code> nodes.
<
p> <
code>setFromTree</
code> - Native Format
The <
code>setFromTree</
code> operation, when given a tree in the native
format described below, will simply replace the existing tree in its entirety
with the new one. The tree must consist of <
code>IIOMetadataNode</
code>s.
<
p> <
code>setFromTree</
code> - Standard Format
The <
code>setFromTree</
code> operation, when given a tree in the standard
format, performs a <
code>reset</
code> followed by a merge of the new tree.
<
a name=image>Image Metadata DTD</
a>
<!DOCTYPE "javax_imageio_jpeg_image_1.0" [
<!ELEMENT "javax_imageio_jpeg_image_1.0" (JPEGvariety, markerSequence)>
<!ELEMENT "JPEGvariety" (app0JFIF)>
<!-- A node grouping all marker segments specific to the variety of
<!ELEMENT "app0JFIF" (JFXX?, app2ICC?)>
<!ATTLIST "app0JFIF" "majorVersion" #CDATA "1">
<!-- The major JFIF version number -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "app0JFIF" "minorVersion" #CDATA "2">
<!-- The minor JFIF version number -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "app0JFIF" "resUnits" ("0" | "1" | "2") "0">
<!-- The resolution units for Xdensisty and Ydensity (0 = no
<!ATTLIST "app0JFIF" "Xdensity" #CDATA "1">
<!-- The horizontal density or aspect ratio numerator -->
<!-- Data type: Integer -->
<!-- Min value: 1 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ATTLIST "app0JFIF" "Ydensity" #CDATA "1">
<!-- The vertical density or aspect ratio denominator -->
<!-- Data type: Integer -->
<!-- Min value: 1 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ATTLIST "app0JFIF" "thumbWidth" #CDATA "0">
<!-- The width of the thumbnail, or 0 if there isn't one -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "app0JFIF" "thumbHeight" #CDATA "0">
<!-- The height of the thumbnail, or 0 if there isn't one -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ELEMENT "JFXX" (app0JFXX)*>
<!-- Min children: 1 -->
<!ELEMENT "app0JFXX" (JFIFthumbJPEG | JFIFthumbPalette |
<!-- A JFIF extension marker segment -->
<!ATTLIST "app0JFXX" "extensionCode" ("16" | "17" | "19")
<!-- The JFXX extension code identifying thumbnail type: (16 =
JPEG, 17 = indexed, 19 = RGB -->
<!ELEMENT "JFIFthumbJPEG" (markerSequence?)>
<!-- A JFIF thumbnail in JPEG format (no JFIF segments
<!ELEMENT "JFIFthumbPalette" EMPTY>
<!-- A JFIF thumbnail as an RGB indexed image -->
<!ATTLIST "JFIFthumbPalette" "thumbWidth" #CDATA #IMPLIED>
<!-- The width of the thumbnail -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "JFIFthumbPalette" "thumbHeight" #CDATA #IMPLIED>
<!-- The height of the thumbnail -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ELEMENT "JFIFthumbRGB" EMPTY>
<!-- A JFIF thumbnail as an RGB image -->
<!ATTLIST "JFIFthumbRGB" "thumbWidth" #CDATA #IMPLIED>
<!-- The width of the thumbnail -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "JFIFthumbRGB" "thumbHeight" #CDATA #IMPLIED>
<!-- The height of the thumbnail -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ELEMENT "app2ICC" EMPTY>
<!-- An ICC profile APP2 marker segment -->
<!ELEMENT "markerSequence" (dqt | dht | dri | com | unknown |
app14Adobe | sof | sos)*>
<!-- A node grouping all non-jfif marker segments -->
<!ELEMENT "dqt" (dqtable)*>
<!-- A Define Quantization Table(s) marker segment -->
<!-- Min children: 1 -->
<!-- Max children: 4 -->
<!ELEMENT "dqtable" EMPTY>
<!-- A single quantization table -->
<!ATTLIST "dqtable" "elementPrecision" #CDATA "0">
<!-- The number of bits in each table element (0 = 8, 1 = 16)
<!-- Data type: Integer -->
<!ATTLIST "dqtable" "qtableId" ("0" | "1" | "2" | "3") #REQUIRED>
<!ELEMENT "dht" (dhtable)*>
<!-- A Define Huffman Table(s) marker segment -->
<!-- Min children: 1 -->
<!-- Max children: 4 -->
<!ELEMENT "dhtable" EMPTY>
<!-- A single Huffman table -->
<!ATTLIST "dhtable" "class" ("0" | "1") #REQUIRED>
<!-- Indicates whether this is a DC (0) or an AC (1) table -->
<!ATTLIST "dhtable" "htableId" ("0" | "1" | "2" | "3") #REQUIRED>
<!-- The table id -->
<!ELEMENT "dri" EMPTY>
<!-- A Define Restart Interval marker segment -->
<!ATTLIST "dri" "interval" #CDATA #REQUIRED>
<!-- The restart interval in MCUs -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ELEMENT "com" EMPTY>
<!-- A Comment marker segment. The user object contains the actual
<!-- User object: array of [B -->
<!-- Min length: 1 -->
<!-- Max length: 65533 -->
<!ATTLIST "com" "comment" #CDATA #IMPLIED>
<!-- The comment as a string (used only if user object is null)
<!-- Data type: String -->
<!ELEMENT "unknown" EMPTY>
<!-- An unrecognized marker segment. The user object contains the
data not including length. -->
<!-- User object: array of [B -->
<!-- Min length: 1 -->
<!-- Max length: 65533 -->
<!ATTLIST "unknown" "MarkerTag" #CDATA #REQUIRED>
<!-- The tag identifying this marker segment -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ELEMENT "app14Adobe" EMPTY>
<!-- An Adobe APP14 marker segment -->
<!ATTLIST "app14Adobe" "version" #CDATA "100">
<!-- The version of Adobe APP14 marker segment -->
<!-- Data type: Integer -->
<!-- Min value: 100 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "app14Adobe" "flags0" #CDATA "0">
<!-- The flags0 variable of an APP14 marker segment -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ATTLIST "app14Adobe" "flags1" #CDATA "0">
<!-- The flags1 variable of an APP14 marker segment -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ATTLIST "app14Adobe" "transform" ("0" | "1" | "2") #REQUIRED>
<!-- The color transform applied to the image (0 = Unknown, 1 =
<!ELEMENT "sof" (componentSpec)*>
<!-- A Start Of Frame marker segment -->
<!-- Min children: 1 -->
<!-- Max children: 4 -->
<!ATTLIST "sof" "process" ("0" | "1" | "2") #IMPLIED>
<!-- The JPEG process (0 = Baseline sequential, 1 = Extended
sequential, 2 = Progressive) -->
<!ATTLIST "sof" "samplePrecision" #CDATA "8">
<!-- The number of bits per sample -->
<!-- Data type: Integer -->
<!ATTLIST "sof" "numLines" #CDATA #IMPLIED>
<!-- The number of lines in the image -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ATTLIST "sof" "samplesPerLine" #CDATA #IMPLIED>
<!-- The number of samples per line -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 65535 (inclusive) -->
<!ATTLIST "sof" "numFrameComponents" ("1" | "2" | "3" | "4")
<!-- The number of components in the image -->
<!ELEMENT "componentSpec" EMPTY>
<!-- A component specification for a frame -->
<!ATTLIST "componentSpec" "componentId" #CDATA #REQUIRED>
<!-- The id for this component -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "componentSpec" "HsamplingFactor" #CDATA #REQUIRED>
<!-- The horizontal sampling factor for this component -->
<!-- Data type: Integer -->
<!-- Min value: 1 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "componentSpec" "VsamplingFactor" #CDATA #REQUIRED>
<!-- The vertical sampling factor for this component -->
<!-- Data type: Integer -->
<!-- Min value: 1 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "componentSpec" "QtableSelector" ("0" | "1" | "2" |
<!-- The quantization table to use for this component -->
<!ELEMENT "sos" (scanComponentSpec)*>
<!-- A Start Of Scan marker segment -->
<!-- Min children: 1 -->
<!-- Max children: 4 -->
<!ATTLIST "sos" "numScanComponents" ("1" | "2" | "3" | "4")
<!-- The number of components in the scan -->
<!ATTLIST "sos" "startSpectralSelection" #CDATA "0">
<!-- The first spectral band included in this scan -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 63 (inclusive) -->
<!ATTLIST "sos" "endSpectralSelection" #CDATA "63">
<!-- The last spectral band included in this scan -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 63 (inclusive) -->
<!ATTLIST "sos" "approxHigh" #CDATA "0">
<!-- The highest bit position included in this scan -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 15 (inclusive) -->
<!ATTLIST "sos" "approxLow" #CDATA "0">
<!-- The lowest bit position included in this scan -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 15 (inclusive) -->
<!ELEMENT "scanComponentSpec" EMPTY>
<!-- A component specification for a scan -->
<!ATTLIST "scanComponentSpec" "componentSelector" #CDATA
<!-- The id of this component -->
<!-- Data type: Integer -->
<!-- Min value: 0 (inclusive) -->
<!-- Max value: 255 (inclusive) -->
<!ATTLIST "scanComponentSpec" "dcHuffTable" ("0" | "1" | "2" |
<!-- The huffman table to use for encoding DC coefficients -->
<!ATTLIST "scanComponentSpec" "acHuffTable" ("0" | "1" | "2" |
<!-- The huffman table to use for encoding AC coefficients -->
<
a name=stream>Stream Metadata DTD</
a>
<!DOCTYPE "javax_imageio_jpeg_stream_1.0" [
<!ELEMENT "javax_imageio_jpeg_stream_1.0" (dqt |
<!-- All elements are as defined above for image metadata -->