Java GIF动画无法正确重新绘制

时间:2014-10-12 22:14:00

标签: java swing animation gif imageicon

我试图为GIF图像制作动画。动画有效,但效果不佳。

它显示如下(非动画屏幕截图):How I see it

在图片中,尾巴像这样摇晃:This was the image I used

如您所见,图像不能很好地重现。我不想使用JLabel,但这样做不正常,所以我跟着this question when my image did not animate

我的代码是这样的:

public void draw(JPanel canvas, Graphics2D g2d, int x, int y) {
    getFrontImage().paintIcon(canvas, g2d, x, y);
}

检索图像的位置如下:

ImageIcon gif = new ImageIcon(getClass().getResource(filename));

在JPanel画布中,我制作了一个paint方法和一个每10ms重绘一次的计时器线程。这适用于除GIF之外的所有事情。有谁可以帮我这个?

---编辑

我很抱歉误会,我已将图片更新为我实际使用的图像。我希望得到正确答案并不是太麻烦......

1 个答案:

答案 0 :(得分:6)

好吧,经过多次讨论之后,我终于可以将框架的处理方法更改为restoreToBackgroundColor。基本上,这意味着动画不是增量变化,而是完整的帧替换......

Pica Gif

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class AnimatedGifTest1 {

    public static void main(String[] args) {
        new AnimatedGifTest1();
    }

    public AnimatedGifTest1() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new PaintPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class PaintPane extends JPanel {

        private ImageIcon image;

        public PaintPane() {
            image = new ImageIcon(getClass().getResource("/ertcM02.gif"));
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? new Dimension(200, 200) : new Dimension(image.getIconWidth(), image.getIconHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); // This is very important!
            int x = (getWidth() - image.getIconWidth()) / 2;
            int y = (getHeight() - image.getIconHeight()) / 2;
            image.paintIcon(this, g, x, y);
        }

    }



}

<强>更新...

所以,我终于能够看一下你正在使用的gif的处理方法,它被设置为restoreToPrevious,根据GRAPHICS INTERCHANGE FORMAT Version 89a的意思:

  

恢复到上一个​​。解码器需要恢复图形覆盖的区域,以及渲染图形之前的区域。

我上面提供的图片使用restoreToBackgroundColor的位置,根据GRAPHICS INTERCHANGE FORMAT Version 89a表示:

  

恢复为背景色。必须将图形使用的区域恢复为背景颜色

您可以使用以下代码自行检查......

public static class AnimatedGif {

    public enum DisposalMethod {

        RESTORE_TO_BACKGROUND,
        RESTORE_TO_PREVIOUS,
        DO_NOT_DISPOSE,
        UNSPECIFIED;

        public static DisposalMethod find(String text) {

            DisposalMethod dm = UNSPECIFIED;
            System.out.println(text);

            switch (text) {
                case "restoreToBackgroundColor":
                    dm = RESTORE_TO_BACKGROUND;
                    break;
                case "restoreToPrevious":
                    dm = RESTORE_TO_PREVIOUS;
                    break;
            }

            return dm;

        }
    }

    private List<ImageFrame> frames;
    private int frame;

    public AnimatedGif(JComponent player, URL url) throws IOException {
        frames = new ArrayList<>(25);
        try (InputStream is = url.openStream(); ImageInputStream stream = ImageIO.createImageInputStream(is)) {
            Iterator readers = ImageIO.getImageReaders(stream);
            if (!readers.hasNext()) {
                throw new RuntimeException("no image reader found");
            }
            ImageReader reader = (ImageReader) readers.next();
            reader.setInput(stream);            // don't omit this line!
            int n = reader.getNumImages(true);  // don't use false!
            System.out.println("numImages = " + n);
            for (int i = 0; i < n; i++) {
                BufferedImage image = reader.read(i);
                ImageFrame imageFrame = new ImageFrame(image);

                IIOMetadata imd = reader.getImageMetadata(i);
                Node tree = imd.getAsTree("javax_imageio_gif_image_1.0");
                NodeList children = tree.getChildNodes();

                for (int j = 0; j < children.getLength(); j++) {
                    Node nodeItem = children.item(j);
                    NamedNodeMap attr = nodeItem.getAttributes();
                    switch (nodeItem.getNodeName()) {
                        case "ImageDescriptor":
                            ImageDescriptor id = new ImageDescriptor(
                                            getIntValue(attr.getNamedItem("imageLeftPosition")),
                                            getIntValue(attr.getNamedItem("imageTopPosition")),
                                            getIntValue(attr.getNamedItem("imageWidth")),
                                            getIntValue(attr.getNamedItem("imageHeight")),
                                            getBooleanValue(attr.getNamedItem("interlaceFlag")));
                            imageFrame.setImageDescriptor(id);
                            break;
                        case "GraphicControlExtension":
                            GraphicControlExtension gc = new GraphicControlExtension(
                                            DisposalMethod.find(getNodeValue(attr.getNamedItem("disposalMethod"))),
                                            getBooleanValue(attr.getNamedItem("userInputFlag")),
                                            getBooleanValue(attr.getNamedItem("transparentColorFlag")),
                                            getIntValue(attr.getNamedItem("delayTime")) * 10,
                                            getIntValue(attr.getNamedItem("transparentColorIndex")));
                            imageFrame.setGraphicControlExtension(gc);
                            break;
                    }
                }
                frames.add(imageFrame);
            }
        } finally {
        }
    }

