diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/javax/imageio/metadata/doc-files/jpeg_metadata.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/javax/imageio/metadata/doc-files/jpeg_metadata.html Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,1148 @@ + + + + + +JPEG Metadata Format Specification and Usage Notes + + + + +

+JPEG Metadata Format Specification and Usage Notes +

+ +

+JPEG Metadata
+Abbreviated Streams
+Sources of Tables
+Colorspace Transformations and Conventional Markers
+Thumbnail Images
+Progressive Encoding
+Native Metadata Format Tree Structure and Editing
+Image Metadata DTD
+Stream Metadata DTD +

+NOTE: It is important to call dispose() +on the JPEG reader and writer objects when they are no longer needed, as +they consume significant native resources which are not adequately recovered +by garbage collection. Both reader and writer call dispose() +in their finalizers, but those finalizers may not be called before the native +code has exhausted native memory. + +

+ +The JPEG writer does not support replacing pixels. + +

+

+JPEG Metadata +

+JPEG metadata consists of the data contained in marker segments in a JPEG +stream. The image metadata object returned from a read describes the +contents of the marker segments between the SOI marker and +the EOI marker for that image. The image metadata object +passed into a write determines the contents of the stream between the +SOI marker and the EOI marker for that image, +subject to the controls in any ImageWriteParam. + +

+Stream metadata is used only for tables-only images found (or to be +placed) at the beginning of a stream containing abbreviated images. +Tables-only images are not treated as images and do not consume an +image index. The stream metadata object returned from a read describes the +contents of the marker segments between the SOI marker and +the EOI marker for the single tables-only image at the +beginning of the stream, if one is present. If no tables-only image is +present at the front of the stream, the getStreamMetadata +method of ImageReader returns null. If +stream metadata is provided to the writer, a single tables-only image +containing the tables from the stream metadata object will be written at +the beginning of the stream. If the stream metadata object contains no +tables, default tables will be written. As the sole purpose of stream +metadata is for specifying tables-only images at the front of abbreviated +streams, the stream metadata argument is useful only on the +ImageWriter.prepareWriteSequence method. It is ignored on all +other methods. + +

+The ImageWriter.getDefaultStreamMetadata method returns an +object containing the tables from the ImageWriteParam argument, +if it is a JPEGImageWriteParam and contains tables. Otherwise, +the returned object will contain default tables. + +

The ImageWriter.getDefaultImageMetadata method returns a +metadata object containing no tables if the +ImageWriteParam argument contains tables. Otherwise the +returned metadata object will contain default visually lossless tables. +Of course, only a JPEGImageWriteParam may contain tables. + +

+If ignoreMetadata is set to true when the input +is set on the reader, stream metadata will not be available, but image +metadata will. + +

+

+Abbreviated Streams +

+Both the reader and the writer retain their tables from one operation to the +next, thus permitting the use of abbreviated streams quite naturally, with a +few minor restrictions: +
    +
  1. Abbreviated streams may contain only one tables-only image, which must + come first in the stream. Subsequent tables-only images will cause + undefined behavior.
  2. +
  3. Abbreviated streams must be read fully and in order. No random access + is allowed, in either direction. The same image may be read multiple + times. If a call is made with an image index that is not the same as + or one greater than the most recent call (or 0 if no calls have been + made), then an IllegalArgumentException is thrown.
  4. +
+These restrictions mean that streams may contain abbreviated images +interspersed with images containing tables. As required by JPEG, any tables +appearing in the stream override previous tables, regardless of the source +of the previous tables. + +

+Note that once a tables-only image has been read, it's contents is available +as stream metadata from the reader until either another tables-only image +is read from another stream or the reader is reset. Changing the input does +not reset the stream metadata. This is useful for reading the tables from +one file, then changing the input to read an abbreviated stream containing +a sequence of images. The tables will be used automatically, and will remain +available as "stream" metadata. + +

+Abbreviated streams are written using the sequence methods of +ImageWriter. Stream metadata is used to write a tables-only +image at the beginning of the stream, and the tables are set up for use, using +ImageWriter.prepareWriteSequence. If no stream metadata is +supplied to ImageWriter.prepareWriteSequence, then no +tables-only image is written. If stream metadata containing no tables is +supplied to ImageWriter.prepareWriteSequence, then a tables-only +image containing default visually lossless tables is written. + +

+Sources of Tables +

+

