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]);
}
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();