1. /*
  2. * @(#)GIFStreamMetadata.java 1.25 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.imageio.plugins.gif;
  8. import javax.imageio.ImageTypeSpecifier;
  9. import javax.imageio.metadata.IIOMetadata;
  10. import javax.imageio.metadata.IIOMetadataNode;
  11. import javax.imageio.metadata.IIOMetadataFormat;
  12. import javax.imageio.metadata.IIOMetadataFormatImpl;
  13. import org.w3c.dom.Node;
  14. // TODO - document elimination of globalColorTableFlag
  15. /**
  16. * @version 0.5
  17. */
  18. public class GIFStreamMetadata extends IIOMetadata {
  19. // package scope
  20. static final String
  21. nativeMetadataFormatName = "javax_imageio_gif_stream_1.0";
  22. public static final String[] versionStrings = { "87a", "89a" };
  23. public String version; // 87a or 89a
  24. public int logicalScreenWidth;
  25. public int logicalScreenHeight;
  26. public int colorResolution; // 1 to 8
  27. public int pixelAspectRatio;
  28. public int backgroundColorIndex; // Valid if globalColorTable != null
  29. public boolean sortFlag; // Valid if globalColorTable != null
  30. public static final String[] colorTableSizes = {
  31. "2", "4", "8", "16", "32", "64", "128", "256"
  32. };
  33. // Set global color table flag in header to 0 if null, 1 otherwise
  34. public byte[] globalColorTable = null;
  35. public GIFStreamMetadata() {
  36. super(true,
  37. nativeMetadataFormatName,
  38. "com.sun.imageio.plugins.gif.GIFStreamMetadataFormat",
  39. null, null);
  40. }
  41. public boolean isReadOnly() {
  42. return true;
  43. }
  44. public Node getAsTree(String formatName) {
  45. if (formatName.equals(nativeMetadataFormatName)) {
  46. return getNativeTree();
  47. } else if (formatName.equals
  48. (IIOMetadataFormatImpl.standardMetadataFormatName)) {
  49. return getStandardTree();
  50. } else {
  51. throw new IllegalArgumentException("Not a recognized format!");
  52. }
  53. }
  54. private Node getNativeTree() {
  55. IIOMetadataNode node; // scratch node
  56. IIOMetadataNode root =
  57. new IIOMetadataNode(nativeMetadataFormatName);
  58. node = new IIOMetadataNode("Version");
  59. node.setAttribute("value", version);
  60. root.appendChild(node);
  61. // Image descriptor
  62. node = new IIOMetadataNode("LogicalScreenDescriptor");
  63. node.setAttribute("logicalScreenWidth",
  64. Integer.toString(logicalScreenWidth));
  65. node.setAttribute("logicalScreenHeight",
  66. Integer.toString(logicalScreenHeight));
  67. // Stored value plus one
  68. node.setAttribute("colorResolution",
  69. Integer.toString(colorResolution));
  70. node.setAttribute("pixelAspectRatio",
  71. Integer.toString(pixelAspectRatio));
  72. root.appendChild(node);
  73. if (globalColorTable != null) {
  74. node = new IIOMetadataNode("GlobalColorTable");
  75. int numEntries = globalColorTable.length3;
  76. node.setAttribute("sizeOfGlobalColorTable",
  77. Integer.toString(numEntries));
  78. node.setAttribute("backgroundColorIndex",
  79. Integer.toString(backgroundColorIndex));
  80. node.setAttribute("sortFlag",
  81. sortFlag ? "TRUE" : "FALSE");
  82. for (int i = 0; i < numEntries; i++) {
  83. IIOMetadataNode entry =
  84. new IIOMetadataNode("ColorTableEntry");
  85. entry.setAttribute("index", Integer.toString(i));
  86. int r = globalColorTable[3*i] & 0xff;
  87. int g = globalColorTable[3*i + 1] & 0xff;
  88. int b = globalColorTable[3*i + 2] & 0xff;
  89. entry.setAttribute("red", Integer.toString(r));
  90. entry.setAttribute("green", Integer.toString(g));
  91. entry.setAttribute("blue", Integer.toString(b));
  92. node.appendChild(entry);
  93. }
  94. root.appendChild(node);
  95. }
  96. return root;
  97. }
  98. public IIOMetadataNode getStandardChromaNode() {
  99. IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
  100. IIOMetadataNode node = null; // scratch node
  101. node = new IIOMetadataNode("ColorSpaceType");
  102. node.setAttribute("name", "RGB");
  103. chroma_node.appendChild(node);
  104. node = new IIOMetadataNode("BlackIsZero");
  105. node.setAttribute("value", "TRUE");
  106. chroma_node.appendChild(node);
  107. // NumChannels not in stream
  108. // Gamma not in format
  109. if (globalColorTable != null) {
  110. node = new IIOMetadataNode("Palette");
  111. int numEntries = globalColorTable.length3;
  112. for (int i = 0; i < numEntries; i++) {
  113. IIOMetadataNode entry =
  114. new IIOMetadataNode("PaletteEntry");
  115. entry.setAttribute("index", Integer.toString(i));
  116. entry.setAttribute("red",
  117. Integer.toString(globalColorTable[3*i] & 0xff));
  118. entry.setAttribute("green",
  119. Integer.toString(globalColorTable[3*i + 1] & 0xff));
  120. entry.setAttribute("blue",
  121. Integer.toString(globalColorTable[3*i + 2] & 0xff));
  122. node.appendChild(entry);
  123. }
  124. chroma_node.appendChild(node);
  125. // backgroundColorIndex is valid iff there is a color table
  126. node = new IIOMetadataNode("BackgroundIndex");
  127. node.setAttribute("value", Integer.toString(backgroundColorIndex));
  128. chroma_node.appendChild(node);
  129. }
  130. return chroma_node;
  131. }
  132. public IIOMetadataNode getStandardCompressionNode() {
  133. IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
  134. IIOMetadataNode node = null; // scratch node
  135. node = new IIOMetadataNode("CompressionTypeName");
  136. node.setAttribute("value", "lzw");
  137. compression_node.appendChild(node);
  138. node = new IIOMetadataNode("Lossless");
  139. node.setAttribute("value", "true");
  140. compression_node.appendChild(node);
  141. // NumProgressiveScans not in stream
  142. // BitRate not in format
  143. return compression_node;
  144. }
  145. public IIOMetadataNode getStandardDataNode() {
  146. IIOMetadataNode data_node = new IIOMetadataNode("Data");
  147. IIOMetadataNode node = null; // scratch node
  148. // PlanarConfiguration
  149. node = new IIOMetadataNode("SampleFormat");
  150. node.setAttribute("value", "Index");
  151. data_node.appendChild(node);
  152. node = new IIOMetadataNode("BitsPerSample");
  153. node.setAttribute("value", Integer.toString(colorResolution));
  154. data_node.appendChild(node);
  155. // SignificantBitsPerSample
  156. // SampleMSB
  157. return data_node;
  158. }
  159. public IIOMetadataNode getStandardDimensionNode() {
  160. IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
  161. IIOMetadataNode node = null; // scratch node
  162. node = new IIOMetadataNode("PixelAspectRatio");
  163. float aspectRatio = 1.0F;
  164. if (pixelAspectRatio != 0) {
  165. aspectRatio = (pixelAspectRatio + 15)/64.0F;
  166. }
  167. node.setAttribute("value", Float.toString(aspectRatio));
  168. dimension_node.appendChild(node);
  169. node = new IIOMetadataNode("ImageOrientation");
  170. node.setAttribute("value", "Normal");
  171. dimension_node.appendChild(node);
  172. // HorizontalPixelSize not in format
  173. // VerticalPixelSize not in format
  174. // HorizontalPhysicalPixelSpacing not in format
  175. // VerticalPhysicalPixelSpacing not in format
  176. // HorizontalPosition not in format
  177. // VerticalPosition not in format
  178. // HorizontalPixelOffset not in stream
  179. // VerticalPixelOffset not in stream
  180. node = new IIOMetadataNode("HorizontalScreenSize");
  181. node.setAttribute("value", Integer.toString(logicalScreenWidth));
  182. dimension_node.appendChild(node);
  183. node = new IIOMetadataNode("VerticalScreenSize");
  184. node.setAttribute("value", Integer.toString(logicalScreenHeight));
  185. dimension_node.appendChild(node);
  186. return dimension_node;
  187. }
  188. public IIOMetadataNode getStandardDocumentNode() {
  189. IIOMetadataNode document_node = new IIOMetadataNode("Document");
  190. IIOMetadataNode node = null; // scratch node
  191. node = new IIOMetadataNode("FormatVersion");
  192. node.setAttribute("value", version);
  193. document_node.appendChild(node);
  194. // SubimageInterpretation not in format
  195. // ImageCreationTime not in format
  196. // ImageModificationTime not in format
  197. return document_node;
  198. }
  199. public IIOMetadataNode getStandardTextNode() {
  200. // Not in stream
  201. return null;
  202. }
  203. public IIOMetadataNode getStandardTransparencyNode() {
  204. // Not in stream
  205. return null;
  206. }
  207. public void setFromTree(String formatName, Node root) {
  208. throw new IllegalStateException("Metadata is read-only!");
  209. }
  210. public void mergeTree(String formatName, Node root) {
  211. throw new IllegalStateException("Metadata is read-only!");
  212. }
  213. public void reset() {
  214. throw new IllegalStateException("Metadata is read-only!");
  215. }
  216. }