ImageIO.write bmp does not work
Asked Answered
T

5

17

I'm trying to save an image in bmp format, but it doesn't create any file. If I use "png" instead, everything works fine. Any ideas?

//This works fine:
ImageIO.write(bi, "png", new File("D:\\MyImage.png"));

//This does not work:
ImageIO.write(bi, "bmp", new File("D:\\MyImage.bmp"));

ImageIO.getWriterFormatNames() gives me "jpg", "bmp", "jpeg" and some others..

Thanks in advance.

Jakob

Tokenism answered 23/9, 2013 at 10:25 Comment(10)
What exactly does "does not work" mean? Are you getting any error messages? And it's unlikely that your "code" will actually work, since you have to escape the backslash.Ethelred
@chrylis The backslash was escaped, it just didn't display as such in the question (which happens when you don't format it as code).Devland
"does not work" means that a file was not created when I used the "bmp" format.Tokenism
- but when I use "png" format, a file is createdTokenism
@JakobMathiasen And it's failing silently? You're not getting any sort of error message?Ethelred
@chrylis Yes, no exception thrown.Tokenism
Looks like #3962187Sophister
write returns a boolean, you should check it.Devland
The short answer is: TYPE_INT_ARGB doesn't work, but TYPE_INT_RGB works.Bencion
@EvgeniSergeev that helped me a lot! could you explain why is that? I am following Oracle tutorial (docs.oracle.com/javase/tutorial/essential/concurrency/…) and I needed to change it to make it workGallopade
R
27

I just finished debugging a similar problem and I thought I will present my reasoning here, although Jakob has gone ahead with the PNG format.

First, always check the return value of ImageIO.write(...). It will return false if no appropriate writer can be found and that's what should have happened when Jakob tried writing it as a bitmap. This happens when the actual image format of the file does not match what is given in the 'format name' argument. No exception is thrown in this case. Check out the docs at https://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#write(java.awt.image.RenderedImage,%20java.lang.String,%20java.io.File)

Second, check the image type of the BufferedImage object by using the BufferedImage#getType() method. Check out the possible return values at https://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getType(). For example, If you get the type as TYPE_INT_ARGB from your BufferedImage object (which represents a PNG with a alpha component) you wont have success using ImageIO.write(bi, "BMP", new File("D:\\test.bmp")) and the method would return false, even though you can see BMP/bmp in the list of entries obtained using ImageIO.getWriterFormatNames(). You might have to work on the encoding and transform your image to the desired format.

Third, when facing such problems which can be a pain sometimes, it always helps to use an image editor such as GIMP to check out your image properties in detail.

@Green arrow, a minor note... you can use either "bmp" or "BMP" as the image format value. The same applies for other formats as well. It does not matter.

Redstone answered 27/2, 2014 at 8:22 Comment(1)
Good answer: in addition (and completion for me), the link to the ever-useful mkyong that shows how to do for converting an image mkyong.com/java/convert-png-to-jpeg-image-file-in-java. That works also with bmps.Payton
E
9

As @bincob says, if write returns false, you can redraw the source image like this

BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(), 
bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);

And then you can write again.

Exemplify answered 7/6, 2016 at 7:14 Comment(3)
There's a bug in your code (last occurrence of "newBufferedImage" should read "bufferedImage"). Otherwise, good answer! Added it to my language here: tinybrain.de/1004274Leonelleonelle
This should be the selected answer.Erroneous
I had the same problem with an JPEG file, the reason I think is because I tried to save memory by leaving the white parts of the image transparent and that's why only PNG worked.Demure
E
1

Using BufferedImage.TYPE_INT_RGB encoding works for "gif","png","tif" as well as "jpg" and "bmp":

