1/* 2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.imageio.plugins.gif; 27 28/* 29 * The source for this class was copied verbatim from the source for 30 * package com.sun.imageio.plugins.gif.GIFImageMetadata and then modified 31 * to make the class read-write capable. 32 */ 33 34import javax.imageio.ImageTypeSpecifier; 35import javax.imageio.metadata.IIOInvalidTreeException; 36import javax.imageio.metadata.IIOMetadata; 37import javax.imageio.metadata.IIOMetadataNode; 38import javax.imageio.metadata.IIOMetadataFormat; 39import javax.imageio.metadata.IIOMetadataFormatImpl; 40import org.w3c.dom.Node; 41 42class GIFWritableStreamMetadata extends GIFStreamMetadata { 43 44 // package scope 45 static final String 46 NATIVE_FORMAT_NAME = "javax_imageio_gif_stream_1.0"; 47 48 public GIFWritableStreamMetadata() { 49 super(true, 50 NATIVE_FORMAT_NAME, 51 "com.sun.imageio.plugins.gif.GIFStreamMetadataFormat", // XXX J2SE 52 null, null); 53 54 // initialize metadata fields by default values 55 reset(); 56 } 57 58 public boolean isReadOnly() { 59 return false; 60 } 61 62 public void mergeTree(String formatName, Node root) 63 throws IIOInvalidTreeException { 64 if (formatName.equals(nativeMetadataFormatName)) { 65 if (root == null) { 66 throw new IllegalArgumentException("root == null!"); 67 } 68 mergeNativeTree(root); 69 } else if (formatName.equals 70 (IIOMetadataFormatImpl.standardMetadataFormatName)) { 71 if (root == null) { 72 throw new IllegalArgumentException("root == null!"); 73 } 74 mergeStandardTree(root); 75 } else { 76 throw new IllegalArgumentException("Not a recognized format!"); 77 } 78 } 79 80 public void reset() { 81 version = null; 82 83 logicalScreenWidth = UNDEFINED_INTEGER_VALUE; 84 logicalScreenHeight = UNDEFINED_INTEGER_VALUE; 85 colorResolution = UNDEFINED_INTEGER_VALUE; 86 pixelAspectRatio = 0; 87 88 backgroundColorIndex = 0; 89 sortFlag = false; 90 globalColorTable = null; 91 } 92 93 protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { 94 Node node = root; 95 if (!node.getNodeName().equals(nativeMetadataFormatName)) { 96 fatal(node, "Root must be " + nativeMetadataFormatName); 97 } 98 99 node = node.getFirstChild(); 100 while (node != null) { 101 String name = node.getNodeName(); 102 103 if (name.equals("Version")) { 104 version = getStringAttribute(node, "value", null, 105 true, versionStrings); 106 } else if (name.equals("LogicalScreenDescriptor")) { 107 /* NB: At the moment we use empty strings to support undefined 108 * integer values in tree representation. 109 * We need to add better support for undefined/default values 110 * later. 111 */ 112 logicalScreenWidth = getIntAttribute(node, 113 "logicalScreenWidth", 114 UNDEFINED_INTEGER_VALUE, 115 true, 116 true, 1, 65535); 117 118 logicalScreenHeight = getIntAttribute(node, 119 "logicalScreenHeight", 120 UNDEFINED_INTEGER_VALUE, 121 true, 122 true, 1, 65535); 123 124 colorResolution = getIntAttribute(node, 125 "colorResolution", 126 UNDEFINED_INTEGER_VALUE, 127 true, 128 true, 1, 8); 129 130 pixelAspectRatio = getIntAttribute(node, 131 "pixelAspectRatio", 132 0, true, 133 true, 0, 255); 134 } else if (name.equals("GlobalColorTable")) { 135 int sizeOfGlobalColorTable = 136 getIntAttribute(node, "sizeOfGlobalColorTable", 137 true, 2, 256); 138 if (sizeOfGlobalColorTable != 2 && 139 sizeOfGlobalColorTable != 4 && 140 sizeOfGlobalColorTable != 8 && 141 sizeOfGlobalColorTable != 16 && 142 sizeOfGlobalColorTable != 32 && 143 sizeOfGlobalColorTable != 64 && 144 sizeOfGlobalColorTable != 128 && 145 sizeOfGlobalColorTable != 256) { 146 fatal(node, 147 "Bad value for GlobalColorTable attribute sizeOfGlobalColorTable!"); 148 } 149 150 backgroundColorIndex = getIntAttribute(node, 151 "backgroundColorIndex", 152 0, true, 153 true, 0, 255); 154 155 sortFlag = getBooleanAttribute(node, "sortFlag", false, true); 156 157 globalColorTable = getColorTable(node, "ColorTableEntry", 158 true, sizeOfGlobalColorTable); 159 } else { 160 fatal(node, "Unknown child of root node!"); 161 } 162 163 node = node.getNextSibling(); 164 } 165 } 166 167 protected void mergeStandardTree(Node root) 168 throws IIOInvalidTreeException { 169 Node node = root; 170 if (!node.getNodeName() 171 .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { 172 fatal(node, "Root must be " + 173 IIOMetadataFormatImpl.standardMetadataFormatName); 174 } 175 176 node = node.getFirstChild(); 177 while (node != null) { 178 String name = node.getNodeName(); 179 180 if (name.equals("Chroma")) { 181 Node childNode = node.getFirstChild(); 182 while(childNode != null) { 183 String childName = childNode.getNodeName(); 184 if (childName.equals("Palette")) { 185 globalColorTable = getColorTable(childNode, 186 "PaletteEntry", 187 false, -1); 188 189 } else if (childName.equals("BackgroundIndex")) { 190 backgroundColorIndex = getIntAttribute(childNode, 191 "value", 192 -1, true, 193 true, 0, 255); 194 } 195 childNode = childNode.getNextSibling(); 196 } 197 } else if (name.equals("Data")) { 198 Node childNode = node.getFirstChild(); 199 while(childNode != null) { 200 String childName = childNode.getNodeName(); 201 if (childName.equals("BitsPerSample")) { 202 colorResolution = getIntAttribute(childNode, 203 "value", 204 -1, true, 205 true, 1, 8); 206 break; 207 } 208 childNode = childNode.getNextSibling(); 209 } 210 } else if (name.equals("Dimension")) { 211 Node childNode = node.getFirstChild(); 212 while(childNode != null) { 213 String childName = childNode.getNodeName(); 214 if (childName.equals("PixelAspectRatio")) { 215 float aspectRatio = getFloatAttribute(childNode, 216 "value"); 217 if (aspectRatio == 1.0F) { 218 pixelAspectRatio = 0; 219 } else { 220 int ratio = (int)(aspectRatio*64.0F - 15.0F); 221 pixelAspectRatio = 222 Math.max(Math.min(ratio, 255), 0); 223 } 224 } else if (childName.equals("HorizontalScreenSize")) { 225 logicalScreenWidth = getIntAttribute(childNode, 226 "value", 227 -1, true, 228 true, 1, 65535); 229 } else if (childName.equals("VerticalScreenSize")) { 230 logicalScreenHeight = getIntAttribute(childNode, 231 "value", 232 -1, true, 233 true, 1, 65535); 234 } 235 childNode = childNode.getNextSibling(); 236 } 237 } else if (name.equals("Document")) { 238 Node childNode = node.getFirstChild(); 239 while(childNode != null) { 240 String childName = childNode.getNodeName(); 241 if (childName.equals("FormatVersion")) { 242 String formatVersion = 243 getStringAttribute(childNode, "value", null, 244 true, null); 245 for (int i = 0; i < versionStrings.length; i++) { 246 if (formatVersion.equals(versionStrings[i])) { 247 version = formatVersion; 248 break; 249 } 250 } 251 break; 252 } 253 childNode = childNode.getNextSibling(); 254 } 255 } 256 257 node = node.getNextSibling(); 258 } 259 } 260 261 public void setFromTree(String formatName, Node root) 262 throws IIOInvalidTreeException 263 { 264 reset(); 265 mergeTree(formatName, root); 266 } 267} 268