001: /*
002: * $RCSfile: GIFStreamMetadata.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.1 $
042: * $Date: 2006/03/24 22:30:10 $
043: * $State: Exp $
044: */
045:
046: package com.sun.media.imageioimpl.plugins.gif;
047:
048: import javax.imageio.ImageTypeSpecifier;
049: import javax.imageio.metadata.IIOInvalidTreeException;
050: import javax.imageio.metadata.IIOMetadata;
051: import javax.imageio.metadata.IIOMetadataNode;
052: import javax.imageio.metadata.IIOMetadataFormat;
053: import javax.imageio.metadata.IIOMetadataFormatImpl;
054: import org.w3c.dom.Node;
055:
056: // TODO - document elimination of globalColorTableFlag
057:
058: /**
059: * @version 0.5
060: */
061: public class GIFStreamMetadata extends GIFMetadata {
062:
063: // package scope
064: static final String nativeMetadataFormatName = "javax_imageio_gif_stream_1.0";
065:
066: public static final String[] versionStrings = { "87a", "89a" };
067:
068: public String version; // 87a or 89a
069: public int logicalScreenWidth;
070: public int logicalScreenHeight;
071: public int colorResolution; // 1 to 8
072: public int pixelAspectRatio;
073:
074: public int backgroundColorIndex; // Valid if globalColorTable != null
075: public boolean sortFlag; // Valid if globalColorTable != null
076:
077: public static final String[] colorTableSizes = { "2", "4", "8",
078: "16", "32", "64", "128", "256" };
079:
080: // Set global color table flag in header to 0 if null, 1 otherwise
081: public byte[] globalColorTable = null;
082:
083: protected GIFStreamMetadata(
084: boolean standardMetadataFormatSupported,
085: String nativeMetadataFormatName,
086: String nativeMetadataFormatClassName,
087: String[] extraMetadataFormatNames,
088: String[] extraMetadataFormatClassNames) {
089: super (standardMetadataFormatSupported,
090: nativeMetadataFormatName,
091: nativeMetadataFormatClassName,
092: extraMetadataFormatNames, extraMetadataFormatClassNames);
093: }
094:
095: public GIFStreamMetadata() {
096: this (
097: true,
098: nativeMetadataFormatName,
099: "com.sun.media.imageioimpl.plugins.gif.GIFStreamMetadataFormat",
100: null, null);
101:
102: }
103:
104: public boolean isReadOnly() {
105: return true;
106: }
107:
108: public Node getAsTree(String formatName) {
109: if (formatName.equals(nativeMetadataFormatName)) {
110: return getNativeTree();
111: } else if (formatName
112: .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
113: return getStandardTree();
114: } else {
115: throw new IllegalArgumentException(
116: "Not a recognized format!");
117: }
118: }
119:
120: private Node getNativeTree() {
121: IIOMetadataNode node; // scratch node
122: IIOMetadataNode root = new IIOMetadataNode(
123: nativeMetadataFormatName);
124:
125: node = new IIOMetadataNode("Version");
126: node.setAttribute("value", version);
127: root.appendChild(node);
128:
129: // Image descriptor
130: node = new IIOMetadataNode("LogicalScreenDescriptor");
131: /* NB: At the moment we use empty strings to support undefined
132: * integer values in tree representation.
133: * We need to add better support for undefined/default values later.
134: */
135: node.setAttribute("logicalScreenWidth",
136: logicalScreenWidth == UNDEFINED_INTEGER_VALUE ? ""
137: : Integer.toString(logicalScreenWidth));
138: node.setAttribute("logicalScreenHeight",
139: logicalScreenHeight == UNDEFINED_INTEGER_VALUE ? ""
140: : Integer.toString(logicalScreenHeight));
141: // Stored value plus one
142: node.setAttribute("colorResolution",
143: colorResolution == UNDEFINED_INTEGER_VALUE ? ""
144: : Integer.toString(colorResolution));
145: node.setAttribute("pixelAspectRatio", Integer
146: .toString(pixelAspectRatio));
147: root.appendChild(node);
148:
149: if (globalColorTable != null) {
150: node = new IIOMetadataNode("GlobalColorTable");
151: int numEntries = globalColorTable.length / 3;
152: node.setAttribute("sizeOfGlobalColorTable", Integer
153: .toString(numEntries));
154: node.setAttribute("backgroundColorIndex", Integer
155: .toString(backgroundColorIndex));
156: node.setAttribute("sortFlag", sortFlag ? "TRUE" : "FALSE");
157:
158: for (int i = 0; i < numEntries; i++) {
159: IIOMetadataNode entry = new IIOMetadataNode(
160: "ColorTableEntry");
161: entry.setAttribute("index", Integer.toString(i));
162: int r = globalColorTable[3 * i] & 0xff;
163: int g = globalColorTable[3 * i + 1] & 0xff;
164: int b = globalColorTable[3 * i + 2] & 0xff;
165: entry.setAttribute("red", Integer.toString(r));
166: entry.setAttribute("green", Integer.toString(g));
167: entry.setAttribute("blue", Integer.toString(b));
168: node.appendChild(entry);
169: }
170: root.appendChild(node);
171: }
172:
173: return root;
174: }
175:
176: public IIOMetadataNode getStandardChromaNode() {
177: IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
178: IIOMetadataNode node = null; // scratch node
179:
180: node = new IIOMetadataNode("ColorSpaceType");
181: node.setAttribute("name", "RGB");
182: chroma_node.appendChild(node);
183:
184: node = new IIOMetadataNode("BlackIsZero");
185: node.setAttribute("value", "TRUE");
186: chroma_node.appendChild(node);
187:
188: // NumChannels not in stream
189: // Gamma not in format
190:
191: if (globalColorTable != null) {
192: node = new IIOMetadataNode("Palette");
193: int numEntries = globalColorTable.length / 3;
194: for (int i = 0; i < numEntries; i++) {
195: IIOMetadataNode entry = new IIOMetadataNode(
196: "PaletteEntry");
197: entry.setAttribute("index", Integer.toString(i));
198: entry.setAttribute("red", Integer
199: .toString(globalColorTable[3 * i] & 0xff));
200: entry.setAttribute("green", Integer
201: .toString(globalColorTable[3 * i + 1] & 0xff));
202: entry.setAttribute("blue", Integer
203: .toString(globalColorTable[3 * i + 2] & 0xff));
204: node.appendChild(entry);
205: }
206: chroma_node.appendChild(node);
207:
208: // backgroundColorIndex is valid iff there is a color table
209: node = new IIOMetadataNode("BackgroundIndex");
210: node.setAttribute("value", Integer
211: .toString(backgroundColorIndex));
212: chroma_node.appendChild(node);
213: }
214:
215: return chroma_node;
216: }
217:
218: public IIOMetadataNode getStandardCompressionNode() {
219: IIOMetadataNode compression_node = new IIOMetadataNode(
220: "Compression");
221: IIOMetadataNode node = null; // scratch node
222:
223: node = new IIOMetadataNode("CompressionTypeName");
224: node.setAttribute("value", "lzw");
225: compression_node.appendChild(node);
226:
227: node = new IIOMetadataNode("Lossless");
228: node.setAttribute("value", "true");
229: compression_node.appendChild(node);
230:
231: // NumProgressiveScans not in stream
232: // BitRate not in format
233:
234: return compression_node;
235: }
236:
237: public IIOMetadataNode getStandardDataNode() {
238: IIOMetadataNode data_node = new IIOMetadataNode("Data");
239: IIOMetadataNode node = null; // scratch node
240:
241: // PlanarConfiguration
242:
243: node = new IIOMetadataNode("SampleFormat");
244: node.setAttribute("value", "Index");
245: data_node.appendChild(node);
246:
247: node = new IIOMetadataNode("BitsPerSample");
248: node.setAttribute("value",
249: colorResolution == UNDEFINED_INTEGER_VALUE ? ""
250: : Integer.toString(colorResolution));
251: data_node.appendChild(node);
252:
253: // SignificantBitsPerSample
254: // SampleMSB
255:
256: return data_node;
257: }
258:
259: public IIOMetadataNode getStandardDimensionNode() {
260: IIOMetadataNode dimension_node = new IIOMetadataNode(
261: "Dimension");
262: IIOMetadataNode node = null; // scratch node
263:
264: node = new IIOMetadataNode("PixelAspectRatio");
265: float aspectRatio = 1.0F;
266: if (pixelAspectRatio != 0) {
267: aspectRatio = (pixelAspectRatio + 15) / 64.0F;
268: }
269: node.setAttribute("value", Float.toString(aspectRatio));
270: dimension_node.appendChild(node);
271:
272: node = new IIOMetadataNode("ImageOrientation");
273: node.setAttribute("value", "Normal");
274: dimension_node.appendChild(node);
275:
276: // HorizontalPixelSize not in format
277: // VerticalPixelSize not in format
278: // HorizontalPhysicalPixelSpacing not in format
279: // VerticalPhysicalPixelSpacing not in format
280: // HorizontalPosition not in format
281: // VerticalPosition not in format
282: // HorizontalPixelOffset not in stream
283: // VerticalPixelOffset not in stream
284:
285: node = new IIOMetadataNode("HorizontalScreenSize");
286: node.setAttribute("value",
287: logicalScreenWidth == UNDEFINED_INTEGER_VALUE ? ""
288: : Integer.toString(logicalScreenWidth));
289: dimension_node.appendChild(node);
290:
291: node = new IIOMetadataNode("VerticalScreenSize");
292: node.setAttribute("value",
293: logicalScreenHeight == UNDEFINED_INTEGER_VALUE ? ""
294: : Integer.toString(logicalScreenHeight));
295: dimension_node.appendChild(node);
296:
297: return dimension_node;
298: }
299:
300: public IIOMetadataNode getStandardDocumentNode() {
301: IIOMetadataNode document_node = new IIOMetadataNode("Document");
302: IIOMetadataNode node = null; // scratch node
303:
304: node = new IIOMetadataNode("FormatVersion");
305: node.setAttribute("value", version);
306: document_node.appendChild(node);
307:
308: // SubimageInterpretation not in format
309: // ImageCreationTime not in format
310: // ImageModificationTime not in format
311:
312: return document_node;
313: }
314:
315: public IIOMetadataNode getStandardTextNode() {
316: // Not in stream
317: return null;
318: }
319:
320: public IIOMetadataNode getStandardTransparencyNode() {
321: // Not in stream
322: return null;
323: }
324:
325: public void setFromTree(String formatName, Node root)
326: throws IIOInvalidTreeException {
327: throw new IllegalStateException("Metadata is read-only!");
328: }
329:
330: protected void mergeNativeTree(Node root)
331: throws IIOInvalidTreeException {
332: throw new IllegalStateException("Metadata is read-only!");
333: }
334:
335: protected void mergeStandardTree(Node root)
336: throws IIOInvalidTreeException {
337: throw new IllegalStateException("Metadata is read-only!");
338: }
339:
340: public void reset() {
341: throw new IllegalStateException("Metadata is read-only!");
342: }
343: }
|