Gna*_*air 4 java compression jai image-compression javax.imageio
我使用javax.imageio API和JAI来压缩不同类型的图像.它适用于JPEG使用JPEGImageWriter和GIF使用GIFImageWriter.但它不支持PNG压缩,使用PNGImageWriter它会抛出一个异常,比如没有设置压缩类型或"无有效压缩"等等.所以我在下面使用了这个ImageWriterPNG.它工作但图像质量太差.
任何人都可以建议如何使用PNGImageWriterPNG压缩和哪些JAR包含它?
File input = new File("test.png");
InputStream is = new FileInputStream(input);
BufferedImage image = ImageIO.read(is);
File compressedImageFile = new File(input.getName());
OutputStream os =new FileOutputStream(compressedImageFile);
Iterator<ImageWriter>writers =
ImageIO.getImageWritersByFormatName("jpg"); // here "png" does not work
ImageWriter writer = (ImageWriter) writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);
writer.write(null, new IIOImage(image, null, null), param);
Run Code Online (Sandbox Code Playgroud)
似乎com.sun.imageio.plugins.png.PNGImageWriter与JRE捆绑在一起的默认设置不支持设置压缩.这有点令人惊讶,因为格式显然支持压缩.但是,PNGImageWriter 始终写入压缩.
您可以从它使用的源代码中看到:
Deflater def = new Deflater(Deflater.BEST_COMPRESSION);
Run Code Online (Sandbox Code Playgroud)
哪个会给你带来良好但缓慢的压缩效果.它对您来说可能已经足够了,但在某些情况下,使用更快的压缩和更大的文件可能会更好.
要修复代码,以便它可以使用任何格式名称,更改行:
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);
Run Code Online (Sandbox Code Playgroud)
至:
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
// NOTE: Any method named [set|get]Compression.* throws UnsupportedOperationException if false
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);
}
Run Code Online (Sandbox Code Playgroud)
它仍然会写入压缩的PNG.
如果您需要更多地控制PNG压缩,例如设置压缩或使用的过滤器,您需要找到ImageWriter支持它的.当你提到JAI时,我认为CLibPNGImageWriter这是设置压缩的一部分jai-imageio.jar或jai-imageio-tools.jar支持设置压缩.您只需要查看ImageWriters迭代器,看看是否安装了它:
Iterator<ImageWriter>writers = ImageIO.getImageWritersByFormatName("png");
ImageWriter writer = null;
while (writers.hasNext()) {
ImageWriter candidate = writers.next();
if (candidate.getClass().getSimpleName().equals("CLibPNGImageWriter")) {
writer = candidate; // This is the one we want
break;
}
else if (writer == null) {
writer = candidate; // Any writer is better than no writer ;-)
}
}
Run Code Online (Sandbox Code Playgroud)
如果正确ImageWriter,您的代码应该按预期工作.