使用 Java 时帧速率不同的动画 gif 加载不正确

Animated gif with varying frame rates loading incorrectly using Java

我想我刚刚指出了问题所在,但我仍然不确定该怎么做。

我使用 Photoshop 创建了各种动画 gif,我想在我的 java 应用程序中显示它们。使用 ImageIcon,其中一些会按应有的方式显示。这些是具有相同帧速率的帧(例如每帧长 1 秒)。但是,具有不同帧速率的 gif(例如,一帧是 1 秒,另一帧是 0.5 秒,下一帧是 .2)似乎无法正确显示。一旦 gif 到达以秒为单位变化的帧,图像就会混乱。一些例子包括背景短暂地改变颜色和一半图像消失,或者大部分图像消失而 gif 仍在动画。

我很难表达,但我是否需要使用 ImageIcon 以外的其他东西来正确加载具有不同帧速率的 gif?喜欢 BufferedImage 吗?

编辑:在下面添加了完整的代码。同样,它适用于具有相同帧速率的图像,但不适用于具有不同帧速率的图像。

here is the image that works fine

here is the image that messes up

import java.awt.*;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;


public class Creature extends JWindow {
    public void initCreature() {

        JPanel contentPane = (JPanel) getContentPane();
        ImageIcon idleImage = new ImageIcon(getClass().getResource("img.gif"));

        // Set window properties
        getRootPane().putClientProperty("Window.shadow", false);
        setBackground(new Color(0,0,0,0));
        setAlwaysOnTop(true);
        contentPane.setOpaque(false);

        // Get size of user's screen
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
        Rectangle screen = defaultScreen.getDefaultConfiguration().getBounds();
        int taskbarheight = (int) (Toolkit.getDefaultToolkit().getScreenSize().height 
        - GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().getHeight());

        int x = (int) screen.getMaxX() - idleImage.getIconWidth();
        int y = (int) screen.getMaxY() - idleImage.getIconHeight() - taskbarheight;

        JLabel imageLabel = new JLabel(idleImage);
        setSize(idleImage.getIconWidth(), idleImage.getIconHeight());
        contentPane.add(imageLabel);
        setLocation(x, y);
        setVisible(true);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                Creature cr = new Creature();
                cr.initCreature();          
            }
        });

    }
}

imageLabel不知道在 GIF 的帧改变时重新绘制。您需要通过将 JLabel 传递给 setImageObserver:

来告诉 ImageIcon 通知 JLabel 帧更改
idleImage.setImageObserver(imageLabel);

来自该方法的文档:

Set this property if the ImageIcon contains an animated GIF, so the observer is notified to update its display.

两个版本的帧速率似乎相同(一个在浏览器中看到,另一个在 JLabel 中看到)。实际问题是 Java 中的渲染在动画的 区域中变为 'clipped' 'clipped'

我猜想问题在于 PhotoShop 使用高级编码来确保只有 框架发生变化的部分 得到更新。请注意,尽管 Java 支持特定的 文件类型 ,如 GIF、PNG 或 JPEG,但这并不意味着它能正确理解每个 encoding 类型每种文件类型。

一个更简单的图像,每次更改都会更改 整个帧 应该效果更好,但字节数也更大。事实上,您可以在另一张图片中看到它的工作原理。因为小龙是弯着腰又站起来,可见图像的所有部分都需要改变,所以不能像第一张图像那样优化动画。