/*
* Copyright (C) 2014 James Lawrence.
*
* This file is part of GrimEdi.
*
* GrimEdi is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sqrt4.grimedi.util;
import org.w3c.dom.Node;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.util.Iterator;
/**
* Created by James on 28/09/2014.
*/
public class AnimatedGifCreator {
private static final ImageWriter gifEncoder;
private static final ImageWriteParam defaultParams;
private final ImageOutputStream dest;
private final IIOMetadata metadata;
public AnimatedGifCreator(ImageOutputStream dest, int imageType, float fps, boolean loop, int loopCount) throws IOException {
this.dest = dest;
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
metadata = gifEncoder.getDefaultImageMetadata(imageTypeSpecifier, defaultParams);
String metaFormatName = metadata.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(metaFormatName);
IIOMetadataNode gcen = findNode(root, "GraphicControlExtension");
gcen.setAttribute("disposalMethod", "none");
gcen.setAttribute("userInputFlag", "FALSE");
gcen.setAttribute("transparentColorFlag", "FALSE");
gcen.setAttribute("delayTime", Integer.toString((int) (100f / fps)));
gcen.setAttribute("transparentColorIndex", "0");
IIOMetadataNode aepn = findNode(root, "ApplicationExtensions");
IIOMetadataNode aen = new IIOMetadataNode("ApplicationExtension");
aen.setAttribute("applicationID", "NETSCAPE");
aen.setAttribute("authenticationCode", "2.0");
int l = loop ? loopCount : 1;
aen.setUserObject(new byte[]{0x1, (byte) (l & 0xff), (byte) ((l >> 8) & 0xff)});
aepn.appendChild(aen);
metadata.setFromTree(metaFormatName, root);
gifEncoder.setOutput(dest);
gifEncoder.prepareWriteSequence(null);
}
public void addFrame(RenderedImage i) throws IOException {
gifEncoder.writeToSequence(new IIOImage(i, null, metadata), defaultParams);
}
public void finish() throws IOException {
gifEncoder.endWriteSequence();
gifEncoder.setOutput(null);
}
private static IIOMetadataNode findNode(IIOMetadataNode parent, String name) {
for(Node n = parent.getFirstChild(); n != null; n = n.getNextSibling()) {
if(n.getNodeName().equalsIgnoreCase(name))
return (IIOMetadataNode) n;
}
IIOMetadataNode node = new IIOMetadataNode(name);
parent.appendChild(node);
return node;
}
static {
Iterator<ImageWriter> writers = ImageIO.getImageWritersBySuffix("gif");
if (!writers.hasNext())
throw new RuntimeException("GIF encoding not available");
gifEncoder = writers.next();
defaultParams = gifEncoder.getDefaultWriteParam();
}
}