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