2017-02-28 167 views
-1

我有一個Java程序,可以創建多個PNG文件(截圖)。我現在需要找到一種方法來從這些文件中創建一個GIF動畫,並且不知道從哪裏開始。如何將多個PNG文件轉換爲動畫GIF?

如何將多個PNG文件轉換爲動畫GIF?

+0

對不起,這不是StackOverflow的工作方式。形式問題_「我想做X,請給我提示和/或示例代碼」_被認爲是題外話。請訪問[幫助]並閱讀[問],尤其是閱讀[爲什麼是「有人可以幫助我?」不是一個真正的問題?](http://meta.stackoverflow.com/q/284236/18157) –

+0

我不知道該怎麼做,谷歌一直沒有幫助,所以我應該問什麼? –

+0

我做了一個谷歌serach「轉換PNG動畫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); 
    } 
} 
+0

有人知道如何傳遞參數?我傳遞「a.png,b.png,c.png」而沒有引號,它說這是錯誤的... – Jas

+0

@Jas他們在'a.png,b.png,c.png'中有5個參數 - 其中兩個是兩個逗號。如果它是'a.png,b.png,c.png'(value和','之間沒有空格),那麼它會是三個參數。 –

+0

@andewv - 謝謝,但它仍然無法正常工作。它繼續說,我只有一個圖像,當我應該有兩個或更多... – Jas