static void saveBufferedImageToFileTest(){

    String[] types = new String[] {"gif","png","tif","jpg","bmp"};

    //JPEG and BMP needs BufferedImage.TYPE_INT_RGB. See https://mkyong.com/java/convert-png-to-jpeg-image-file-in-java/
    //BufferedImage.TYPE_INT_RGB for all `types`
    int biType = BufferedImage.TYPE_INT_RGB;   // BufferedImage.TYPE_INT_ARGB does not work for "bmp" and "jpeg"
    BufferedImage bi = new BufferedImage(200 ,200, biType);
    Graphics g = bi.getGraphics();
    g.fillRect(50, 50, 100,  100);
    g.dispose();

    try {
        for(String type : types){
            boolean success = ImageIO.write(bi,type,new File("test_image."+type));
            System.out.println(type + (success ?  " file created" : " file NOT created") );
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}
Extragalactic answered 14/1, 2021 at 6:43 Comment(0)
P
0

didn't try but I think the format should be "BMP" and not "bmp" actually. Please try with

ImageIO.write(bi, "BMP", new File("D:\\MyImage.bmp"));

and see what happens.

We can't see how your bi is build.

BufferedImage bufferedImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);

Is the encodingType is set properly ?

I think your bi is corrupted, that's work perfectly for me.

BufferedImage bi = new BufferedImage(50,50,BufferedImage.TYPE_INT_RGB);
Graphics gd = bi.getGraphics();
gd.drawRect(0, 0, 10, 10);      
try {
    ImageIO.write(bi, "BMP", new File("C:\\test.bmp"));
    ImageIO.write(bi, "PNG", new File("C:\\test.png"));
} catch (IOException e) {
    System.out.println("error "+e.getMessage());
}
Presage answered 23/9, 2013 at 10:45 Comment(7)
The imagetype is BufferedImage.TYPE_INT_ARGB. This works for the png file type. I have now tried the BufferedImage.TYPE_INT_RGB, and now a BMP file is actually created. But its all black.. The image in the PNG file is also black when using the BufferedImage.TYPE_INT_RGB.Tokenism
What about using type_int_ARGB and "BMP" instead of "bmp" ?Presage
When using BMP instead of bmp (and BufferedImage.TYPE_INT_ARGB) no file is created (and no exception). The PNG file is created ok.Tokenism
When using BMP and BufferedImage.TYPE_INT_RGB a .bmp file is created but its all black. still The PNG file is created ok.Tokenism
I can't try now. gonna try tonight and tell you what I've found. I think it's an encoding problem. you can try with a full white image and different encoding type to see what's happeingPresage
Did you finally fix it with my edit ? don't forget bmp = no transparency, maybe you're drawing in black on black.Presage
Green Arrow:Sorry my late answer. We did not go further with the bitmap. We acceptet the .png file solution. Thanks for your effort.Tokenism
F
0

An oldie, but BMPs are still useful occasionally and the answers above all skirt the best solution: do it yourself. That way it works for any type of bitmap.

static void writeBMP(BufferedImage image, File f) throws IOException {
    OutputStream out = new BufferedOutputStream(new FileOutputStream(f));
    int width = image.getWidth();
    int height = image.getHeight();
    int row = (width * 3 + 3) / 4 * 4;
    out.write('B');
    out.write('M');
    writeInt(out, 14 + 40 + row * height);  // file size
    writeInt(out, 0); 
    writeInt(out, 14 + 40);        // bitmap offset
    writeInt(out, 40);             // size
    writeInt(out, width);          // width
    writeInt(out, height);         // weight
    writeInt(out, (24<<16) | 1);   // planes, bpp
    writeInt(out, 0);              // compression
    writeInt(out, row * height);   // bitmap size
    writeInt(out, 0);              // resx
    writeInt(out, 0);              // resy
    writeInt(out, 0);              // used colors
    writeInt(out, 0);              // important colors
    for (int y=height-1;y>=0;y--) {
        for (int x=0;x<width;x++) {
            int rgba = image.getRGB(x, y); 
            out.write(rgba & 0xFF); // b
            out.write(rgba >> 8);   // g
            out.write(rgba >> 16);  // r
        }   
        for (int x=width*3;x%4!=0;x++) { // pad to 4 bytes
            out.write(0);
        }   
    }   
    out.close();
}   
private static void writeInt(OutputStream out, int v) throws IOException {
    out.write(v);
    out.write(v >> 8);
    out.write(v >> 16);
    out.write(v >> 24);
}   
Firebird answered 11/1, 2022 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.