如何将多个 PNG 文件转换为动画 GIF? [关闭]

Posted

技术标签:

【中文标题】如何将多个 PNG 文件转换为动画 GIF? [关闭]【英文标题】:How to convert multiple PNG files to an animated GIF? [closed] 【发布时间】:2017-07-19 18:21:46 【问题描述】:

我有一个创建多个 PNG 文件(截图)的 java 程序。我现在需要找到一种从这些文件创建动画 GIF 的方法,但不知道从哪里开始。

如何将多个 PNG 文件转换为动画 GIF?

【问题讨论】:

抱歉,这不是 *** 的工作方式。 “我想做 X,请给我提示和/或示例代码” 形式的问题被视为离题。请访问help center并阅读How to Ask,尤其是阅读Why is “Can someone help me?” not an actual question? 我不知道该怎么做,谷歌也没有帮助,我该怎么问? 我为“将 png 转换为动画 gif java”做了一个 Google 搜索,并获得了很多点击。显然你实际上并没有做任何研究。 我做了,但实际上没有一个对如何使用它们有任何体面的解释 使用ImageMagick,那么就是convert -delay 80 *.png animated, gif 【参考方案1】:

改编自旧的thread on Sun forums。不包括电池,所有保修均无效。

import java.awt.image.BufferedImage;
import java.io.File;
import org.w3c.dom.Node;

import javax.imageio.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.ImageOutputStream;

/**
 * Creates an animated GIF from GIF frames. A thin wrapper to code written by
 * other people, as documented on the thread on the Sun forums 'Create animated
 * GIF using imageio' http://forums.sun.com/thread.jspa?threadID=5395006 See the
 * printUsage() method for details on paramaters required.
 *
 * @author Andrew Thompson
 */
