2

I'm working on a project and the goal is to have all images read with ImageIO. This seems to work for everything except GIF images (which display as a static image of the initial frame). I have seen other answers on Stack Overflow and from a thread on the Oracle forums but most require using Java's File class which I can't access due to the program's SecurityManager. I've been able to break the GIF down into an Image array and edit the metadata, but after stitching everything back together I can only display a single image.

Below is a SSCCE for the program:

import java.awt.Image;
import java.awt.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GifRenderer {

  public static void main(String[] args) throws Exception {
    Image image = null;
    byte[] imageByteArray = null;

    try {
      String location = "http://i.imgur.com/Ejh5gJa.gif";
      imageByteArray = createByteArray(location);

      // This works, but I'm trying to use ImageIO
      //image = Toolkit.getDefaultToolkit().createImage(imageByteArray);

      InputStream in = new ByteArrayInputStream(imageByteArray);
      image = ImageIO.read(in);
    } catch (IOException e) {
      e.printStackTrace();
    }

    JFrame frame = new JFrame();
    frame.setSize(300, 300);
    JLabel label = new JLabel(new ImageIcon(image));
    frame.add(label);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  // Constraint:  This method simulates how the image is originally received
  private static byte[] createByteArray(String urlString) throws IOException {
    URL url = new URL(urlString);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    InputStream is = null;
    try {
      is = url.openStream ();
      byte[] byteChunk = new byte[4096];
      int n;
      while ( (n = is.read(byteChunk)) > 0 ) {
        baos.write(byteChunk, 0, n);
      }
    } catch (IOException e) {
      e.printStackTrace ();
    } finally {
      if (is != null) { is.close(); }
    }
    return baos.toByteArray();
  }

}

Some constraints worth mentioning that might not be clear:

  • The image is originally received as a byte array
  • The image should be read by ImageIO
  • The final result should be an Image object
  • The File class can't be accessed

Given these constraints is there still a way to use ImageIO to display the GIF the same way Toolkit.getDefaultToolkit().createImage() would display the image?

Community
  • 1
  • 1
apicellaj
  • 233
  • 1
  • 3
  • 16
  • ImageIO doesn't really support this, you can load the individual frames using something like [this](http://stackoverflow.com/questions/8933893/convert-each-animated-gif-frame-to-a-separate-bufferedimage), t then you become responsible for the animation. Nb createImageInputStream can accept a InputStream (it ignore even accept a URL, but I'd need to verify that with the docs). ImageIcon and a JLabel should do the trick – MadProgrammer Mar 17 '16 at 08:00
  • 2
    If you're really determined (and just a little crazy) you also do something like [this](http://stackoverflow.com/questions/22188940/gif-image-doesnt-moves-on-adding-it-to-the-jtabbed-pane/22190844#22190844) – MadProgrammer Mar 17 '16 at 08:02
  • While ImageIO is great for a lot of things, displaying a GIF animation clearly isn't one of them. Really impressive work there by @MadProgrammer actually making it work. :-) – Harald K Mar 17 '16 at 09:25
  • I had a feeling ImageIO didn't support proper GIF rendering under such constraints (if at all). The current program architecture might make animating the individual frames quite difficult, but at least it's an option. Thanks for the replies. – apicellaj Mar 17 '16 at 14:38

0 Answers0