为什么ImageIO在MS Paint中重新保存之前不会读取BMP文件? [英] Why doesn't ImageIO read a BMP file until it is re-saved in MS Paint?

查看:128
本文介绍了为什么ImageIO在MS Paint中重新保存之前不会读取BMP文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个位图文件, test3.bmp ,我可以使用我测试过的每个图像查看器查看和编辑它。

I have a bitmap file, test3.bmp, which I can view and edit with every image viewer I have tested with.

那就是说,我无法将它读入我的Java应用程序。如果我在MS Paint中编辑BMP,保存它,撤消更改并保存( test3_resaved.bmp ),我有相同的图像,但文件大小不同。不同的文件大小与我无关......我的应用程序可以读取重新保存的文件是什么。

That said, I cannot read it into my Java application. If I edit the BMP in MS Paint, save it, undo the change, and save it (test3_resaved.bmp), I have the same image, but with a different file size. The different file sizes do not concern me... what does, is that my application can read the re-saved file.

任何人都可以告诉我为什么一个图像有效我的代码,但另一个没有?

Could anyone enlighten me on why one image works with my code but the other does not?

图像文件:

test3_resaved.bmp

这是一个最小测试应用程序:

Here is a minimal test application:

package Test;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class Test extends JFrame {
    private ImageIcon imageIcon;

    public Test(String filename) throws IOException {
        super();
        BufferedImage image = javax.imageio.ImageIO.read(new File(filename));
        imageIcon = new ImageIcon(image);
        setVisible(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        repaint();
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        setSize(imageIcon.getIconWidth(), imageIcon.getIconHeight());
        if (imageIcon != null)
            g2d.drawImage(imageIcon.getImage(), 0, 0, this);
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            if (args.length > 0)
                new Test(args[0]);
            else
                System.out.println("usage - specify image filename on command line");
        }
        catch (Throwable t) {
            t.printStackTrace();
        }
    }

}


推荐答案

(扩展我的评论)

问题归结为:人们通常认为格式 由以下命令给出:

The problem boils down to this: people typically believe that the "format" given by the following command:

ImageIO.getReaderFileSuffixes();

但是这不是应该如何阅读/理解,因为它根本不是它的工作原理。

But that's not how it should be read/understood because that is simply not how it works.

错误:ImageIO可以读取任何用这些格式之一编码的文件

正确:ImageIO无法读取使用不属于这些格式的格式编码的图像

但是现在对该列表中出现的格式有什么看法呢?嗯......这很棘手。

But now what does that say about formats appearing in that list? Well... It gets tricky.

例如,该列表通常会返回PNG和BMP(以及其他格式)。但是,没有一个PNG,也没有一个BMP。我明天可以用一个有效的PNG(子)格式来完美,但没有单个PNG解码器可以解码(它必须经过验证和接受:但一旦被接受,它就会破坏 所有现有的PNG解码器都在那里。幸运的是,对于PNG图片,问题并不算太糟糕。

For example that list typically returns both "PNG" and "BMP" (and other formats). But there's not "one" PNG nor "one" BMP. I can come tomorrow with a "valid" PNG (sub)format that would be perfectly fine but that no single PNG decoder out there would decode (it would have to be validated and accepted: but once it would be accepted, it would "break" all the existing PNG decoders out there). Luckily, for the PNG pictures the problem ain't too bad.

BMP格式非常复杂。你可以压缩或不压缩(这可以解释你看到的不同文件大小)。你可以有各种标题(不同的长度,也可以解释你看到的不同文件大小)。哎呀,BMP实际上是如此复杂,我认为你可以将PNG编码的像素嵌入到BMPshell中。

The BMP format is very complicated. You can have compression or not (which may explain the varying file size you've seen). You can have various headers (of differing length, which may also explain the varying file sized you've seen). Heck, BMP is actually so complex that I think that you can embed PNG encoded pixels inside a BMP "shell".

基本上有两种有问题的BMP文件:

There are basically two problematic types of BMP files:


  • 创建Java解码器后出现的BMP变体

  • BMP变体,模糊不清,以便Java ImageIO实现者认为它不值得支持

错误包括认为有一个PNG或一个BMP格式。两种格式(以及其他图像格式)实际上都是可扩展的。每当一个新版本出现时,它就有可能打破那里的任何解码器。

The "error" consists in thinking that there's one PNG or one BMP format. Both formats (and other image formats too) are actually "extensible". An everytime a new variant comes out it has the potential to break any decoder out there.

所以你的情况是这样的:

So what's happening in your case is this:


  1. 您正在从MS Paint读取您的原​​始BMP文件,MS Paint能够读取该文件,因为它恰好是MS Paint理解的BMP格式。

  1. you're reading your original BMP file from MS Paint and MS Paint is able to read that file because it happens to be a BMP format that MS Paint understands.

相同的BMP格式与您正在使用的Java版本不同(希望它在另一个Java中受支持)版本,但我不会指望它)。

that same BMP format is alien to the Java version you're using (there's hope that it will be supported in another Java version but I wouldn't count on it).

当您从MS Paint重新保存该文件时,您将保存为绝对的BMP格式作为原始格式(变化的文件大小非常明确)

when you re-save that file from MS Paint, you're saving in a BMP format that is definitely not the same as the original format (the varying file size being quite a tell)

您的Java版本恰好支持其他格式。

that other format happens to be supported by your version of Java.

现在要真正解决您的问题:根据我的经验, ImageMagick 等图像库能够读取更多内容图片比默认的Java ImageIO API,所以我看看 ImageMagick 周围的其他图像库或包装。

Now to actually solve your problem: in my experience image libraries like ImageMagick are able to read much much more pictures than the default Java ImageIO API so I'd give a look at either other image libraries or wrappers around ImageMagick.

这些库也是通常更新以比Java更快地支持更新的变体和更新的格式。例如,来自谷歌的惊人的 WebP 格式(在无损+半透明图像上比PNG高出28%到34%)已经得到了相当多的图像处理库的支持,但我并没有屏住呼吸。它来做一个 ImageIO.read(someWebPpicture) ...

These libraries are also typically updated to support newer variants and newer formats much faster than Java is. For example the amazing WebP format from Google (up to 28% to 34% better than PNG on lossless+translucent images) is already supported by quite some image manipulation libraries but I'm not holding my breath when it comes to do a ImageIO.read( someWebPpicture)...

另一种选择是使用PNG:尽管理论上PNG可以是延长你不太可能在野外找到不支持的PNG。对于BMP来说,它太常见了。

Another option would be to use PNG: even though theoretically PNG can be extended you're less likely to find "non supported" PNGs in the wild. With BMPs it's all too common.

这篇关于为什么ImageIO在MS Paint中重新保存之前不会读取BMP文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