+Images are written with tables if tables are present in their metadata objects +or without them if no tables are present in their metadata objects. If no +metadata object is present then the tables are written. The tables used for +compression are taken from one of the following sources, which are consulted +in order: +

    +
  1. If there is an ImageWriteParam and the compression mode is + set to EXPLICIT, default tables constructed using the + quality setting are used. They are written only if the metadata + contains tables or if there is no metadata, but they replace the + tables in the metadata.
  2. +
  3. If there is an ImageWriteParam and the compression mode is + set to DEFAULT, default visually lossles tables are used. + They are written only if the metadata contains tables or if + there is no metadata, but they replace the tables in the + metadata.
  4. +
  5. Otherwise the compression mode on the ImageWriteParam must + be MODE_COPY_FROM_METADATA, in which case the following + are used: +
      +
    1. the tables in the image metadata, if present
    2. +
    3. the tables in the stream metadata, if present
    4. +
    5. the tables in the JPEGImageWriteParam, if present
    6. +
    7. default visually lossless tables
    8. +
    Tables are written only if they are taken from image metadata. +
  6. +
+ +This ordering implements the design intention that tables should be included +in JPEGImageWriteParams only as a means of specifying tables +when no other source is available, and this can occur only when writing to an +abbreviated stream without tables using known non-standard tables for +compression. + +

+When reading, tables in a JPEGImageReadParam are consulted only +if tables have not been set by any previous read. Tables set from a +JPEGImageReadParam are overridden by any tables present in the +stream being read. + +

+Note that if no image metadata object is specified for a particular image, a +default object is used, which includes default tables. + +

+

+Colorspace Transformations and Conventional Markers +

+Colorspace transformations are controlled by the destination type for +both reading and writing of images. When Rasters are +read, no colorspace transformation is performed, and any destination type +is ignored. A warning is sent to any listeners if a destination type is +specified in this case. When Rasters are written, any +destination type is used to interpret the bands. This might result in a +JFIF or Adobe header being written, or different component ids being written +to the frame and scan headers. If values present in a metadata object do not +match the destination type, the destination type is used and a warning is sent +to any listeners. + +

+ +When reading, the contents of the stream are interpreted by the usual +JPEG conventions, as follows: + +

+ +Once an encoded colorspace is determined, then the target colorspace is +determined as follows: + + + +

+For writing, the color transformation to apply is determined as +follows: + +

+If a subset of the source bands is to be written, no color conversion is +performed. Any destination, if set, must match the number of bands that will +be written, and serves as an interpretation of the selected bands, rather than +a conversion request. This behavior is identical to that for +Rasters. If all the bands are to be written and an image +(as opposed to a Raster) is being written, any destination type +is ignored and a warning is sent to any listeners. + +

+If a destination type is used and any aspect of the metadata object, if there +is one, is not compatible with that type, the destination type is used, the +metadata written is modified from that provided, and a warning is sent to +listeners. This includes the app0JFIF and +app14Adobe nodes. The component ids in the sof and +sos nodes are not modified, however, as unless a +app0JFIF node is present, any values may be used. +

+ +When a full image is written, a destination colorspace will be +chosen based on the image contents and the metadata settings, according to +the following algorithm: + +

+ +If no metadata object is specified, then the following defaults apply: + +

+ +Default metadata objects for these image types will reflect these settings. + +

+ +If a metadata object is specified, then the number of channels in the +frame and scan headers must always match the number of bands to be +written, or an exception is thrown. app0JFIF and +app14Adobe nodes may appear in the same metadata object only +if the app14Adobe node indicates YCbCr, and the component ids +are JFIF compatible (0-2). The various image types are processed in the +following ways: + +
+ +(All multi-channel images are subsampled according to the sampling factors +in the frame header node of the metadata object, regardless of color space.) + +

+ +

+

+Thumbnail Images +

+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. app0JFIF and app0JFXX 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. + +

+ +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 +listeners. + +

+

+Progressive Encoding +

+ +Progressive encoding must be enabled on the ImageWriteParam +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 ImageWriteParam, +all Huffman tables in the metadata or in the ImageWriteParam +itself are ignored, and a warning will be sent to any warning listeners if +any such tables are present. + +

+

+Native Metadata Format Tree Structure and Editing +

+ +The DTDs below describe just the trees of metadata objects actually returned +by the IIOMetadata object. They do not include nodes +corresponding to SOI, EOI, or RST +markers, as these parsing delimiters do not carry any meaningful metadata. +

+ +The first node is always a JPEGvariety node. In the +javax_imageio_jpeg_image_1.0 version of the JPEG metadata +format, this node may have one child, an app0JFIF 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 JPEGvariety node. +

