001: /*
002: * $RCSfile: J2KMetadataFormat.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.2 $
042: * $Date: 2005/04/27 18:23:01 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageioimpl.plugins.jpeg2000;
046:
047: import java.awt.image.ColorModel;
048: import java.awt.image.IndexColorModel;
049:
050: import java.lang.reflect.Method;
051: import java.util.ArrayList;
052: import java.util.Enumeration;
053: import java.util.Hashtable;
054: import java.util.Iterator;
055: import java.util.List;
056: import java.util.Set;
057: import javax.imageio.metadata.*;
058: import javax.imageio.ImageTypeSpecifier;
059:
060: public class J2KMetadataFormat extends IIOMetadataFormatImpl {
061: /** The table to link the child to its parent.
062: */
063: private static Hashtable parents = new Hashtable();
064:
065: static {
066: //children for the root
067: parents.put("JPEG2000SignatureBox",
068: "com_sun_media_imageio_plugins_jpeg2000_image_1.0");
069: parents.put("JPEG2000FileTypeBox",
070: "com_sun_media_imageio_plugins_jpeg2000_image_1.0");
071: parents.put("OtherBoxes",
072: "com_sun_media_imageio_plugins_jpeg2000_image_1.0");
073:
074: // children for the boxes other than
075: // JPEG2000SignatureBox/JPEG2000FileTypeBox
076: parents.put("JPEG2000HeaderSuperBox", "OtherBoxes");
077: parents.put("JPEG2000CodeStreamBox", "OtherBoxes");
078:
079: parents.put("JPEG2000IntellectualPropertyRightsBox",
080: "OtherBoxes");
081: parents.put("JPEG2000XMLBox", "OtherBoxes");
082: parents.put("JPEG2000UUIDBox", "OtherBoxes");
083: parents.put("JPEG2000UUIDInfoBox", "OtherBoxes");
084:
085: // Children of JPEG2000HeaderSuperBox
086: parents.put("JPEG2000HeaderBox", "JPEG2000HeaderSuperBox");
087: parents.put("OptionalBoxes", "JPEG2000HeaderSuperBox");
088:
089: // Optional boxes in JPEG2000HeaderSuperBox
090: parents.put("JPEG2000BitsPerComponentBox", "OptionalBoxes");
091: parents.put("JPEG2000ColorSpecificationBox", "OptionalBoxes");
092: parents.put("JPEG2000PaletteBox", "OptionalBoxes");
093: parents.put("JPEG2000ComponentMappingBox", "OptionalBoxes");
094: parents.put("JPEG2000ChannelDefinitionBox", "OptionalBoxes");
095: parents.put("JPEG2000ResolutionBox", "OptionalBoxes");
096:
097: // Children of JPEG2000ResolutionBox
098: parents.put("JPEG2000CaptureResolutionBox",
099: "JPEG2000ResolutionBox");
100: parents.put("JPEG2000DefaultDisplayResolutionBox",
101: "JPEG2000ResolutionBox");
102:
103: // Children of JPEG2000UUIDInfoBox
104: parents.put("JPEG2000UUIDListBox", "JPEG2000UUIDInfoBox");
105: parents.put("JPEG2000DataEntryURLBox", "JPEG2000UUIDInfoBox");
106: }
107:
108: private static J2KMetadataFormat instance;
109:
110: public static synchronized J2KMetadataFormat getInstance() {
111: if (instance == null)
112: instance = new J2KMetadataFormat();
113: return instance;
114: }
115:
116: String resourceBaseName = this .getClass().getName() + "Resources";
117:
118: /** Constructs <code>J2KMetadataFormat</code>. Calls the super
119: * class constructor. Sets the resource base name. Adds the elements
120: * into this format object based on the XML schema and DTD.
121: */
122: J2KMetadataFormat() {
123: super ("com_sun_media_imageio_plugins_jpeg2000_image_1.0",
124: CHILD_POLICY_ALL);
125: setResourceBaseName(resourceBaseName);
126: addElements();
127: }
128:
129: /** Adds the elements into this format object based on the XML
130: * schema and DTD.
131: */
132: private void addElements() {
133: addElement("JPEG2000SignatureBox",
134: getParent("JPEG2000SignatureBox"), CHILD_POLICY_EMPTY);
135:
136: addElement("JPEG2000FileTypeBox",
137: getParent("JPEG2000FileTypeBox"), CHILD_POLICY_ALL);
138: addElement("OtherBoxes", getParent("OtherBoxes"),
139: CHILD_POLICY_CHOICE);
140:
141: addElement("JPEG2000HeaderSuperBox",
142: getParent("JPEG2000HeaderSuperBox"),
143: CHILD_POLICY_CHOICE);
144: addElement("JPEG2000CodeStreamBox",
145: getParent("JPEG2000CodeStreamBox"), CHILD_POLICY_EMPTY);
146: addElement("JPEG2000IntellectualPropertyRightsBox",
147: getParent("JPEG2000IntellectualPropertyRightsBox"),
148: CHILD_POLICY_ALL);
149: addElement("JPEG2000XMLBox", getParent("JPEG2000XMLBox"),
150: CHILD_POLICY_ALL);
151: addElement("JPEG2000UUIDBox", getParent("JPEG2000UUIDBox"),
152: CHILD_POLICY_ALL);
153: addElement("JPEG2000UUIDInfoBox",
154: getParent("JPEG2000UUIDInfoBox"), CHILD_POLICY_ALL);
155:
156: addElement("JPEG2000HeaderBox", "JPEG2000HeaderSuperBox",
157: CHILD_POLICY_ALL);
158: addElement("OptionalBoxes", "JPEG2000HeaderSuperBox",
159: CHILD_POLICY_CHOICE);
160: addElement("JPEG2000BitsPerComponentBox", "OptionalBoxes",
161: CHILD_POLICY_ALL);
162: addElement("JPEG2000ColorSpecificationBox", "OptionalBoxes",
163: CHILD_POLICY_ALL);
164: addElement("JPEG2000PaletteBox", "OptionalBoxes",
165: CHILD_POLICY_ALL);
166: addElement("JPEG2000ComponentMappingBox", "OptionalBoxes",
167: CHILD_POLICY_ALL);
168: addElement("JPEG2000ChannelDefinitionBox", "OptionalBoxes",
169: CHILD_POLICY_ALL);
170: addElement("JPEG2000ResolutionBox", "OptionalBoxes",
171: CHILD_POLICY_ALL);
172:
173: addElement("JPEG2000CaptureResolutionBox",
174: "JPEG2000ResolutionBox", CHILD_POLICY_ALL);
175: addElement("JPEG2000DefaultDisplayResolutionBox",
176: "JPEG2000ResolutionBox", CHILD_POLICY_ALL);
177:
178: addElement("JPEG2000UUIDListBox", "JPEG2000UUIDInfoBox",
179: CHILD_POLICY_ALL);
180: addElement("JPEG2000DataEntryURLBox", "JPEG2000UUIDInfoBox",
181: CHILD_POLICY_ALL);
182: // Adds the default attributes "Length", "Type" and "ExtraLength" into
183: // the J2K box-related data elements
184: Enumeration keys = parents.keys();
185: while (keys.hasMoreElements()) {
186: String s = (String) keys.nextElement();
187: if (s.startsWith("JPEG2000")) {
188: addAttribute(s, "Length", DATATYPE_INTEGER, true, null);
189: addAttribute(s, "Type", DATATYPE_STRING, true, Box
190: .getTypeByName(s));
191: addAttribute(s, "ExtraLength", DATATYPE_STRING, false,
192: null);
193:
194: // If it is a simple node, adds the data elements by using
195: // relection.
196: Class c = Box.getBoxClass(Box.getTypeInt(Box
197: .getTypeByName(s)));
198:
199: try {
200: Method m = c.getMethod("getElementNames",
201: (Class[]) null);
202: String[] elementNames = (String[]) m.invoke(null,
203: (Object[]) null);
204: for (int i = 0; i < elementNames.length; i++)
205: addElement(elementNames[i], s,
206: CHILD_POLICY_EMPTY);
207: } catch (Exception e) {
208: // no such method
209: }
210: }
211: }
212:
213: addAttribute("JPEG2000SignatureBox", "Signature",
214: DATATYPE_STRING, true, "0D0A870A");
215:
216: addElement("BitDepth", "JPEG2000BitsPerComponentBox",
217: CHILD_POLICY_EMPTY);
218:
219: addElement("NumberEntries", "JPEG2000PaletteBox",
220: CHILD_POLICY_EMPTY);
221:
222: addElement("NumberColors", "JPEG2000PaletteBox",
223: CHILD_POLICY_EMPTY);
224:
225: addElement("BitDepth", "JPEG2000PaletteBox", CHILD_POLICY_EMPTY);
226:
227: addElement("LUT", "JPEG2000PaletteBox", 1, 1024);
228:
229: addElement("LUTRow", "LUT", CHILD_POLICY_EMPTY);
230:
231: addElement("Component", "JPEG2000ComponentMappingBox",
232: CHILD_POLICY_EMPTY);
233:
234: addElement("ComponentType", "JPEG2000ComponentMappingBox",
235: CHILD_POLICY_EMPTY);
236:
237: addElement("ComponentAssociation",
238: "JPEG2000ComponentMappingBox", CHILD_POLICY_EMPTY);
239:
240: addElement("NumberOfDefinition",
241: "JPEG2000ChannelDefinitionBox", CHILD_POLICY_EMPTY);
242:
243: addElement("Definitions", "JPEG2000ChannelDefinitionBox", 0, 9);
244:
245: addElement("ChannelNumber", "Definitions", CHILD_POLICY_EMPTY);
246:
247: addElement("ChannelType", "Definitions", CHILD_POLICY_EMPTY);
248: addElement("ChannelAssociation", "Definitions",
249: CHILD_POLICY_EMPTY);
250: addElement("CodeStream", "JPEG2000CodeStreamBox",
251: CHILD_POLICY_EMPTY);
252: addElement("Content", "JPEG2000IntellectualPropertyRightsBox",
253: CHILD_POLICY_EMPTY);
254: addElement("Content", "JPEG2000XMLBox", CHILD_POLICY_EMPTY);
255: addElement("UUID", "JPEG2000UUIDBox", CHILD_POLICY_EMPTY);
256: addElement("Data", "JPEG2000UUIDBox", CHILD_POLICY_EMPTY);
257: addElement("NumberUUID", "JPEG2000UUIDListBox",
258: CHILD_POLICY_EMPTY);
259: addElement("UUID", "JPEG2000UUIDListBox", CHILD_POLICY_EMPTY);
260: addElement("Version", "JPEG2000DataEntryURLBox",
261: CHILD_POLICY_EMPTY);
262: addElement("Flags", "JPEG2000DataEntryURLBox",
263: CHILD_POLICY_EMPTY);
264: addElement("URL", "JPEG2000DataEntryURLBox", CHILD_POLICY_EMPTY);
265: }
266:
267: public String getParent(String elementName) {
268: return (String) parents.get(elementName);
269: }
270:
271: public boolean canNodeAppear(String elementName,
272: ImageTypeSpecifier imageType) {
273: ColorModel cm = imageType.getColorModel();
274: if (!(cm instanceof IndexColorModel))
275: if ("JPEG2000PaletteBox".equals(elementName))
276: return false;
277: if (!cm.hasAlpha())
278: if ("JPEG2000ChannelDefinitionBox".equals(elementName))
279: return false;
280:
281: if (getParent(elementName) != null)
282: return true;
283: return false;
284: }
285:
286: public boolean isLeaf(String name) {
287: Set keys = parents.keySet();
288: Iterator iterator = keys.iterator();
289: while (iterator.hasNext()) {
290: if (name.equals(parents.get(iterator.next())))
291: return false;
292: }
293:
294: return true;
295: }
296:
297: public boolean singleInstance(String name) {
298: return !(name.equals("JPEG2000IntellectualPropertyRightsBox")
299: || name.equals("JPEG2000XMLBox")
300: || name.equals("JPEG2000UUIDBox")
301: || name.equals("JPEG2000UUIDInfoBox")
302: || name.equals("JPEG2000UUIDListBox") || name
303: .equals("JPEG2000DataEntryURLBox"));
304: }
305: }
|