如何使java的ImageBuffer正确读取PNG文件?
由于某些原因,使用 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)
解决方案?
还有另一个我可以一起使用的库吗?
For some reason, opening up some PNG files using ImageBuffer and ImageIO does not work. Here's some code I am using that works fine for resizing/cropping JPGs:
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;
The goal of this function is to take whatever type is given, resize and crop the image, and then save it to PNG with the same filename.
It works on Windows, but if I crop/resize on Linux (lenny), it crashes altogether and complains about the type of the file (it says the type is 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)
Solutions?
Is there another library I can use altogether?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 Windows 上运行我的函数时,croppedImaged.getType() 返回值 5。因此,简单的“hack”就是存储类型,检查它是否为 0...如果是,则手动将值设置为 5 。
然后我们传入imageType,它应该可以在 Linux 上运行。
我确信这有一个缺点,如果在其他情况下该值为 0,它会将其设置为 5,这是错误的。然而,这似乎适用于 Linux 上的常见图像类型,并且没有引起任何问题。
很明显,Windows 版本的 Java 1.6 完全没问题,但 Linux 版本有一个错误。
When running my function on Windows, croppedImaged.getType() returns the value 5. So, the simple "hack" is to store the type, check to see if it's 0... and if it is, set the value to 5 manually.
We then pass in imageType instead and it should work on Linux.
I am sure this has the drawback that if the value is 0 in other cases, it will set it to 5 and that will be wrong. However, this seems to work for common image types on Linux and it hasn't caused any problems.
It's pretty clear that the Windows version of Java 1.6 is perfectly fine, but the Linux version has a bug in it.
egervari,您可以使用像 imgscalr (Apache 2 )为您“正确”地进行所有大小调整,以修复诸如此类的问题 非常简单的 API - 它不会帮助裁剪,但调整大小是它最擅长的(不同的速度、质量,如果需要的话甚至可以抗锯齿)。
我想指出的是,您现在使用的代码(将 CUSTOM 类型强制转换为 3BYTE_BGR 类型)还应该考虑带有 Alpha 通道的入站图像。
另外,如果您想继续使用自定义代码,RGB 和 ARGB 是 Java2D 中支持最好的两种图像类型 - 如果您使用支持较差的图像类型,当 Java2D 执行图像操作时,它会回退到其软件渲染管线并且不使用专门的硬件加速管线。这不仅会影响性能,因为您会发现结果实际上看起来更糟(例如,在 GIF 中您经常看到这种情况)。
再说一次,如果你想尝试一下,imgscalr 会自动为你处理所有这些事情,但如果你不想尝试,我想我会提醒你,以防你遇到一些令人头疼的问题。
java图像处理是...喜怒无常:)
egervari, you can use a library like imgscalr (Apache 2) to do all the resizing for you "properly" that fixes issues like these with a very simple API -- it won't help with the cropping, but the resizing is what it does best (different speeds, qualities, even anti-aliasing if you want).
I would point out that the code you are using now (forcing a CUSTOM type into a 3BYTE_BGR type) should also account for inbound images with an alpha channel.
Also if you want to keep using your custom code, RGB and ARGB are two of the best supported image types in Java2D -- if you use a poorly supported image type, when Java2D goes to perform the image op, it falls back to its software rendering pipeline and doesn't use the specialized hardware accelerated ones. This doesn't just effect performance as you'll see the result actually look worse (e.g. in GIF You see this a lot).
Again, imgscalr takes care of all this for you automatically if you wanted to give it a try, but if not, I figured I'd just give a heads up incase you were running into some of these headaches.
java image processing is... temperamental :)
解决方法是先将文件转换为 jpeg,然后再对其进行处理。 0 型错误似乎主要影响 PNG 图像。
A workaround solution would be to convert the file to jpeg first, and then process it. The type 0 bug seems to mostly affect PNG images.