com.day.imageio.plugins.GIFStreamMetadata Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.day.imageio.plugins;
import javax.imageio.metadata.IIOMetadata;
import org.w3c.dom.Node;
/**
* The GIFStreamMetadataExt
class extends the
* GIFStreamMetadata
class to add fields and support for animated
* GIF image files. Namely this is the application extension support to define
* image loops. An instance of this class is returned by the
* {@link com.day.imageio.plugins.GifImageWriter#getDefaultStreamMetadata(javax.imageio.ImageWriteParam)}
* method.
*
* This class does not currently contain XML format support for this application
* extension block.
*
* For more details, look at the
* GIF89 Specification.
* Generally this page
* contains many interesting information on animated GIFs.
*
* @version $Revision: 34047 $
* @author fmeschbe
* @since coati
* @audience core
*/
public class GIFStreamMetadata extends IIOMetadata {
public static final String[] versionStrings = { "87a", "89a" };
public String version; // 87a or 89a
public int logicalScreenWidth;
public int logicalScreenHeight;
public int colorResolution; // 1 to 8
public int pixelAspectRatio;
public int backgroundColorIndex; // Valid if globalColorTable != null
public boolean sortFlag; // Valid if globalColorTable != null
public static final String[] colorTableSizes = { "2", "4", "8", "16", "32",
"64", "128", "256" };
// Set global color table flag in header to 0 if null, 1 otherwise
public byte[] globalColorTable = null;
/** The application extension blocks, null
to nott add any */
public ApplicationExtension[] extensions = null;
/** The index of the loop application extenion in the list */
private int loopAE = -1;
public GIFStreamMetadata() {
super(false, null, null, null, null);
}
public boolean isReadOnly() {
return true;
}
public Node getAsTree(String formatName) {
throw new IllegalArgumentException("Not a recognized format!");
}
public void setFromTree(String formatName, Node root) {
throw new IllegalStateException("Metadata is read-only!");
}
public void mergeTree(String formatName, Node root) {
throw new IllegalStateException("Metadata is read-only!");
}
public void reset() {
throw new IllegalStateException("Metadata is read-only!");
}
// --- Extensions for animated GIF
/**
* Sets the number of loops, the GIF image animation representated by the
* metadata should use. This method may be called multiple times, where
* later calls overwrite earlier settings.
*
* @param loops The number of loops to set as an unsigned 16bit value. If
* specified as 0, the loop application block is removed.
*/
public final void setLoops(int loops) {
// remove loops ?
if (loops < 0) {
removeLoops();
}
// Have we already set once ?
if (loopAE < 0) {
// prepare for the addition of the extension
if (extensions == null) {
extensions = new ApplicationExtension[1];
} else {
ApplicationExtension[] tmp = new ApplicationExtension[extensions.length + 1];
System.arraycopy(extensions, 0, tmp, 0, extensions.length);
}
// index of the loop application extension block
loopAE = extensions.length - 1;
// populate base settings of the loop application extension
extensions[loopAE] = new ApplicationExtension();
extensions[loopAE].identifier = "NETSCAPE".getBytes();
extensions[loopAE].authCode = "2.0".getBytes();
extensions[loopAE].subBlocks = new byte[1][3];
extensions[loopAE].subBlocks[0][0] = (byte) 0x01;
}
// set the number of loops
extensions[loopAE].subBlocks[0][1] = (byte) (loops & 0xff);
extensions[loopAE].subBlocks[0][2] = (byte) ((loops >> 8) & 0xff);
}
/**
* Removes the loop application extension block from the meta data, if at
* all contained.
*/
public void removeLoops() {
// have an application extension ?
if (loopAE >= 0) {
// is it the only one
if (extensions.length == 1) {
// remove alltogether if it is the only one
extensions = null;
} else {
// remove only the loop extension
ApplicationExtension[] tmp = new ApplicationExtension[extensions.length - 1];
for (int i = 0, j = 0; j < tmp.length;) {
if (i == loopAE) {
i++;
continue;
}
tmp[j++] = extensions[i++];
}
}
loopAE = -1;
}
}
// ---------- internal class -----------------------------------------------
/**
* The ApplicationExtension
class provides structured access
* GIF image application extensions.
*/
public final class ApplicationExtension {
/** Identifier of the application extension block - max. 8 bytes */
byte[] identifier;
/** Authentication code - max. 3 bytes */
byte[] authCode;
/**
* Application data in GIF subblock format - list of byte array
* subblocks - no length limit
*/
byte[][] subBlocks;
}
}