// -*- mode:java; encoding:utf-8 -*-
// vim:set fileencoding=utf-8:
// @homepage@

package example;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.StreamSupport;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;

public final class MainPanel extends JPanel {
  private MainPanel() {
    super(new BorderLayout());
    URL url = getClass().getResource("duke.running.gif");
    JLabel label = new JLabel();
    label.setIcon(new ImageIcon(url));
    label.setBorder(BorderFactory.createTitledBorder("duke.running.gif"));

    Box box = Box.createHorizontalBox();
    box.setBorder(BorderFactory.createTitledBorder("Extract frames from Animated GIF"));

    // [JDK-8080225] FileInput/OutputStream/FileChannel cleanup should be improved - Java Bug System
    // https://bugs.openjdk.java.net/browse/JDK-8080225
    // try (InputStream is = getClass().getResourceAsStream("duke.running.gif");
    //      ImageInputStream iis = ImageIO.createImageInputStream(is)) {
    // URL url = getClass().getResource("duke.running.gif");
    // try (InputStream is = Files.newInputStream(Paths.get(url.toURI()));
    //      ImageInputStream iis = ImageIO.createImageInputStream(is)) {
    try (ImageInputStream iis = ImageIO.createImageInputStream(url.openStream())) {
      loadFromStream(iis).stream().map(ImageIcon::new).map(JLabel::new).forEach(box::add);
    } catch (IOException ex) {
      ex.printStackTrace();
      label.setText(ex.getMessage());
    }
    add(label, BorderLayout.WEST);
    add(new JScrollPane(box));
    setPreferredSize(new Dimension(320, 240));
  }
  // // https://community.oracle.com/thread/1271862 Reading gif animation frame rates and such?
  // private List<BufferedImage> loadFromStream(ImageInputStream imageStream) throws IOException {
  //   String format = "gif";
  //   String meta = "javax_imageio_gif_image_1.0";
  //   ImageReader reader = null;
  //   Iterator<ImageReader> readers = ImageIO.getImageReaders(imageStream);
  //   while (readers.hasNext()) {
  //     reader = readers.next();
  //     String metaFormat = reader.getOriginatingProvider().getNativeImageMetadataFormatName();
  //     if (format.equalsIgnoreCase(reader.getFormatName()) && meta.equals(metaFormat)) {
  //       break;
  //     }
  //   }
  //   ImageReader imageReader = Objects.requireNonNull(reader, "Can not read image format!");
  //   boolean isGif = format.equalsIgnoreCase(imageReader.getFormatName());
  //   imageReader.setInput(imageStream, false, !isGif);
  //   List<BufferedImage> list = new ArrayList<>();
  //   for (int i = 0; i < imageReader.getNumImages(true); i++) {
  //     IIOImage frame = imageReader.readAll(i, null);
  //     list.add((BufferedImage) frame.getRenderedImage());
  //   }
  //   imageReader.dispose();
  //   return list;
  // }

  private static List<BufferedImage> loadFromStream(ImageInputStream imageStream) throws IOException {
    Iterable<ImageReader> it = () -> ImageIO.getImageReaders(imageStream);
    ImageReader reader = StreamSupport.stream(it.spliterator(), false)
        .filter(MainPanel::checkGifFormat)
        .findFirst()
        .orElseThrow(() -> new IOException("Can not read image format!"));
    reader.setInput(imageStream, false, false);
    List<BufferedImage> list = new ArrayList<>();
    for (int i = 0; i < reader.getNumImages(true); i++) {
      IIOImage frame = reader.readAll(i, null);
      list.add((BufferedImage) frame.getRenderedImage());
    }
    reader.dispose();
    return list;
  }

  private static boolean checkGifFormat(ImageReader reader) {
    String metaFormat = reader.getOriginatingProvider().getNativeImageMetadataFormatName();
    String name;
    try {
      name = reader.getFormatName();
    } catch (IOException ex) {
      name = "";
    }
    return "gif".equalsIgnoreCase(name) && "javax_imageio_gif_image_1.0".equals(metaFormat);
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(MainPanel::createAndShowGui);
  }

  private static void createAndShowGui() {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
    }
    JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

@@ -246,24 +246,51 @@
 .util.List;%0A
+import java.util.Optional;%0A
 import java.
@@ -316,16 +316,16 @@
 upport;%0A
-
 import j
@@ -585,36 +585,97 @@
 ));%0A    
-URL url = getClass()
+ClassLoader cl = Thread.currentThread().getContextClassLoader();%0A    URL url = cl
 .getReso
@@ -672,32 +672,40 @@
 cl.getResource(%22
+example/
 duke.running.gif
@@ -716,73 +716,171 @@
     
-JLabel label = new JLabel();%0A    label.setIcon(new ImageIcon(url)
+Icon icon = Optional.ofNullable(url).%3CIcon%3Emap(ImageIcon::new)%0A        .orElseGet(() -%3E UIManager.getIcon(%22html.missingImage%22));%0A    JLabel label = new JLabel(icon
 );%0A 
@@ -1601,24 +1601,49 @@
 ream(is)) %7B%0A
+    if (url != null) %7B%0A  
     try (Ima
@@ -1720,16 +1720,18 @@
 %7B%0A      
+ 
+ 
 loadFrom
@@ -1807,24 +1807,26 @@
 ::add);%0A    
+  
 %7D catch (IOE
@@ -1832,32 +1832,34 @@
 Exception ex) %7B%0A
+  
       ex.printSt
@@ -1872,24 +1872,26 @@
 ce();%0A      
+  
 label.setTex
@@ -1902,32 +1902,40 @@
 .getMessage());%0A
+      %7D%0A
     %7D%0A    add(la

argument 'getClass().getResource(...)' might be null