【问题标题】:Java gif frame to BufferedImage without holding all of them as an arrayJava gif 帧到 BufferedImage,而不将它们全部保存为数组
【发布时间】:2015-05-29 17:44:52
【问题描述】:

所以我尝试了很多次,但我就是无法让它工作。我有一个程序可以将动画 GIF 转换为具有一系列可配置设置的 PNG 序列。

问题是,我能找到能够将 GIF 帧读取为 BufferedImages 并重用 ImageReader 的唯一方法涉及创建一个数组或某种类型的列表来存储所有帧。这非常方便,但是对于长的高分辨率文件,这会占用大量内存。理想情况下,我想一次阅读它们,并在完成框架后将它们处理掉。我曾尝试研究压缩 GIF 的工作原理,但事实证明处理的工作方式有点超出我的想象。我尝试过但惨遭失败的两种基本方法是

public BufferedImage getNextFrame() 

返回未压缩的完整下一帧,并且

public void reset()

将索引重置为 0。我意识到如果不将每个帧都存储为数组或列表的索引,就不可能有效地跳转到任意帧。

当我打算对帧做更多而不是简单地显示它们时,有人可以给我一些关于如何以资源有效的方式管理 GIF 的指示吗?我不是要你写完整的东西,只是让我知道如何做到这一点。

【问题讨论】:

  • “理想情况下,我希望一次阅读一本,并在完成框架后将其丢弃。”为什么这是个问题?我认为这就像删除对BufferedImage 的引用一样简单(即分配它null)。 (注意:这可能并不那么容易,但我只是不清楚为什么不这样做。如果您澄清并在问题中添加更多细节会有所帮助。:-))
  • 压缩 GIF 使用前一帧的信息来制作下一帧的图像。我正在努力寻找一种方法来跟踪我需要哪些过去的帧,而且我真的不习惯像这样直接处理文件。我根据this question 的第三个答案构建了我的原始课程。我尝试将 for 循环中的部分退出并将其变成一个方法(显然进行了一些结构更改),但它并不顺利。

标签: java gif bufferedimage animated-gif


【解决方案1】:

我自己想不通,但我确实找到了this 来解决这个问题。查看代码,我什至无法自己弄清楚。

【讨论】:

    【解决方案2】:

    如果您不介意使用第三方代码,here 是我制作的一个 Java 图像库,它可以做的不仅仅是抓取动画 GIF 的每一帧。

    也就是说,有一个名为 FrameReader 的特定类,它旨在完全按照您的意愿进行操作:一次抓取一个 GIF 帧。下面的例子展示了如何使用它:

    import java.awt.image.BufferedImage;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    import com.icafe4j.image.gif.FrameReader;
    import com.icafe4j.image.gif.GIFFrame;
    
    
    public class GrabFrame {
    
        public static void main(String[] args) throws Exception {
            InputStream is = new FileInputStream(args[0]);
            FrameReader reader = new FrameReader();
            BufferedImage curFrame = null;
    
            GIFFrame gifFrame = reader.getGIFFrameEx(is);
    
            while(gifFrame != null) {
                curFrame = gifFrame.getFrame();
                // Do something with curFrame
                gifFrame = reader.getGIFFrameEx(is);
            }       
        }
    }
    

    getGIFFrameEx(is) 方法返回一个 GIFFrame 实例,该实例在其他帧控制参数中包装了一个 BufferedImage,它考虑了动画 GIF 图形控制块使用的不同处理方法。如果你不关心处理方法,你可以调用getGIFFrame(is),它也包装了一个BufferedImage,但是它没有考虑不同帧之间的关系。正如here 所说,这可能会产生看起来很奇怪的帧。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 2022-12-05
      • 2013-01-07
      • 2011-05-12
      • 2012-02-14
      • 1970-01-01
      相关资源
      最近更新 更多