/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
public class GIFImageMetadata extends GIFMetadata {
// package scope
static final String
nativeMetadataFormatName = "javax_imageio_gif_image_1.0";
static final String[] disposalMethodNames = {
"none",
"doNotDispose",
"restoreToBackgroundColor",
"restoreToPrevious",
"undefinedDisposalMethod4",
"undefinedDisposalMethod5",
"undefinedDisposalMethod6",
"undefinedDisposalMethod7"
};
// Fields from Image Descriptor
public int imageLeftPosition;
public int imageTopPosition;
public int imageWidth;
public int imageHeight;
public boolean interlaceFlag = false;
public boolean sortFlag = false;
public byte[] localColorTable = null;
// Fields from Graphic Control Extension
public int disposalMethod = 0;
public boolean userInputFlag = false;
public boolean transparentColorFlag = false;
public int delayTime = 0;
public int transparentColorIndex = 0;
// Fields from Plain Text Extension
public boolean hasPlainTextExtension = false;
public int textGridLeft;
public int textGridTop;
public int textGridWidth;
public int textGridHeight;
public int characterCellWidth;
public int characterCellHeight;
public int textForegroundColor;
public int textBackgroundColor;
public byte[] text;
// Fields from ApplicationExtension
// List of byte[]
public List applicationIDs = null; // new ArrayList();
// List of byte[]
public List authenticationCodes = null; // new ArrayList();
// List of byte[]
public List applicationData = null; // new ArrayList();
// Fields from CommentExtension
// List of byte[]
public List comments = null; // new ArrayList();
protected GIFImageMetadata(boolean standardMetadataFormatSupported,
String nativeMetadataFormatName,
String nativeMetadataFormatClassName,
String[] extraMetadataFormatNames,
String[] extraMetadataFormatClassNames)
{
super(standardMetadataFormatSupported,
nativeMetadataFormatName,
nativeMetadataFormatClassName,
extraMetadataFormatNames,
extraMetadataFormatClassNames);
}
public GIFImageMetadata() {
this(true,
nativeMetadataFormatName,
"com.sun.imageio.plugins.gif.GIFImageMetadataFormat",
null, null);
}
public boolean isReadOnly() {
return true;
}
public Node getAsTree(String formatName) {
if (formatName.equals(nativeMetadataFormatName)) {
return getNativeTree();
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
return getStandardTree();
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
private String toISO8859(byte[] data) {
try {
return new String(data, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
return "";
}
}
private Node getNativeTree() {
IIOMetadataNode node; // scratch node
IIOMetadataNode root =
new IIOMetadataNode(nativeMetadataFormatName);
// Image descriptor
node = new IIOMetadataNode("ImageDescriptor");
node.setAttribute("imageLeftPosition",
Integer.toString(imageLeftPosition));
node.setAttribute("imageTopPosition",
Integer.toString(imageTopPosition));
node.setAttribute("imageWidth", Integer.toString(imageWidth));
node.setAttribute("imageHeight", Integer.toString(imageHeight));
node.setAttribute("interlaceFlag",
interlaceFlag ? "TRUE" : "FALSE");
root.appendChild(node);
// Local color table
if (localColorTable != null) {
node = new IIOMetadataNode("LocalColorTable");
int numEntries = localColorTable.length/3;
node.setAttribute("sizeOfLocalColorTable",
Integer.toString(numEntries));
node.setAttribute("sortFlag",
sortFlag ? "TRUE" : "FALSE");
for (int i = 0; i < numEntries; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("ColorTableEntry");
entry.setAttribute("index", Integer.toString(i));
int r = localColorTable[3*i] & 0xff;
int g = localColorTable[3*i + 1] & 0xff;
int b = localColorTable[3*i + 2] & 0xff;
entry.setAttribute("red", Integer.toString(r));
entry.setAttribute("green", Integer.toString(g));
entry.setAttribute("blue", Integer.toString(b));
node.appendChild(entry);
}
root.appendChild(node);
}
// Graphic control extension
node = new IIOMetadataNode("GraphicControlExtension");
node.setAttribute("disposalMethod",
disposalMethodNames[disposalMethod]);
node.setAttribute("userInputFlag",
userInputFlag ? "TRUE" : "FALSE");
node.setAttribute("transparentColorFlag",
transparentColorFlag ? "TRUE" : "FALSE");
node.setAttribute("delayTime",
Integer.toString(delayTime));
node.setAttribute("transparentColorIndex",
Integer.toString(transparentColorIndex));
root.appendChild(node);
if (hasPlainTextExtension) {
node = new IIOMetadataNode("PlainTextExtension");
node.setAttribute("textGridLeft",
Integer.toString(textGridLeft));
node.setAttribute("textGridTop",
Integer.toString(textGridTop));
node.setAttribute("textGridWidth",
Integer.toString(textGridWidth));
node.setAttribute("textGridHeight",
Integer.toString(textGridHeight));
node.setAttribute("characterCellWidth",
Integer.toString(characterCellWidth));
node.setAttribute("characterCellHeight",
Integer.toString(characterCellHeight));
node.setAttribute("textForegroundColor",
Integer.toString(textForegroundColor));
node.setAttribute("textBackgroundColor",
Integer.toString(textBackgroundColor));
node.setAttribute("text", toISO8859(text));
root.appendChild(node);
}
// Application extensions
int numAppExtensions = applicationIDs == null ?
0 : applicationIDs.size();
if (numAppExtensions > 0) {
node = new IIOMetadataNode("ApplicationExtensions");
for (int i = 0; i < numAppExtensions; i++) {
IIOMetadataNode appExtNode =
new IIOMetadataNode("ApplicationExtension");
byte[] applicationID = (byte[])applicationIDs.get(i);
appExtNode.setAttribute("applicationID",
toISO8859(applicationID));
byte[] authenticationCode = (byte[])authenticationCodes.get(i);
appExtNode.setAttribute("authenticationCode",
toISO8859(authenticationCode));
byte[] appData = (byte[])applicationData.get(i);
appExtNode.setUserObject((byte[])appData.clone());
node.appendChild(appExtNode);
}
root.appendChild(node);
}
// Comment extensions
int numComments = comments == null ? 0 : comments.size();
if (numComments > 0) {
node = new IIOMetadataNode("CommentExtensions");
for (int i = 0; i < numComments; i++) {
IIOMetadataNode commentNode =
new IIOMetadataNode("CommentExtension");
byte[] comment = (byte[])comments.get(i);
commentNode.setAttribute("value", toISO8859(comment));
node.appendChild(commentNode);
}
root.appendChild(node);
}
return root;
}
public IIOMetadataNode getStandardChromaNode() {
IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("ColorSpaceType");
node.setAttribute("name", "RGB");
chroma_node.appendChild(node);
node = new IIOMetadataNode("NumChannels");
node.setAttribute("value", transparentColorFlag ? "4" : "3");
chroma_node.appendChild(node);
// Gamma not in format
node = new IIOMetadataNode("BlackIsZero");
node.setAttribute("value", "TRUE");
chroma_node.appendChild(node);
if (localColorTable != null) {
node = new IIOMetadataNode("Palette");
int numEntries = localColorTable.length/3;
for (int i = 0; i < numEntries; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("PaletteEntry");
entry.setAttribute("index", Integer.toString(i));
entry.setAttribute("red",
Integer.toString(localColorTable[3*i] & 0xff));
entry.setAttribute("green",
Integer.toString(localColorTable[3*i + 1] & 0xff));
entry.setAttribute("blue",
Integer.toString(localColorTable[3*i + 2] & 0xff));
node.appendChild(entry);
}
chroma_node.appendChild(node);
}
// BackgroundIndex not in image
// BackgroundColor not in format
return chroma_node;
}
public IIOMetadataNode getStandardCompressionNode() {
IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("CompressionTypeName");
node.setAttribute("value", "lzw");
compression_node.appendChild(node);
node = new IIOMetadataNode("Lossless");
node.setAttribute("value", "TRUE");
compression_node.appendChild(node);
node = new IIOMetadataNode("NumProgressiveScans");
node.setAttribute("value", interlaceFlag ? "4" : "1");
compression_node.appendChild(node);
// BitRate not in format
return compression_node;
}
public IIOMetadataNode getStandardDataNode() {
IIOMetadataNode data_node = new IIOMetadataNode("Data");
IIOMetadataNode node = null; // scratch node
// PlanarConfiguration not in format
node = new IIOMetadataNode("SampleFormat");
node.setAttribute("value", "Index");
data_node.appendChild(node);
// BitsPerSample not in image
// SignificantBitsPerSample not in format
// SampleMSB not in format
return data_node;
}
public IIOMetadataNode getStandardDimensionNode() {
IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
IIOMetadataNode node = null; // scratch node
// PixelAspectRatio not in image
node = new IIOMetadataNode("ImageOrientation");
node.setAttribute("value", "Normal");
dimension_node.appendChild(node);
// HorizontalPixelSize not in format
// VerticalPixelSize not in format
// HorizontalPhysicalPixelSpacing not in format
// VerticalPhysicalPixelSpacing not in format
// HorizontalPosition not in format
// VerticalPosition not in format
node = new IIOMetadataNode("HorizontalPixelOffset");
node.setAttribute("value", Integer.toString(imageLeftPosition));
dimension_node.appendChild(node);
node = new IIOMetadataNode("VerticalPixelOffset");
node.setAttribute("value", Integer.toString(imageTopPosition));
dimension_node.appendChild(node);
// HorizontalScreenSize not in image
// VerticalScreenSize not in image
return dimension_node;
}
// Document not in image
public IIOMetadataNode getStandardTextNode() {
if (comments == null) {
return null;
}
Iterator commentIter = comments.iterator();
if (!commentIter.hasNext()) {
return null;
}
IIOMetadataNode text_node = new IIOMetadataNode("Text");
IIOMetadataNode node = null; // scratch node
while (commentIter.hasNext()) {
byte[] comment = (byte[])commentIter.next();
String s = null;
try {
s = new String(comment, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Encoding ISO-8859-1 unknown!");
}
node = new IIOMetadataNode("TextEntry");
node.setAttribute("value", s);
node.setAttribute("encoding", "ISO-8859-1");
node.setAttribute("compression", "none");
text_node.appendChild(node);
}
return text_node;
}
public IIOMetadataNode getStandardTransparencyNode() {
if (!transparentColorFlag) {
return null;
}
IIOMetadataNode transparency_node =
new IIOMetadataNode("Transparency");
IIOMetadataNode node = null; // scratch node
// Alpha not in format
node = new IIOMetadataNode("TransparentIndex");
node.setAttribute("value",
Integer.toString(transparentColorIndex));
transparency_node.appendChild(node);
// TransparentColor not in format
// TileTransparencies not in format
// TileOpacities not in format
return transparency_node;
}
public void setFromTree(String formatName, Node root)
throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
protected void mergeNativeTree(Node root) throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
protected void mergeStandardTree(Node root) throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
public void reset() {
throw new IllegalStateException("Metadata is read-only!");
}
}