22

I am uploading images using servlet. To perform resize operations i am converting InputStream to BufferedImage. Now i want to save it in mongoDB. Since, i am new to mongoDB as far as i know, GridFS takes InputStream.

So, is there any way to convert BufferedImage to InputStream?

Sorter
  • 9,704
  • 6
  • 64
  • 74

4 Answers4

25

BufferedImageByteArrayOutputStreambyte[]ByteArrayInputStream

Use the ImageIO.write method to make a BufferedImage (which is a RenderedImage) into a ByteArrayOutputStream. From there get a byte array (byte[]), feeding that into an InputStream of type ByteArrayInputStream.

ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(buffImage, "jpeg", os);                          // Passing: ​(RenderedImage im, String formatName, OutputStream output)
InputStream is = new ByteArrayInputStream(os.toByteArray());

Both the ByteArrayOutputStream and InputStream implement AutoCloseable. So you can conveniently have those closed automatically by using try-with-resources syntax.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Sorter
  • 9,704
  • 6
  • 64
  • 74
  • Tried this, got a compile error on the third line: "The method ByteArrayInputStream(byte[]) is undefined for the type" What does that mean? – Möoz Dec 19 '14 at 00:48
  • Have you made the import correctly. The constructor is correct. http://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html#ByteArrayInputStream(byte[]) – Sorter Dec 19 '14 at 06:38
  • 2
    Doesn't anything need to be closed anywhere? I'm not asking to be mean, I simply dont know ;) – Nicofisi Oct 31 '17 at 18:15
  • Let your IDE do that for you. – Sorter Oct 31 '17 at 18:16
  • @Nicofisi Both `ByteArrayOutputStream` & `InputStream` implement [`AutoCloseable`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/AutoCloseable.html). So you can use [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) syntax to conveniently and automatically close those resources whether or not exceptions are thrown. – Basil Bourque Oct 26 '19 at 18:15
13

First of all you must get your "bytes":

byte[] buffer = ((DataBufferByte)(bufferedImage).getRaster().getDataBuffer()).getData();

And then use ByteArrayInputStream(byte[] buf) constructor to create your InputStream;

Edward83
  • 6,664
  • 14
  • 74
  • 102
12

You need to save the BufferedImage to a ByteArrayOutputStream using the ImageIO class, then create a ByteArrayInputStream from toByteArray().

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 13
    Why is this necessary? Doesn't this load an extra (large) byte array into memory? – djechlin Jun 13 '14 at 16:15
  • 1
    +1. and this method copies the data not once but twice! once when writing to ByteArrayOutputStream and then again by converting it into a byte array when toByteArray() is called. – morpheus May 21 '16 at 00:37
  • You can find the code [below](https://stackoverflow.com/a/21569243/1097600) – Sorter Oct 11 '18 at 14:51
4

By overriding the method toByteArray(), returning the buf itself (not copying), you can avoid memory related problems. This will share the same array, and not creating another of the correct size. The important thing is to use the size() method in order to control the number of valid bytes into the array.

final ByteArrayOutputStream output = new ByteArrayOutputStream() {
    @Override
    public synchronized byte[] toByteArray() {
        return this.buf;
    }
};
ImageIO.write(image, "png", output);
return new ByteArrayInputStream(output.toByteArray(), 0, output.size());
ronalchn
  • 12,225
  • 10
  • 51
  • 61
Igor
  • 129
  • 1
  • 2