【问题标题】:Java: .gif Creator Needs TweakingJava:.gif 创建者需要调整
【发布时间】:2018-12-28 11:43:49
【问题描述】:

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

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

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

我认为自己对 Java 非常了解,但是我在搜索 Internet 档案时发现的脚本却超出了我的范围。考虑一下我的 8 本书中没有一本涵盖 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,但失败了。

【问题讨论】:

  • 看看this answer的后半部分
  • 我对为什么这个应用程序试图伪装成 netscape 浏览器很感兴趣...

标签: java gif


【解决方案1】:

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

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

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

查看GIF Animation and Disposal Methods 了解更多详细信息,如果您真的很喜欢冒险,GIF specification 和Image :: Java Animated GIFs (with transparant pixel disposal modes) 列出了可能的处理方法,因此您可以试一试,看看哪些方法有效。 .

【讨论】:

  • 哇!就是这样!非常感谢!!
猜你喜欢
  • 2011-01-13
  • 2011-10-19
  • 2010-11-01
  • 2012-01-13
  • 2022-11-27
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
相关资源
最近更新 更多