ImageIO.write bmp 不起作用

Posted

技术标签:

【中文标题】ImageIO.write bmp 不起作用【英文标题】:ImageIO.write bmp does not work 【发布时间】:2013-09-23 10:25:33 【问题描述】:

我正在尝试以 bmp 格式保存图像,但它不会创建任何文件。 如果我改用“png”,一切正常。 有什么想法吗?

//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() 给了我“jpg”、“bmp”、“jpeg”和其他一些..

提前致谢。

雅各布

【问题讨论】:

“不起作用”到底是什么意思?您是否收到任何错误消息?而且您的“代码”不太可能真正起作用,因为您必须转义反斜杠。 @chrylis 反斜杠被转义了,它只是没有在问题中显示(当您不将其格式化为代码时会发生这种情况)。 "does not work"表示我使用"bmp"格式时没有创建文件。 write 返回一个boolean,你应该检查一下。 简短的回答是:TYPE_INT_ARGB 不起作用,但 TYPE_INT_RGB 起作用。 【参考方案1】:

我刚刚完成了一个类似问题的调试,我想我会在这里展示我的推理,尽管 Jakob 已经使用 PNG 格式。

首先,始终检查ImageIO.write(...)的返回值。如果找不到合适的作者,它将返回 false,这就是 Jakob 尝试将其写为位图时应该发生的情况。当文件的实际图像格式与“格式名称”参数中给出的内容不匹配时,就会发生这种情况。在这种情况下不会抛出异常。在http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#write(java.awt.image.RenderedImage, java.lang.String, java.io.File)查看文档

其次,使用BufferedImage#getType()方法检查BufferedImage对象的图片类型。在http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getType() 查看可能的返回值。例如,如果您从 BufferedImage 对象(表示带有 alpha 组件的 PNG)中获取类型为 TYPE_INT_ARGB,则使用 ImageIO.write(bi, "BMP", new File("D:\\test.bmp")) 将不会成功,并且该方法将返回 false em>,即使您可以在使用ImageIO.getWriterFormatNames() 获得的条目列表中看到 BMP/bmp。您可能需要进行编码并将图像转换为所需的格式。

第三,当遇到这些有时会让人头疼的问题时,使用GIMP 等图像编辑器详细检查您的图像属性总是有帮助的。

@Green 箭头,一个小提示...您可以使用“bmp”或“BMP”作为图像格式值。这同样适用于其他格式。没关系。

【讨论】:

好答案:此外(对我来说是完成),指向永远有用的 mkyong 的链接显示了如何转换图像mkyong.com/java/convert-png-to-jpeg-image-file-in-java。这也适用于 bmps。【参考方案2】:

正如@bincob 所说,如果 write 返回 false,您可以像这样重绘源图像

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

然后你又可以写了。

【讨论】:

您的代码中有一个错误(“newBufferedImage”的最后一次出现应该是“bufferedImage”)。否则,很好的答案!在此处将其添加到我的语言中:tinybrain.de/1004274 这应该是选择的答案。 我在使用 JPEG 文件时遇到了同样的问题,我认为是因为我试图通过让图像的白色部分透明来节省内存,这就是为什么只有 PNG 有效。【参考方案3】:

没有尝试,但我认为格式实际上应该是“BMP”而不是“bmp”。 请尝试

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

看看会发生什么。

我们看不到你的 bi 是如何构建的。

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

encodingType 是否设置正确?

我认为您的 bi 已损坏,这对我来说非常有用。

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

【讨论】:

图像类型为 BufferedImage.TYPE_INT_ARGB。这适用于 png 文件类型。我现在已经尝试了 BufferedImage.TYPE_INT_RGB,现在实际上创建了一个 BMP 文件。但是全黑..使用BufferedImage.TYPE_INT_RGB时PNG文件中的图像也是黑色的。 用 type_int_ARGB 和 "BMP" 代替 "bmp" 怎么样? 当使用 BMP 而不是 bmp(和 BufferedImage.TYPE_INT_ARGB)时,不会创建文件(也不例外)。 PNG文件创建正常。 使用 BMP 和 BufferedImage.TYPE_INT_RGB 时会创建一个 .bmp 文件,但它全是黑色的。仍然可以正常创建PNG文件。 我现在不能尝试。今晚试试,告诉你我发现了什么。我认为这是一个编码问题。您可以尝试使用全白图像和不同的编码类型来查看发生了什么【参考方案4】:

使用BufferedImage.TYPE_INT_RGB 编码适用于“gif”、“png”、“tif”以及“jpg”和“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();
    

【讨论】:

【参考方案5】:

老了,但 BMP 偶尔仍然有用,而且最重要的答案是最好的解决方案:自己做。这样它就适用于任何类型的位图。

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

【讨论】:

以上是关于ImageIO.write bmp 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

多维动态数组,为啥不起作用?

UITableViewCell 样式字幕多行不起作用

Hibernate HQL Count Distinct 不起作用?

react-bootstrap:模态的 dialogClassName 道具不起作用

@font-face 在 Firefox 中不起作用 [重复]

swift - 从 var(UITextField 输入)中删除空格不起作用