【问题标题】:Read delay between frames in animated GIF动画 GIF 中帧之间的读取延迟
【发布时间】:2013-11-20 02:22:28
【问题描述】:

您如何读取动画 GIF 的每一帧之间的控制块?我对每帧之间的延迟感兴趣。我查看了 ImageReader 的 Javadoc,但什么也没看到。

这是我从动画 GIF 中读取所有帧的代码,我将如何增强它以读取有关嵌入在动画 GIF 中的每个帧的元数据?

    List<BufferedImage> list = new ArrayList<BufferedImage>();
    try {
        ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
        reader.setInput(ImageIO.createImageInputStream(urlImage.openStream()));
        int i = reader.getMinIndex();
        int numImages = reader.getNumImages(true);
        while (i < numImages)
        {
            list.add(reader.read(i++));
        }

        // do stuff with frames of image...

    } catch (Exception e) {
        e.printStackTrace();
    }

【问题讨论】:

    标签: java image image-processing metadata animated-gif


    【解决方案1】:

    您必须从元数据节点中寻找"delayTime" 属性。使用以下工作示例来理解:

    public class GiffTest {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) throws IOException {
            ImageReader reader = ImageIO.getImageReadersBySuffix("gif").next();
            reader.setInput(ImageIO.createImageInputStream(new FileInputStream("H:\\toonGif.gif")));
            int i = reader.getMinIndex();
            int numImages = reader.getNumImages(true);
    
            IIOMetadata imageMetaData =  reader.getImageMetadata(0);
            String metaFormatName = imageMetaData.getNativeMetadataFormatName();
    
        IIOMetadataNode root = (IIOMetadataNode)imageMetaData.getAsTree(metaFormatName);
    
        IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
    
            System.out.println(graphicsControlExtensionNode.getAttribute("delayTime"));
        }
    
        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);
      }
    }
    

    【讨论】:

    • 谢谢!这些值是以毫秒为单位的吗?我添加了循环以获取帧的所有延迟时间值。它们比我预期的要小得多——如果我尝试在 Java 中使用这些值(以毫秒为单位)来制作动画,它的运行速度太快了。将这些值乘以 10 可以很好地近似于我期望它的运行方式。
    • 看起来实际上是百分之一秒。来自动画 GIF wiki:许多渲染程序将图块或图层解释为动画帧,并将它们按顺序显示为无尽的动画 [11],大多数网络浏览器会以 0.1 秒的延迟时间自动显示帧。
    • Wiki 对此似乎很清楚:“每一帧的动画延迟在 GCE 中以百分之一秒为单位指定。” en.wikipedia.org/wiki/Graphics_Interchange_Format
    • 从哪里可以找到“ImageIO,IIOMetadata,IIOMetadataNode”类?
    • @Naitik,请查看文档页面。它们是javax.imageio 包的一部分。即:ImageIO
    猜你喜欢
    • 1970-01-01
    • 2012-02-08
    • 2016-03-11
    • 1970-01-01
    • 2017-01-27
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多