Reputation: 1277
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
Upvotes: 17
Views: 16597
Reputation: 919
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.
Upvotes: 27
Reputation: 1669
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);
}
Upvotes: 0
Reputation: 18792
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();
}
}
Upvotes: 1
Reputation: 790
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.
Upvotes: 9
Reputation: 329
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());
}
Upvotes: 0