class WriteAnimatedGif 

    /**
     * See http://forums.sun.com/thread.jspa?messageID=10755673#10755673
     *
     * @author Maxideon
     * @param delayTime String Frame delay for this frame.
     */
    public static void configure(IIOMetadata meta,
            String delayTime,
            int imageIndex) 

        String metaFormat = meta.getNativeMetadataFormatName();

        if (!"javax_imageio_gif_image_1.0".equals(metaFormat)) 
            throw new IllegalArgumentException(
                    "Unfamiliar gif metadata format: " + metaFormat);
        

        Node root = meta.getAsTree(metaFormat);

        //find the GraphicControlExtension node
        Node child = root.getFirstChild();
        while (child != null) 
            if ("GraphicControlExtension".equals(child.getNodeName())) 
                break;
            
            child = child.getNextSibling();
        

        IIOMetadataNode gce = (IIOMetadataNode) child;
        gce.setAttribute("userDelay", "FALSE");
        gce.setAttribute("delayTime", delayTime);

        //only the first node needs the ApplicationExtensions node
        if (imageIndex == 0) 
            IIOMetadataNode aes
                    = new IIOMetadataNode("ApplicationExtensions");
            IIOMetadataNode ae
                    = new IIOMetadataNode("ApplicationExtension");
            ae.setAttribute("applicationID", "NETSCAPE");
            ae.setAttribute("authenticationCode", "2.0");
            byte[] uo = new byte[]
                //last two bytes is an unsigned short (little endian) that
                //indicates the the number of times to loop.
                //0 means loop forever.
                0x1, 0x0, 0x0
            ;
            ae.setUserObject(uo);
            aes.appendChild(ae);
            root.appendChild(aes);
        

        try 
            meta.setFromTree(metaFormat, root);
         catch (IIOInvalidTreeException e) 
            //shouldn't happen
            throw new Error(e);
        
    

    /**
     * See http://forums.sun.com/thread.jspa?messageID=9988198
     *
     * @author GeoffTitmus
     * @param file File A File in which to store the animation.
     * @param frames BufferedImage[] Array of BufferedImages, the frames of the
     * animation.
     * @param delayTimes String[] Array of Strings, representing the frame delay
     * times.
     */
    public static void saveAnimate(
            File file,
            BufferedImage[] frames,
            String[] delayTimes) throws Exception 

        ImageWriter iw = ImageIO.getImageWritersByFormatName("gif").next();

        ImageOutputStream ios = ImageIO.createImageOutputStream(file);
        iw.setOutput(ios);
        iw.prepareWriteSequence(null);

        for (int i = 0; i < frames.length; i++) 
            BufferedImage src = frames[i];
            ImageWriteParam iwp = iw.getDefaultWriteParam();
            IIOMetadata metadata = iw.getDefaultImageMetadata(
                    new ImageTypeSpecifier(src), iwp);
            configure(metadata, delayTimes[i], i);
            IIOImage ii = new IIOImage(src, null, metadata);
            iw.writeToSequence(ii, null);
        

        iw.endWriteSequence();

        ios.close();
    

    /**
     * Dump the usage to the System.err stream.
     */
    public static void printUsage() 
        StringBuffer sb = new StringBuffer();
        String eol = System.getProperty("line.separator");
        sb.append("Usage: 2 forms each using 3 arguments");
        sb.append(eol);
        sb.append("1) output (animated GIF) file name");
        sb.append(eol);
        sb.append("2) input files (animation frames), separated by ','");
        sb.append(eol);
        sb.append("3) single frame rate, or comma separared list of frame rates");
        sb.append(eol);
        sb.append("java WriteAnimatedGif animate.gif frm1.gif,frm2.gif,..,frmN.gif 100");
        sb.append(eol);
        sb.append("java WriteAnimatedGif animate.gif frm1.gif,frm2.gif,..,frmN.gif 100,40,..,N");
        sb.append(eol);
        sb.append("The 2nd form must have exactly as many integers as there are frames.");
        sb.append(eol);
        sb.append("Frame rates are specified in increments of 1/100th second, NOT milliseconds.");
        sb.append(eol);

        System.err.print(sb);
    

    /**
     * Checks that a String intended as a delayTime is an integer>0. If not,
     * dumps a warning message and the usage, then exits. If successful, returns
     * the String unaltered.
     */
    public static String checkDelay(String delay) 
        try 
            int val = Integer.parseInt(delay);
            if (val < 1) 
                System.err.println(
                        "Animation frame delay '"
                        + val
                        + "' is < 1!");
                printUsage();
                System.exit(1);
            
         catch (NumberFormatException nfe) 
            System.err.println(
                    "Could not parse '"
                    + delay
                    + "' as an integer.");
            printUsage();
            System.exit(1);
        
        return delay;
    

    /**
     * Parse the arguments and if successful, attempt to write the animated GIF.
     */
    public static void main(String[] args) throws Exception 

        if (args.length != 3) 
            printUsage();
            System.exit(1);
        

        // deal with the output file name
        File f = new File(args[0]);

        // deal with the input file names
        String[] names = args[1].split(",");
        if (names.length < 2) 
            System.err.println("An animation requires 2 or more frames!");
            printUsage();
            System.exit(1);
        
        BufferedImage[] frames = new BufferedImage[names.length];
        for (int ii = 0; ii < names.length; ii++) 
            frames[ii] = ImageIO.read(new File(names[ii]));
        

        // deal with the frame rates
        String[] delays = args[2].split(",");
        // note: length of names, not delays
        String[] delayTimes = new String[names.length];
        if (delays.length != names.length) 
            System.err.println(delays.length
                    + " delays specified for "
                    + names.length
                    + " frames!");
            printUsage();
            System.exit(1);
         else if (delays.length == 1) 
            for (int ii = 0; ii < delayTimes.length; ii++) 
                // fill all values with the single delayTime
                delayTimes[ii] = checkDelay(delays[0]);
            
         else 
            for (int ii = 0; ii < delayTimes.length; ii++) 
                delayTimes[ii] = checkDelay(delays[ii]);
            
        

        // save an animated GIF
        saveAnimate(f, frames, delayTimes);
    

【讨论】:

有人知道如何传递参数吗?我正在传递 "a.png , b.png , c.png" 没有引号,它说这是错误的...... @Jas 它们是a.png , b.png , c.png 中的 5 个参数 - 其中两个是两个逗号。如果改为a.png, b.png, c.png(值和, 之间没有空格),它将是三个参数。 @andewv - 谢谢,但它仍然无法正常工作。它继续说我只有一个图像,而我应该有 2 个或更多... @Jas “它继续说我只有一个图像” 代码无法“说出”任何类似的东西。始终复制/粘贴错误和异常输出!顺便说一句 - 我刚刚意识到 a.png, b.png, c.png 实际上应该是 a.png,b.png,c.png (根本没有空格字符)。 它给了我一个“异常的数组绑定索引”-> 它将此条目作为唯一参数“frame41,frame42,frame43”。线程“main”中的异常 java.lang.ArrayIndexOutOfBoundsException: 1 at a.video.prototypes.WriteAnimatedGif.main(WriteAnimatedGif.java:175)

以上是关于如何将多个 PNG 文件转换为动画 GIF? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何将emf文件转换成png格式

Android 将 gif 转换为动画 webp

如何从多个 png 图像创建动画 gif 图像?

从一组 png 图像创建动画 gif

如何使用 PHP 冻结动画 gifs/转换为 jpg?

有没有办法将图像文件夹(png、gif)转换为 Python 中的数组列表?