Java ImageWriter BufferedImage to GIF

I hope you guys can help me with this one. I'm not sure if it is a bug in Java or if I'm doing something wrong, but I'll go with the latter.

I want to turn a BufferedImage into a GIF image. I then wish to keep the GIF in the memory in the form of a byte array. (I do not want to save the file to disk)

The program should capture a screen segment (just to create a quick image) and turn it into a GIF byte array using ImageIO ImageWriter and ByteArrayOutputStream.

The code below will show you the bug. The program will crash and give an ArrayIndexOutOfBoundsException and the array remains empty. If you replace the "gif" with "png" it will work just fine, hence my confusion. Also! If I save the image to a file on disk with

write.setOutput(ImageIO.createImageOutputStream(new FileOutputStream(new File("C:/Image.gif")));

it will save it to a .gif file correctly.

So my question is, what did I do wrong in this patch of code? Any help will be greatly appreciated! :)

Note: This is not an animated GIF, no transparency involved either.

    String format = "gif";
    Robot r = null;
    try {
        r = new Robot();
    } catch (AWTException e1) {
        e1.printStackTrace();
    }
    BufferedImage screen = r.createScreenCapture(new Rectangle(512,512));
    final BufferedImage gif = new BufferedImage(512,512,BufferedImage.TYPE_BYTE_INDEXED);
    Graphics2D g = gif.createGraphics();
    g.drawImage(screen,0,0,null);
    g.dispose();
    ImageWriter write = ImageIO.getImageWritersBySuffix(format).next();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        write.setOutput(ImageIO.createImageOutputStream(out));
        write.write(gif);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    for(int i=0; i < 10; i++) {
        System.out.println(out.toByteArray()[i]);
    }

Answers


It seems there is some strange (if not plainly buggy) implementation of stream bufferings in com.sun.imageio.plugins.gif.*. If you don't flush or close explicitly the ImageOutputStream, the contents doesn't get flushed, even after closing the underlying stream. Change

 write.setOutput(ImageIO.createImageOutputStream(out));
 write.write(gif);

to

   ImageOutputStream imageos = ImageIO.createImageOutputStream(out);
   write.setOutput(imageos);
   write.write(gif);
   imageos.close();  // or imageos.flush();

U have to use a ByteArrayOutputStream to get image as bytes. To write to this ByteArrayOutputStream, you should wrap it with an ImageOutputStream.

ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("gif").next();
//got imagewriter for gif
ImageWriteParam gifWriteParam = jpgWriter.getDefaultWriteParam();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios=ImageIO.createImageOutputStream(baos);
jpgWriter.setOutput(ios);
jpgWriter.write(null,new IIOImage(myBufferedImageObject, null, null),gifWriteParam);
baos.flush();
byte[] buf= baos.toByteArray();//got as bytes here

Hope this helps!


Need Your Help

How to set href to some value if I have <a id='view.php'>

javascript jquery

I need to get time in miliseconds and attach that on like get parameter on 'view.php'. How to set href to that value ( href='view.php?time=x) if I have &lt;a id='view.php'&gt; using JQuery ?

How to Add/Remove views efficiently?

android view add removechild

I have an application which shows a list of items with details. When the user selects the item, the app shows the extra detail. I created two Views which extend RelativeLayout, one for listView and...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.