当前位置: 首页 > 面试题库 >

为什么ImageIO不能读取BMP文件,直到在MS Paint中将其重新保存?

施选
2023-03-14
问题内容

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

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

谁能启发我为什么一个图像可以与我的代码一起使用,而另一个图像却不能呢?

图像文件:

  • test3.bmp

  • test3_resaved.bmp

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

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

}

问题答案:

(扩大我的评论)

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

ImageIO.getReaderFileSuffixes();

受Java支持。

但这不是应该被理解/理解的方式,因为那根本不是它的工作方式。

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

正确: “ ImageIO无法读取以不属于这些格式之一的格式编码的图像”

但是,这对出现在该列表中的格式有何说明?好吧,这很棘手。

例如,该列表通常返回“ PNG”和“ BMP”(以及其他格式)。但是没有“一个” PNG和“一个” BMP。明天我可以使用一种“有效的”
PNG(子)格式,该格式会很好,但是那里没有任何一个PNG解码器可以解码(必须经过验证和接受:但是一旦被接受,它将“破坏所有现有的PNG解码器)。幸运的是,对于PNG图片来说,问题还算不错。

BMP格式非常复杂。您是否可以进行压缩(这可以解释您所看到的文件大小的变化)。您可以具有各种标题(长度不同,也可以解释您看到的不同文件大小)。哎呀,BMP实际上是如此复杂,以至于您可以将PNG编码的像素嵌入BMP“外壳”中。

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

  • 创建Java解码器后出现的BMP变体
  • BMP变体非常模糊,以至于Java ImageIO实现者认为它不值得支持

“错误”在于认为存在一种PNG或一种BMP格式。两种格式(以及其他图像格式)实际上都是“可扩展的”。每当出现新的变体时,它就有可能破坏 任何
解码器。

所以您的情况是这样的:

  1. 您正在从MS Paint中读取原始BMP文件,并且MS Paint能够读取该文件,因为它恰好是MS Paint能够识别的BMP格式。

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

  3. 当您重新保存从MS该文件画图,你在一个BMP格式,绝对是节省 一样的原始格式(该变的文件大小为相当告诉)

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

现在实际解决您的问题:以我的经验,像 ImageMagick 这样的图像库比默认的Java ImageIO API能够读取更多的图片,因此我将看看
ImageMagick 周围的其他图像库或包装器。

这些库通常也进行更新以支持更新的变体和格式,比Java快得多。例如,来自Google 的惊人 WebP
格式(无损+半透明图像的PNG格式提高了28%至34%)已经得到了很多图像处理库的支持,但是在执行 ImageIO 时我并不屏息
。阅读(someWebPpicture)

另一种选择是使用PNG:即使理论上可以扩展PNG,您也不太可能在野外找到“不受支持的” PNG。对于BMP,这太普遍了。



 类似资料:
  • 问题内容: 我正在编写我的第一个烧瓶应用程序。我正在处理文件上传,基本上我想要的是读取上传文件的数据/内容而不保存它,然后将其打印在结果页面上。是的,我假设用户始终上传一个文本文件。 这是我正在使用的简单上传功能: 现在,我正在保存文件,但是我需要的是一个’a’变量来包含文件的内容/数据。 问题答案: 包含字段。该对象必须扩展IO或文件对象,因此它必须包含read和其他类似方法。还扩展了strea

  • 下面是我的文本文件: 这是我的代码片段: 我得到以下异常: 我该怎么办?

  • 问题内容: 我的内存中有一个位图,我需要将其保存在bmp文件中(使用bmp文件格式)。 有什么办法可以在Android上实现吗? (我读了很多建议使用png格式的文章-这是无损的-但这不是我所需要的:我真的需要 bmp格式 )。 我已经有一些代码使用Bitmap.compress方法将其保存为jpeg或png : 问题答案: (我在回答自己的问题) 这是我目前的解决方案。它是从以下来源派生的:ht

  • 根据API,Java的ImageIO为方法。 其中两种方法是: Oracle教程网站使用readfrom file方法。然而,我已经看到了许多由程序员编码的例子,这里更喜欢使用URL方法。 Exmaple: 我的问题是:如果我只是为Java桌面应用程序(而不是Java小程序)编写代码。与其他方法相比,使用URL方法是否有显著优势? 注意:在SO:usingurl或File(在ImageIO.rea

  • 根据这本在线书籍,C#中的关键字不能防止重排序写操作后跟读操作。它给出了这个例子,其中和最终都可以设置为,尽管和是: 这似乎符合10.5.3中的规范: 对易失性字段的读取称为易失性读取。易失性读取具有“获取语义”;也就是说,在指令序列中,它保证发生在对内存的任何引用之前,而对内存的任何引用发生在它之后。 对易失性字段的写入称为易失性写入。易失性写入具有“释放语义”;也就是说,它保证在指令序列中写入

  • 问题内容: 我试图将ArrayList添加到Jlist,但我给出的唯一理解是编写这样的代码: 让我感到困惑的是,为什么我不能像这样直接将ArrayList直接添加到Jlist中: 提前致谢。 问题答案: 包含“ helper”构造函数的目的是使使用简单数据结构更加容易。 的(和许多Swing组件)实际上是指与提供实际数据视图模型中使用。 原始设计可以追溯到将Swing纳入主库之前(在JDK 1.3