+ +(Note that an application wishing to interpret Exif metadata given +a metadata tree structure in the javax_imageio_jpeg_image_1.0 +format must check for an unknown marker segment with a tag +indicating an APP1 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 +unknown in that format - it might be structured as a +child node of the JPEGvariety node. Thus, it is important +for an application to specify which version to use by passing the string +identifying the version to the method/constructor used to obtain an +IIOMetadata object.) + +

+ +On reading, JFXX and app2ICC nodes occur as +children of an app0JFIF node. +This is true regardless of where the JFXX APP0 and +APP2 marker segments actually occur in the stream. The ordering +of nodes within the markerSequence node corresponds to the +ordering of marker segments found in the JPEG stream. +

+On writing, any JFXX and app2ICC nodes must +occur as children of an app0JFIF node, itself a child of a +JPEGvariety node, which must always be the first node. +(If the stream is not to be JFIF compliant, no app0JFIF node +should be provided, and the JPEGvariety node should have no +children.) Any +JFIF APP0, JFXX APP0, and APP2 marker +segments are written first, followed by all Adobe APP14, +APPn, COM and unknown segments in the +order in which their corresponding nodes appear in the +markerSequence node, followed by DQT (and +DHT for non-progressive writes) marker segments, followed by the +SOF and SOS marker segments. For progressive writes +using metadata to control progression, the SOS segments are used +in the order in which their corresponding nodes occur in the +markerSequence node. +

+ +The reset, mergeTree and setFromTree +operations have the following semantics for the JPEG plug-in metadata object: + +

reset - A call to reset 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 ImageWriter. This is true regardless of how many times the +metadata object has been modified since creation. + +

mergeTree - Native Format +
The mergeTree 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 +mergeTree. To remove nodes, use setFromTree. The +tree must consist of IIOMetadataNodes. +

+ +

mergeTree - Standard Format +
+The mergeTree operation, when given a tree in the standard +format, will modify the native tree in the following ways: +

+ +

setFromTree - Native Format +
+The setFromTree 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 IIOMetadataNodes. + +

setFromTree - Standard Format +
+The setFromTree operation, when given a tree in the standard +format, performs a reset followed by a merge of the new tree. + +

+Image Metadata DTD +

+ +
+<!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
+              stream being read/written (e.g. JFIF) - may be empty --> 
+
+      <!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 
+               units, just aspect ratio; 1 = dots/inch; 2 = dots/cm) --> 
+        <!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 | 
+          JFIFthumbRGB)>
+          <!-- A JFIF extension marker segment --> 
+          <!ATTLIST "app0JFXX" "extensionCode" ("16" | "17" | "19")
+             #IMPLIED>
+            <!-- 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 
+                 permitted) --> 
+
+          <!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 --> 
+          <!-- Optional User object: java.awt.color.ICC_Profile -->
+
+    <!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 --> 
+          <!-- User object: javax.imageio.plugins.jpeg.JPEGQTable -->
+          <!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 --> 
+          <!-- User object: javax.imageio.plugins.jpeg.JPEGHuffmanTable -->
+          <!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 
+             bytes. --> 
+        <!-- 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 = 
+               YCbCr, 2 = YCCK) --> 
+
+      <!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")
+           #IMPLIED>
+          <!-- 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" | 
+            "3") #REQUIRED>
+            <!-- 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")
+           #REQUIRED>
+          <!-- 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
+             #REQUIRED>
+            <!-- The id of this component --> 
+            <!-- Data type: Integer -->
+            <!-- Min value: 0 (inclusive) -->
+            <!-- Max value: 255 (inclusive) -->
+          <!ATTLIST "scanComponentSpec" "dcHuffTable" ("0" | "1" | "2" | 
+            "3") #REQUIRED>
+            <!-- The huffman table to use for encoding DC coefficients --> 
+          <!ATTLIST "scanComponentSpec" "acHuffTable" ("0" | "1" | "2" | 
+            "3") #REQUIRED>
+            <!-- The huffman table to use for encoding AC coefficients --> 
+]>
+
+ +

+Stream Metadata DTD +

+ +
+<!DOCTYPE "javax_imageio_jpeg_stream_1.0" [
+  <!ELEMENT "javax_imageio_jpeg_stream_1.0" (dqt |
+                      dht | 
+                      dri | 
+                      com | 
+                      unknown)*>
+   
+  <!-- All elements are as defined above for image metadata -->
+]>
+
+ + +