【问题标题】:How do I make java's ImageBuffer to read a PNG file correctly?如何使 java Image Buffer 正确读取 PNG 文件?
【发布时间】:2011-08-15 17:17:41
【问题描述】:

由于某种原因,使用 ImageBuffer 和 ImageIO 打开一些 PNG 文件不起作用。这是我正在使用的一些代码,可以很好地调整/裁剪 JPG 的大小:

BufferedImage image = ImageIO.read(new File(location));

BufferedImage croppedImage = image.getSubimage(
    cropInfo.getX(), cropInfo.getY(), cropInfo.getW(), cropInfo.getH());

BufferedImage resizedImage = new BufferedImage(
    TARGET_WIDTH, TARGET_HEIGHT, croppedImage.getType());
Graphics2D g = resizedImage.createGraphics();
g.drawImage(croppedImage, 0, 0, TARGET_WIDTH, TARGET_HEIGHT, null);
g.dispose();

this.changeContentType("image/png", ".png"); // not really relevant. just a property

ImageIO.write(resizedImage, "png", new File(location));

return resizedImage;

此函数的目标是采用给定的任何类型,调整大小并裁剪图像,然后将其保存为具有相同文件名的 PNG。

它适用于 Windows,但如果我在 Linux (lenny) 上裁剪/调整大小,它会完全崩溃并抱怨文件的类型(它说类型为 0)。

java.lang.IllegalArgumentException: Unknown image type 0
    java.awt.image.BufferedImage.<init>(BufferedImage.java:490)
    trainingdividend.domain.file.ServerImage.resizeImage(ServerImage.java:68)
    trainingdividend.domain.file.ServerImage.cropAndResize(ServerImage.java:80)
    trainingdividend.service.user.UserAccountManagerImpl.cropAvatar(UserAccountManagerImpl.java:155)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

解决方案?

还有其他库我可以完全使用吗?

【问题讨论】:

  • 你在 Linux 中使用的是哪个 JVM? (编辑:根据堆栈跟踪中的 sun.reflect 判断,这是 Sun 的,但可以肯定的是)
  • 是的,最新的sun jvm。 1.6_24
  • 好吧,我修好了。如果 image.getType() == 0,我在其中放置了一个 hack,我手动将其设置为 5。这行得通。
  • FWIW,我刚刚在 windows (jvm 1.6.0_20) 上编译完你的代码,它在随机 jpg 上运行良好。我想知道它是否可能是您的输入文件。
  • 不,此代码适用于所有 Windows。它只是在升级了 jdk 的 Debian (lenny) 上不起作用。我只是检查类型是否为 0,如果是,我传入 5。这似乎使它工作。我的猜测是这是一个错误,与我完全无关:(

标签: java image image-processing resize crop


【解决方案1】:

在 Windows 上运行我的函数时,croppedImaged.getType() 返回值 5。所以,简单的“hack”是存储类型,检查它是否为 0...如果是,设置值手动设置为 5。

int imageType = croppedImage.getType();
if(imageType == 0) imageType = 5;

然后我们传入 imageType,它应该可以在 Linux 上运行。

我确信这有一个缺点,如果在其他情况下该值为 0,它会将其设置为 5,那将是错误的。但是,这似乎适用于 Linux 上的常见图像类型,并且没有造成任何问题。

很明显,Windows 版本的 Java 1.6 完美无缺,但 Linux 版本存在错误。

【讨论】:

    【解决方案2】:

    egervari,您可以使用像 imgscalr (Apache 2) 这样的库来“正确”地为您调整大小,从而使用 very simple API 解决此类问题——它对裁剪没有帮助,但是调整大小是它最擅长的(不同的速度、质量,甚至可以根据需要进行抗锯齿)。

    我要指出的是,您现在使用的代码(将 CUSTOM 类型强制为 3BYTE_BGR 类型)还应考虑具有 alpha 通道的入站图像。

    此外,如果您想继续使用您的自定义代码,RGB 和 ARGB 是 Java2D 中受支持最好的两种图像类型——如果您使用支持不佳的图像类型,当 Java2D 执行图像操作时,它会回退到它的软件渲染管道,并且不使用专门的硬件加速管道。这不仅会影响性能,因为您会看到结果实际上看起来更糟(例如,在 GIF 中您经常看到这种情况)。

    同样,如果您想尝试一下,imgscalr 会自动为您处理这一切,但如果没有,我想我会提醒您,以防您遇到这些问题。

    java 图像处理是...气质:)

    【讨论】:

      【解决方案3】:

      解决方法是先将文件转换为 jpeg,然后再对其进行处理。 0 型错误似乎主要影响 PNG 图像。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-15
        • 2014-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多