Java:.gif Creator需要调整

时间:2013-12-01 22:35:27

标签: java gif

我目前正在创建一个导入图像的程序(使用Java),然后使用这些图像创建.gif文件。

我的大多数图片都有透明背景,alpha设置为0。

我目前的问题是在我将一系列8个图像转换为一个.gif后,它们相互流血。换句话说,在绘制下一帧之前,.gif不会在图像上重新绘制。因此,例如,如果苹果从树上掉落,它将看起来像红色条纹,直到.gif循环。

我认为自己对Java非常了不起,但我在搜索互联网档案时找到的脚本远远超出了我的联盟。考虑我的8本Java书籍都没有涵盖IIOMETANODE。互联网上的资源有限。所以我不确定iio的功能是什么。

这是脚本:

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();
    }
}
}

我再一次试图将.gif从出血图像中一起改变。我尝试在两者之间创建一个缓冲区BufferedImage,但这是一个失败。

1 个答案:

答案 0 :(得分:1)

基本上,您需要更改disposalMethod ...

graphicsControlExtensionNode.setAttribute("disposalMethod", "restoreToBackgroundColor");
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
graphicsControlExtensionNode.setAttribute(
    "transparentColorFlag",
    "TRUE");

假设您要添加的每个图像都是完整的图像,并且图像的优化“添加”

请查看GIF Animation and Disposal Methods以获取更多详情,如果您真的喜欢冒险,GIF specificationImage :: Java Animated GIFs (with transparant pixel disposal modes)列出了可能的处理方法,那么您可以玩一下看看有什么用......