2014-11-07 2 views
0

Я создаю приложение Java, которое отображает определенные файлы GIF из папки. Я в настоящее время, используя кодфиксировать частоту кадров анимированного gif в Java

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

Это работает безупречно, за исключением того, что многие (тысячи) из моих .GIF файлов имеет неправильно частоту кадров, что делает их отображения на бесконечной скорости (frameDelay = 0), при условии, что браузер установит это автоматически. Java по умолчанию не делает этого. Как я могу переопределить frameDelay Java должен использовать для этих анимированных gif с frameDelay = 0?

+0

Вы преобразования '' ImageIcon' в Image' и наоборот. –

+0

См. [Java Gif на значке с квадратами фона, показывающим?] (Http://stackoverflow.com/a/9707490/3453226). –

+0

@ Джойнер. Это важно? Я отредактировал это сейчас, но это не имеет никакого значения. – user1111929

ответ

1

Я нашел this, и он хорошо работает для одного gif, который я пробовал.

Я понятия не имею, что он делает, но с первого взгляда он выглядит как, если первый кадр имеет задержку 0, он перезаписывает задержку для всех кадров с 10. Затем он пишет новый GIF-файл в памяти и загружает изображения.

[edit] Я немного отполировал его и сгладил ошибки.

  • Нет патентованный API
  • Не просто проверить 1-й кадр, чтобы определить, является ли он прослушивал,
  • Заменяет оттянуть только для кадров, где это ноль.
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; 
    } 
} 
+0

Этот код смог исправить мои текущие файлы .gif, спасибо! Только одна проблема: он дает мне предупреждение «GIFImageMetadata является внутренним патентованным API и может быть удалена в будущей версии». Был бы какой-нибудь путь вокруг этого? Я бы, конечно, хотел бы, чтобы моя программа продолжала работать в будущей версии Java, поэтому, если этот пакет вот-вот исчезнет, ​​это проблема. – user1111929

+0

Неважно, используя код в этом разделе http://stackoverflow.com/questions/20077913/read-delay-between-frames-in-animated-gif Мне удалось исправить это предупреждение, теперь код больше не использует GIFImageMetadata класс. Теперь все работает. Огромное спасибо! – user1111929

Смежные вопросы