9

I'm making a program, which gets data about an image in byte array from a server. I'm converting this data into 24bit BMP format (whether its jpeg, png, bmp or 8-24-32bpp). First, I'm saving it to my HD, and then I'm loading it into a JLabel's Icon. Works perfectly, though there are some cases in which I get the following exception:

java.io.EOFException at
javax.imageio.stream.ImageInputStreamImpl.readFully(ImageInputStreamImpl.java:353) at
com.sun.imageio.plugins.bmp.BMPImageReader.read24Bit(BMPImageReader.java:1188) at
com.sun.imageio.plugins.bmp.BMPImageReader.read(BMPImageReader.java:843) at
javax.imageio.ImageIO.read(ImageIO.java:1448) at 
javax.imageio.ImageIO.read(ImageIO.java:1308)

For this line (the second)

File imgFile = new File("d:/image.bmp");
BufferedImage image = ImageIO.read(imgFile);

In these cases:

  • the image does not load into the JLabel, but it can be found on my HD
  • the conversion is not proper, because something "slips"
  • the picture is like when you use italics in a word document

First, i thought maybe the bpp is the problem, then i thought that maybe the pictures are too large, but i have cases it works and cases it doesn't for both suggestions. I'm a little stuck here, and would be glad for ideas.

micheal65536
  • 558
  • 3
  • 6
  • 26
bajla
  • 163
  • 2
  • 2
  • 12
  • 1
    Did you created that images? All i can think of is that they are created with some format of BMP that ImageIO doesn't support. Maybe if you tried to edit images and save them again. – Piro Aug 06 '13 at 12:35
  • 1
    I think the issue is that some pictures doesn't have EOF bytes and that's why you're getting `java.io.EOFException`. I've experienced the same issue with `jpeg` format. It makes sense if you consider file's metadata have info about file's lenght and consequently EOF wouldn't be necessary. This fact explains why your files can be found in your HD (and even can be opened I guess) but you get exception in java. – dic19 Aug 06 '13 at 12:41
  • 1
    Check [this](http://stackoverflow.com/questions/12288813/exception-java-awt-color-cmmexception-invalid-image-format-thrown-when-resizi/16858161#16858161) link, there's an explanation of my experience working with `jpeg` images that I hope be helpful. – dic19 Aug 06 '13 at 12:45
  • @dic19 thanks for the idea! yes, it can be opened, but not with imageIO. Your solution howewer couldn't solve my problem, but it is useful, because now i know, that those files, which i got the exception on, does not have the mentioned EOF bytes. Another thing, I switched the system.arraycopy line in your code to arrays.copyof , because i got an error for the arguments. – bajla Aug 07 '13 at 09:36
  • @Piro: yes, i've created them, the server gives RGB values data. I create the images with Philipp C. Heckel's bitmapencoder (copyright) i modified it a little bit – bajla Aug 07 '13 at 09:39
  • Can you open the problematic BMPs in other image editing software? Also, can you post a link to a "broken" BMP? Maybe you could try using ImageIO to write the images instead of using bitmapencoder? I'm thinking the problem could be in the conversion/writing to BMP rather than reading. – Harald K Aug 07 '13 at 11:25
  • @bajla you're wellcome :D `System.arrayCopy` I used is for `Java ME` (which is different in `Java SE`). Also `Java ME` doesn´t have Collections API implementation (which is a headache) and that's why I didn't use `Arrays.copy`. Sure you'll have to find properly EOF bytes to `bmp` format to solve your problem since my post is about `jpeg` format, but now you're moving on in the right way I guess :D – dic19 Aug 07 '13 at 12:03
  • @haraldK : yes, i can open it, thats how i see it's slipped (irfanview) and i had to use some encoder, because imageIO could not support my byte array, and make an image out of it :) – bajla Aug 07 '13 at 19:18

3 Answers3

7
  • the picture is like .. when You use italics in a word document

Think I finally got what this bullet item meant now.. ;-)

Speculative answer, but here goes:

If the image you write looks "skewed", it's probably due to missing padding for each column as the BMP format specifies (or incorrect width field in the BMP header). I assume then, that the images you get EOF exceptions for, is where the width is not a multiple of 4.

Try to write the BMPs using ImageIO to see if that helps:

private static BufferedImage createRGBImage(byte[] bytes, int width, int height) {
    DataBufferByte buffer = new DataBufferByte(bytes, bytes.length);
    ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{8, 8, 8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
    return new BufferedImage(cm, Raster.createInterleavedRaster(buffer, width, height, width * 3, 3, new int[]{0, 1, 2}, null), false, null);
}

...

byte[] bytes = ...; // Your image bytes
OutputStream stream = ...; // Your output

BufferedImage image = createRGBImage(bytes, width, height);

try {
    ImageIO.write(image, "BMP", stream);
}
finally {
    stream.close();
}
Harald K
  • 26,314
  • 7
  • 65
  • 111
  • you are genius, the problematic images have width 618, 2671, 598 ... all the others' width is a multiple of 4. – bajla Aug 07 '13 at 19:34
  • 1
    @bajla Cool. I updated the answer now, with code to convert RGB bytes to `BufferedImage`. You can use that, unless you figured out how to correctly pad your image data (from what I could understand, Philipp C. Heckel's original code did it correctly, but I only skimmed through it). – Harald K Aug 08 '13 at 08:03
  • Sir, this is the absolute winner solution! thanks for the update. I really appreciate it! This way the image displaying is faster, and now it works in all cases! :) :) – bajla Aug 12 '13 at 06:57
2

Call it by class name, liek ClassName.byteArrayToImage(byte):

public static BufferedImage  byteArrayToImage(byte[] bytes){  
        BufferedImage bufferedImage=null;
        try {
            InputStream inputStream = new ByteArrayInputStream(bytes);
            bufferedImage = ImageIO.read(inputStream);
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
        return bufferedImage;
}
Azad
  • 5,047
  • 20
  • 38
0

You can use this code to convert the output image to a byte Array

   Blob b = rs.getBlob(2);
   byte barr[] = new byte[(int)b.length()]; //create empty array
   barr = b.getBytes(1,(int)b.length());

   FileOutputStream fout = new FileOutputStream("D:\\sonoo.jpg");
   fout.write(barr);
DeanMWake
  • 893
  • 3
  • 19
  • 38
Mohsin Shaikh
  • 494
  • 1
  • 4
  • 11