Вопрос

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

Другие советы

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!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top