当前位置: 首页 > 面试题库 >

修复Java中动画gif的帧频

邴英毅
2023-03-14
问题内容

我正在制作一个Java应用程序,它显示文件夹中的某些GIF文件。我目前正在使用代码

  final JLabel imageLabel = new JLabel();
  imageLabel.setIcon(new ImageIcon(fileName));
  contentPane.add(imageLabel, java.awt.BorderLayout.CENTER);

可以正常工作,只是我的许多.GIF文件的帧速率配置不正确,前提是浏览器会自动修复此问题,从而使它们以无限的速度显示(frameDelay =
0)。Java默认情况下不执行此操作。如何覆盖frameDelay = 0的Java动画gif必须使用的frameDelay?


问题答案:

我已经找到了,并且非常适合我尝试过的一个gif。

我不知道他到底在做什么,但是乍一看, 如果第一帧的延迟为0,它将覆盖所有帧的延迟,即为10。然后他“写入”内存中的新GIF文件并将其加载到图片。

[编辑]我将它擦亮了一点,并消除了这些错误。

  • 没有专有的API
  • 不只是检查第一帧以确定它是否被窃听,
  • 仅将延迟替换为零的帧。

    public static Image readImgFromFile(String filename, Component parent) {
    File file = new File(filename);
    if (!file.exists()) {
    return null;
    }

    // Fix for bug when delay is 0
    try {
        // Load anything but GIF the normal way
        if (!filename.substring(filename.length() - 4).equalsIgnoreCase(".gif")) {
            return ImageIO.read(file);
        }
    
        // Get GIF reader
        ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
        // Give it the stream to decode from
        reader.setInput(ImageIO.createImageInputStream(file));
    
        int numImages = reader.getNumImages(true);
    
        // Get 'metaFormatName'. Need first frame for that.
        IIOMetadata imageMetaData = reader.getImageMetadata(0);
        String metaFormatName = imageMetaData.getNativeMetadataFormatName();
    
        // Find out if GIF is bugged
        boolean foundBug = false;
        for (int i = 0; i < numImages && !foundBug; i++) {
            // Get metadata
            IIOMetadataNode root = (IIOMetadataNode)reader.getImageMetadata(i).getAsTree(metaFormatName);
    
            // Find GraphicControlExtension node
            int nNodes = root.getLength();
            for (int j = 0; j < nNodes; j++) {
                Node node = root.item(j);
                if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) {
                    // Get delay value
                    String delay = ((IIOMetadataNode)node).getAttribute("delayTime");
    
                    // Check if delay is bugged
                    if (Integer.parseInt(delay) == 0) {
                        foundBug = true;
                    }
    
                    break;
                }
            }
        }
    
        // Load non-bugged GIF the normal way
        Image image;
        if (!foundBug) {
            image = Toolkit.getDefaultToolkit().createImage(filename);
        } else {
            // Prepare streams for image encoding
            ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
            try (ImageOutputStream ios = ImageIO.createImageOutputStream(baoStream)) {
                // Get GIF writer that's compatible with reader
                ImageWriter writer = ImageIO.getImageWriter(reader);
                // Give it the stream to encode to
                writer.setOutput(ios);
    
                writer.prepareWriteSequence(null);
    
                for (int i = 0; i < numImages; i++) {
                    // Get input image
                    BufferedImage frameIn = reader.read(i);
    
                    // Get input metadata
                    IIOMetadataNode root = (IIOMetadataNode)reader.getImageMetadata(i).getAsTree(metaFormatName);
    
                    // Find GraphicControlExtension node
                    int nNodes = root.getLength();
                    for (int j = 0; j < nNodes; j++) {
                        Node node = root.item(j);
                        if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) {
                            // Get delay value
                            String delay = ((IIOMetadataNode)node).getAttribute("delayTime");
    
                            // Check if delay is bugged
                            if (Integer.parseInt(delay) == 0) {
                                // Overwrite with a valid delay value
                                ((IIOMetadataNode)node).setAttribute("delayTime", "10");
                            }
    
                            break;
                        }
                    }
    
                    // Create output metadata
                    IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(frameIn), null);
                    // Copy metadata to output metadata
                    metadata.setFromTree(metadata.getNativeMetadataFormatName(), root);
    
                    // Create output image
                    IIOImage frameOut = new IIOImage(frameIn, null, metadata);
    
                    // Encode output image
                    writer.writeToSequence(frameOut, writer.getDefaultWriteParam());
                }
    
                writer.endWriteSequence();
            }
    
            // Create image using encoded data
            image = Toolkit.getDefaultToolkit().createImage(baoStream.toByteArray());
        }
    
        // Trigger lazy loading of image
        MediaTracker mt = new MediaTracker(parent);
        mt.addImage(image, 0);
        try {
            mt.waitForAll();
        }
        catch (InterruptedException e) {
            image = null;
        }
        return image;
    }
    catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    

    }



 类似资料:
  • 1.4. GIF动画 下面的程序会演示Go语言标准库里的image这个package的用法,我们会用这个包来生成一系列的bit-mapped图,然后将这些图片编码为一个GIF动画。我们生成的图形名字叫利萨如图形(Lissajous figures),这种效果是在1960年代的老电影里出现的一种视觉特效。它们是协振子在两个纬度上振动所产生的曲线,比如两个sin正弦波分别在x轴和y轴输入会产生的曲线。

  • 问题内容: 我想在应用程序中显示GIF动画图像。我发现,Android本身并不支持动画GIF的困难方式。 但是,它可以使用AnimationDrawable显示动画: 开发>指南>图像和图形> Drawables概述 该示例使用在应用程序资源中另存为帧的动画,但是我需要直接显示动画gif。 我的计划是将动画GIF分解为帧,并将每个帧作为可绘制对象添加到AnimationDrawable中。 有谁知

  • 问题内容: 您好,我正在使用Swing在Java 1.6上编写GUI应用程序。 我有一个弹出屏幕,该窗口在加载Swing gui时以及稍后会显示gif动画。 我的弹出屏幕是一个JDialog。动画应显示在通过以下方式添加到Jdialog的JLabel上: 现在的事情是,动画仅在gui加载后显示。我相信在GUI加载时(这是我的应用程序中的繁重操作),EDT太忙了,无法运行动画。 现在的问题是,将GU

  • 我对编程和电话差距非常陌生。在计算机上测试的GIF的动画似乎工作正常,但是当导出到api并安装到我的手机中时。动画是滞后和故障。你知道为什么会发生这种情况吗?谢谢。

  • 帧动画模块可以将一系列BK.TextureInfo对象进行播放,构成动画效果。 父类:BK.Sprite 构造函数 BK.AnimationSprite(textureInfoArray) 通过textureInfoArray数组创建一个帧动画对象 手Q版本:7.6.3 textureInfoArray: 参数名 类型 textureInfoArray Array BK.TextureInfo可以

  • 问题内容: 所以我有一个动画gif,我像这样加载到ImageIcon中: 我可以用这个画它: 我知道我可以使用AffineTransform动态地对其进行镜像,但是我需要能够在加载后对其进行水平镜像,以便可以根据需要绘制镜像的镜像,而无需每次重新绘制时都要对其进行转换的开销。有没有一种方法可以使用摆动/自动? 一个可以做到这一点的图书馆也将提供巨大的帮助。 问题答案: 正如您所指出的,问题是gif