0N/A/*
2362N/A * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.imageio.plugins.gif;
0N/A
0N/Aimport java.io.UnsupportedEncodingException;
0N/Aimport java.nio.charset.Charset;
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.Iterator;
0N/Aimport java.util.List;
0N/Aimport javax.imageio.ImageTypeSpecifier;
0N/Aimport javax.imageio.metadata.IIOInvalidTreeException;
0N/Aimport javax.imageio.metadata.IIOMetadata;
0N/Aimport javax.imageio.metadata.IIOMetadataNode;
0N/Aimport javax.imageio.metadata.IIOMetadataFormat;
0N/Aimport javax.imageio.metadata.IIOMetadataFormatImpl;
0N/Aimport org.w3c.dom.Node;
0N/A
0N/Aclass GIFWritableImageMetadata extends GIFImageMetadata {
0N/A
0N/A // package scope
0N/A static final String
0N/A NATIVE_FORMAT_NAME = "javax_imageio_gif_image_1.0";
0N/A
0N/A GIFWritableImageMetadata() {
0N/A super(true,
0N/A NATIVE_FORMAT_NAME,
0N/A "com.sun.imageio.plugins.gif.GIFImageMetadataFormat",
0N/A null, null);
0N/A }
0N/A
0N/A public boolean isReadOnly() {
0N/A return false;
0N/A }
0N/A
0N/A public void reset() {
0N/A // Fields from Image Descriptor
0N/A imageLeftPosition = 0;
0N/A imageTopPosition = 0;
0N/A imageWidth = 0;
0N/A imageHeight = 0;
0N/A interlaceFlag = false;
0N/A sortFlag = false;
0N/A localColorTable = null;
0N/A
0N/A // Fields from Graphic Control Extension
0N/A disposalMethod = 0;
0N/A userInputFlag = false;
0N/A transparentColorFlag = false;
0N/A delayTime = 0;
0N/A transparentColorIndex = 0;
0N/A
0N/A // Fields from Plain Text Extension
0N/A hasPlainTextExtension = false;
0N/A textGridLeft = 0;
0N/A textGridTop = 0;
0N/A textGridWidth = 0;
0N/A textGridHeight = 0;
0N/A characterCellWidth = 0;
0N/A characterCellHeight = 0;
0N/A textForegroundColor = 0;
0N/A textBackgroundColor = 0;
0N/A text = null;
0N/A
0N/A // Fields from ApplicationExtension
0N/A applicationIDs = null;
0N/A authenticationCodes = null;
0N/A applicationData = null;
0N/A
0N/A // Fields from CommentExtension
0N/A // List of byte[]
0N/A comments = null;
0N/A }
0N/A
0N/A private byte[] fromISO8859(String data) {
0N/A try {
0N/A return data.getBytes("ISO-8859-1");
0N/A } catch (UnsupportedEncodingException e) {
215N/A return "".getBytes();
0N/A }
0N/A }
0N/A
0N/A protected void mergeNativeTree(Node root) throws IIOInvalidTreeException {
0N/A Node node = root;
0N/A if (!node.getNodeName().equals(nativeMetadataFormatName)) {
0N/A fatal(node, "Root must be " + nativeMetadataFormatName);
0N/A }
0N/A
0N/A node = node.getFirstChild();
0N/A while (node != null) {
0N/A String name = node.getNodeName();
0N/A
0N/A if (name.equals("ImageDescriptor")) {
0N/A imageLeftPosition = getIntAttribute(node,
0N/A "imageLeftPosition",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A
0N/A imageTopPosition = getIntAttribute(node,
0N/A "imageTopPosition",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A
0N/A imageWidth = getIntAttribute(node,
0N/A "imageWidth",
0N/A -1, true,
0N/A true, 1, 65535);
0N/A
0N/A imageHeight = getIntAttribute(node,
0N/A "imageHeight",
0N/A -1, true,
0N/A true, 1, 65535);
0N/A
0N/A interlaceFlag = getBooleanAttribute(node, "interlaceFlag",
0N/A false, true);
0N/A } else if (name.equals("LocalColorTable")) {
0N/A int sizeOfLocalColorTable =
0N/A getIntAttribute(node, "sizeOfLocalColorTable",
0N/A true, 2, 256);
0N/A if (sizeOfLocalColorTable != 2 &&
0N/A sizeOfLocalColorTable != 4 &&
0N/A sizeOfLocalColorTable != 8 &&
0N/A sizeOfLocalColorTable != 16 &&
0N/A sizeOfLocalColorTable != 32 &&
0N/A sizeOfLocalColorTable != 64 &&
0N/A sizeOfLocalColorTable != 128 &&
0N/A sizeOfLocalColorTable != 256) {
0N/A fatal(node,
0N/A "Bad value for LocalColorTable attribute sizeOfLocalColorTable!");
0N/A }
0N/A
0N/A sortFlag = getBooleanAttribute(node, "sortFlag", false, true);
0N/A
0N/A localColorTable = getColorTable(node, "ColorTableEntry",
0N/A true, sizeOfLocalColorTable);
0N/A } else if (name.equals("GraphicControlExtension")) {
0N/A String disposalMethodName =
0N/A getStringAttribute(node, "disposalMethod", null,
0N/A true, disposalMethodNames);
0N/A disposalMethod = 0;
0N/A while(!disposalMethodName.equals(disposalMethodNames[disposalMethod])) {
0N/A disposalMethod++;
0N/A }
0N/A
0N/A userInputFlag = getBooleanAttribute(node, "userInputFlag",
0N/A false, true);
0N/A
0N/A transparentColorFlag =
0N/A getBooleanAttribute(node, "transparentColorFlag",
0N/A false, true);
0N/A
0N/A delayTime = getIntAttribute(node,
0N/A "delayTime",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A
0N/A transparentColorIndex =
0N/A getIntAttribute(node, "transparentColorIndex",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A } else if (name.equals("PlainTextExtension")) {
0N/A hasPlainTextExtension = true;
0N/A
0N/A textGridLeft = getIntAttribute(node,
0N/A "textGridLeft",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A
0N/A textGridTop = getIntAttribute(node,
0N/A "textGridTop",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A
0N/A textGridWidth = getIntAttribute(node,
0N/A "textGridWidth",
0N/A -1, true,
0N/A true, 1, 65535);
0N/A
0N/A textGridHeight = getIntAttribute(node,
0N/A "textGridHeight",
0N/A -1, true,
0N/A true, 1, 65535);
0N/A
0N/A characterCellWidth = getIntAttribute(node,
0N/A "characterCellWidth",
0N/A -1, true,
0N/A true, 1, 65535);
0N/A
0N/A characterCellHeight = getIntAttribute(node,
0N/A "characterCellHeight",
0N/A -1, true,
0N/A true, 1, 65535);
0N/A
0N/A textForegroundColor = getIntAttribute(node,
0N/A "textForegroundColor",
0N/A -1, true,
0N/A true, 0, 255);
0N/A
0N/A textBackgroundColor = getIntAttribute(node,
0N/A "textBackgroundColor",
0N/A -1, true,
0N/A true, 0, 255);
0N/A
0N/A // XXX The "text" attribute of the PlainTextExtension element
0N/A // is not defined in the GIF image metadata format but it is
0N/A // present in the GIFImageMetadata class. Consequently it is
0N/A // used here but not required and with a default of "". See
0N/A // bug 5082763.
0N/A
0N/A String textString =
0N/A getStringAttribute(node, "text", "", false, null);
0N/A text = fromISO8859(textString);
0N/A } else if (name.equals("ApplicationExtensions")) {
0N/A IIOMetadataNode applicationExtension =
0N/A (IIOMetadataNode)node.getFirstChild();
0N/A
0N/A if (!applicationExtension.getNodeName().equals("ApplicationExtension")) {
0N/A fatal(node,
0N/A "Only a ApplicationExtension may be a child of a ApplicationExtensions!");
0N/A }
0N/A
0N/A String applicationIDString =
0N/A getStringAttribute(applicationExtension, "applicationID",
0N/A null, true, null);
0N/A
0N/A String authenticationCodeString =
0N/A getStringAttribute(applicationExtension, "authenticationCode",
0N/A null, true, null);
0N/A
0N/A Object applicationExtensionData =
0N/A applicationExtension.getUserObject();
0N/A if (applicationExtensionData == null ||
0N/A !(applicationExtensionData instanceof byte[])) {
0N/A fatal(applicationExtension,
0N/A "Bad user object in ApplicationExtension!");
0N/A }
0N/A
0N/A if (applicationIDs == null) {
0N/A applicationIDs = new ArrayList();
0N/A authenticationCodes = new ArrayList();
0N/A applicationData = new ArrayList();
0N/A }
0N/A
0N/A applicationIDs.add(fromISO8859(applicationIDString));
0N/A authenticationCodes.add(fromISO8859(authenticationCodeString));
0N/A applicationData.add(applicationExtensionData);
0N/A } else if (name.equals("CommentExtensions")) {
0N/A Node commentExtension = node.getFirstChild();
0N/A if (commentExtension != null) {
0N/A while(commentExtension != null) {
0N/A if (!commentExtension.getNodeName().equals("CommentExtension")) {
0N/A fatal(node,
0N/A "Only a CommentExtension may be a child of a CommentExtensions!");
0N/A }
0N/A
0N/A if (comments == null) {
0N/A comments = new ArrayList();
0N/A }
0N/A
0N/A String comment =
0N/A getStringAttribute(commentExtension, "value", null,
0N/A true, null);
0N/A
0N/A comments.add(fromISO8859(comment));
0N/A
0N/A commentExtension = commentExtension.getNextSibling();
0N/A }
0N/A }
0N/A } else {
0N/A fatal(node, "Unknown child of root node!");
0N/A }
0N/A
0N/A node = node.getNextSibling();
0N/A }
0N/A }
0N/A
0N/A protected void mergeStandardTree(Node root)
0N/A throws IIOInvalidTreeException {
0N/A Node node = root;
0N/A if (!node.getNodeName()
0N/A .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
0N/A fatal(node, "Root must be " +
0N/A IIOMetadataFormatImpl.standardMetadataFormatName);
0N/A }
0N/A
0N/A node = node.getFirstChild();
0N/A while (node != null) {
0N/A String name = node.getNodeName();
0N/A
0N/A if (name.equals("Chroma")) {
0N/A Node childNode = node.getFirstChild();
0N/A while(childNode != null) {
0N/A String childName = childNode.getNodeName();
0N/A if (childName.equals("Palette")) {
0N/A localColorTable = getColorTable(childNode,
0N/A "PaletteEntry",
0N/A false, -1);
0N/A break;
0N/A }
0N/A childNode = childNode.getNextSibling();
0N/A }
0N/A } else if (name.equals("Compression")) {
0N/A Node childNode = node.getFirstChild();
0N/A while(childNode != null) {
0N/A String childName = childNode.getNodeName();
0N/A if (childName.equals("NumProgressiveScans")) {
0N/A int numProgressiveScans =
0N/A getIntAttribute(childNode, "value", 4, false,
0N/A true, 1, Integer.MAX_VALUE);
0N/A if (numProgressiveScans > 1) {
0N/A interlaceFlag = true;
0N/A }
0N/A break;
0N/A }
0N/A childNode = childNode.getNextSibling();
0N/A }
0N/A } else if (name.equals("Dimension")) {
0N/A Node childNode = node.getFirstChild();
0N/A while(childNode != null) {
0N/A String childName = childNode.getNodeName();
0N/A if (childName.equals("HorizontalPixelOffset")) {
0N/A imageLeftPosition = getIntAttribute(childNode,
0N/A "value",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A } else if (childName.equals("VerticalPixelOffset")) {
0N/A imageTopPosition = getIntAttribute(childNode,
0N/A "value",
0N/A -1, true,
0N/A true, 0, 65535);
0N/A }
0N/A childNode = childNode.getNextSibling();
0N/A }
0N/A } else if (name.equals("Text")) {
0N/A Node childNode = node.getFirstChild();
0N/A while(childNode != null) {
0N/A String childName = childNode.getNodeName();
0N/A if (childName.equals("TextEntry") &&
0N/A getAttribute(childNode, "compression",
0N/A "none", false).equals("none") &&
0N/A Charset.isSupported(getAttribute(childNode,
0N/A "encoding",
0N/A "ISO-8859-1",
0N/A false))) {
0N/A String value = getAttribute(childNode, "value");
0N/A byte[] comment = fromISO8859(value);
0N/A if (comments == null) {
0N/A comments = new ArrayList();
0N/A }
0N/A comments.add(comment);
0N/A }
0N/A childNode = childNode.getNextSibling();
0N/A }
0N/A } else if (name.equals("Transparency")) {
0N/A Node childNode = node.getFirstChild();
0N/A while(childNode != null) {
0N/A String childName = childNode.getNodeName();
0N/A if (childName.equals("TransparentIndex")) {
0N/A transparentColorIndex = getIntAttribute(childNode,
0N/A "value",
0N/A -1, true,
0N/A true, 0, 255);
0N/A transparentColorFlag = true;
0N/A break;
0N/A }
0N/A childNode = childNode.getNextSibling();
0N/A }
0N/A }
0N/A
0N/A node = node.getNextSibling();
0N/A }
0N/A }
0N/A
0N/A public void setFromTree(String formatName, Node root)
0N/A throws IIOInvalidTreeException
0N/A {
0N/A reset();
0N/A mergeTree(formatName, root);
0N/A }
0N/A}