    protected String getNodeValue(Node node) {
        return node == null ? null : node.getNodeValue();
    }

    protected int getIntValue(Node node) {
        return node == null ? 0 : getIntValue(node.getNodeValue());
    }

    protected boolean getBooleanValue(Node node) {
        return node == null ? false : getBooleanValue(node.getNodeValue());
    }

    protected int getIntValue(String value) {
        return value == null ? 0 : Integer.parseInt(value);
    }

    protected boolean getBooleanValue(String value) {
        return value == null ? false : Boolean.parseBoolean(value);
    }

    public class ImageFrame {

        private BufferedImage image;
        private ImageDescriptor imageDescriptor;
        private GraphicControlExtension graphicControlExtension;

        public ImageFrame(BufferedImage image) {
            this.image = image;
        }

        protected void setImageDescriptor(ImageDescriptor imageDescriptor) {
            this.imageDescriptor = imageDescriptor;
        }

        protected void setGraphicControlExtension(GraphicControlExtension graphicControlExtension) {
            this.graphicControlExtension = graphicControlExtension;
            System.out.println(graphicControlExtension.getDisposalMethod());
        }

        public GraphicControlExtension getGraphicControlExtension() {
            return graphicControlExtension;
        }

        public BufferedImage getImage() {
            return image;
        }

        public ImageDescriptor getImageDescriptor() {
            return imageDescriptor;
        }

    }

    public class GraphicControlExtension {

        private DisposalMethod disposalMethod;
        private boolean userInputFlag;
        private boolean transparentColorFlag;
        private int delayTime;
        private int transparentColorIndex;

        public GraphicControlExtension(DisposalMethod disposalMethod, boolean userInputFlag, boolean transparentColorFlag, int delayTime, int transparentColorIndex) {
            this.disposalMethod = disposalMethod;
            this.userInputFlag = userInputFlag;
            this.transparentColorFlag = transparentColorFlag;
            this.delayTime = delayTime;
            this.transparentColorIndex = transparentColorIndex;
        }

        public int getDelayTime() {
            return delayTime;
        }

        public DisposalMethod getDisposalMethod() {
            return disposalMethod;
        }

        public int getTransparentColorIndex() {
            return transparentColorIndex;
        }

        public boolean isTransparentColorFlag() {
            return transparentColorFlag;
        }

        public boolean isUserInputFlag() {
            return userInputFlag;
        }

    }

    public class ImageDescriptor {

        private int imageLeftPosition;
        private int imageTopPosition;
        private int imageHeight;
        private int imageWeight;
        private boolean interlaced;

        public ImageDescriptor(int imageLeftPosition, int imageTopPosition, int imageHeight, int imageWeight, boolean interlaced) {
            this.imageLeftPosition = imageLeftPosition;
            this.imageTopPosition = imageTopPosition;
            this.imageHeight = imageHeight;
            this.imageWeight = imageWeight;
            this.interlaced = interlaced;
        }

        public int getImageHeight() {
            return imageHeight;
        }

        public int getImageLeftPosition() {
            return imageLeftPosition;
        }

        public int getImageTopPosition() {
            return imageTopPosition;
        }

        public int getImageWeight() {
            return imageWeight;
        }

        public boolean isInterlaced() {
            return interlaced;
        }

    }

}

此代码来自.gif image doesn't moves on adding it to the JTabbed pane