I currently am creating a program (with Java) that imports images and then creates a .gif with these images.
Most of my images have a transparent background with the alpha set at 0.
My current problem is after I have a series of 8 images converted to one .gif they bleed over each other. In other words the .gif does not repaint over the image before painting the next frame. So for example, if there is an apple fall from the tree, it will look like a red streak until the .gif loops.
I consider myself to be getting pretty savvy with Java but the script I found while searching the archives of the internet is way out of my league. Consider none of my 8 Java books cover IIOMETANODE. And resources on the internet are limited. So I'm not sure what the capabilities of iio are.
Here is the script:
import javax.imageio.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.awt.image.*;
import java.io.*;
import java.util.Iterator;
public class GifCreator {
private ImageWriter gifWriter;
private ImageWriteParam imageWriteParam;
private IIOMetadata imageMetaData;
public GifCreator(){}
/**
* Creates a new GifSequenceWriter
*
* @param output the ImageOutputStream to be written to
* @param imgType one of the imageTypes specified in BufferedImage
* @param frameTime the time between frames in miliseconds
* @param loop wether the gif should loop repeatedly
* @throws IIOException if no gif ImageWriters are found
*
*/
public GifCreator(ImageOutputStream output, int imgType, int frameTime, boolean loop)
{
try {
gifWriter = getWriter();
imageWriteParam = gifWriter.getDefaultWriteParam();
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imgType);
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);
String metaFormatName = imageMetaData.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);
IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(frameTime / 10));
graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");
IIOMetadataNode appEntensionsNode = getNode(root, "ApplicationExtensions");
IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
child.setAttribute("applicationID", "NETSCAPE");
child.setAttribute("authenticationCode", "2.0");
int aLoop = loop ? 0 : 1;
child.setUserObject(new byte[]{ 0x1, (byte) (aLoop & 0xFF), (byte) ((aLoop >> 8) & 0xFF)});
appEntensionsNode.appendChild(child);
imageMetaData.setFromTree(metaFormatName, root);
gifWriter.setOutput(output);
gifWriter.prepareWriteSequence(null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void writeToSequence(RenderedImage img) throws IOException
{
gifWriter.writeToSequence(new IIOImage(img, null, imageMetaData), imageWriteParam);
}
/**
* Close this GifSequenceWriter object. This does not close the underlying
* stream, just finishes off the GIF.
*/
public void close() throws IOException
{
gifWriter.endWriteSequence();
}
/**
* Returns the first available GIF ImageWriter using
* ImageIO.getImageWritersBySuffix("gif").
*
* @return a GIF ImageWriter object
* @throws IIOException if no GIF image writers are returned
*/
private static ImageWriter getWriter() throws IIOException
{
Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
if (!iter.hasNext()) {
throw new IIOException("No GIF Image Writers Exist");
} else {
return iter.next();
}
}
/**
* Returns an existing child node, or creates and returns a new child node (if
* the requested node does not exist).
*
* @param rootNode the <tt>IIOMetadataNode</tt> to search for the child node.
* @param nodeName the name of the child node.
*
* @return the child node, if found or a new node created with the given name.
*/
private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName)
{
int nNodes = rootNode.getLength();
for (int i = 0; i < nNodes; i++) {
if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0)
return((IIOMetadataNode) rootNode.item(i));
}
IIOMetadataNode node = new IIOMetadataNode(nodeName);
rootNode.appendChild(node);
return(node);
}
public GifCreator(BufferedImage[] imgs, String path)
{
if (imgs.length <= 1)
return;
// Grabs the first BufferedImage from the array.
BufferedImage first = imgs[0];
try {
// Creates a new BufferedOutputStream with the incoming path.
ImageOutputStream output = new FileImageOutputStream(new File(path));
// Creates a gif sequence with the type of the first image, .1 second
// between frames, which loops continuously
GifCreator writer = new GifCreator(output, first.getType(), 100, true);
// write out the first image to our sequence...
writer.writeToSequence((RenderedImage) first);
for (int i = 1; i < imgs.length; i++) {
BufferedImage next = imgs[i];
writer.writeToSequence(next);
}
writer.close();
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Once again I'm trying to change the .gif from bleeding images together. I attempted to create a buffer BufferedImage in between but that was a failure.