猛禽洛的程式筆記庫

[JavaFx] 播放Gif

雖然在JavaFx中,ImageView跟Image物件支援Gif,但是相容性好像不怎麼好,試了5張只有1張能動。

研究了一下發現有Gif的解碼器套件,雖然有點麻煩,但手動處理後相容性好多了,也比較能控制(例如:暫停播放)。

大致上的流程為:

  1. 使用套件解碼Gif成多張圖片。
  2. 將圖片放進陣列。
  3. 紀錄圖片間格。
  4. 建立一個Timer,輪播圖片。

實作部分:

1.在pom.xml導入解碼套件:

Github來源

<dependency>
  <groupId>com.github.zh79325</groupId>
  <artifactId>open-gif</artifactId>
  <version>1.0.4</version>
</dependency>

 

2.讀入Gif檔,並解碼放進陣列

此範例是將Gif作為背景使用,所以比較多轉換過程。

實際上要在ImageView中顯示的話,只要轉成Image即可,不用這麼麻煩轉成Background格式。

private void reloadGifBackground1(){
  //讀入Gif File
  File bg = new File(fsv.getHomeDirectory() + "giphy.gif");
  try{
    final FileInputStream data = new FileInputStream(bg.getAbsolutePath());
    //使用GifDecoder解碼
    final GifDecoder.GifImage gif = GifDecoder.read(data);
    //圖片寬高,如果需要的話
    final int width = gif.getWidth();
    final int height = gif.getHeight();
    //影格總數
    final int frameCount = gif.getFrameCount();

    //存放每個影格的圖片(這邊要放在背景所以才用Background格式,一般存成Image格式即可)
    Background[] bgArray = new Background[frameCount];
    //影格的時間,可以統一儲存也可以存進陣列,看圖片
    int delay = 0;
    //開始讀取影格
    for (int i = 0; i < frameCount; i++) {
      final BufferedImage img = gif.getFrame(i);
      //轉換圖檔並存入陣列
      Image im = SwingFXUtils.toFXImage(img, null);
      bgArray[i] = new Background(new BackgroundImage(im,
          BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER,
          BackgroundSize.DEFAULT));
      delay = gif.getDelay(i);
    }
    //播放
    playGifToBackground1(delay, bgArray, frameCount);
  } catch (IOException e) {
    e.printStackTrace();
  }
}

 

3.使用Timer播放Gif

playGifToBackground1

private int gifBackgroundIndex1 = 0;//gif目前的播放位置
private Timer gifToBackgroundTimer1 = null;
/**
 * 播放gif
 * @param speed 解檔gif中的速度
 * @param bg 轉換過的背景陣列
 * @param count 圖片數
 */
private void playGifToBackground1(long speed, Background[] bg, int count){
  //每當重新呼叫時,重設(播放新圖片)
  gifBackgroundIndex1 = 0;
  gifToBackgroundTimer1 = null;
  gifToBackgroundTimer1 = new Timer();
  gifToBackgroundTimer1.schedule(new TimerTask() {
    public void run() {
      Platform.runLater(() -> {
        aptest.setBackground(bg[gifBackgroundIndex1]);
      });
      //往下一個影格播放,如果到底了就重播
      if(gifBackgroundIndex1 < count-1){
        gifBackgroundIndex1++;
      }else{
        gifBackgroundIndex1 = 0;
      }
    }
  }, 0, speed*10);
}

因為是使用Timer,所以最後離開程式時,要記得關掉。

可以用一個boolean值,控制Gif的播放暫停。

speed速度的部分,不知道為什麼要*10才正確。

 

-END-

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *