我正在尝试用Java编写图像优化软件。第一个也是最明显的一步是删除EXIF元数据,这是我成功完成的。我还尝试使用ImageIO和压缩质量参数压缩图像,如下所示:
filepath=chosen.getCanonicalPath()+"-temp.jpg";
file=new File(filepath);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
if (!writers.hasNext()){
throw new IllegalStateException("No writers found");
}
OutputStream os = new FileOutputStream(file);
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.9f);
writer.write(null, new IIOImage(optimized, null, null), param);
然而,这真的不是很好。当源图像是不同的格式(即不是jpeg)时它可以正常工作,但是当从jpeg压缩到jpeg时,它有时甚至会使文件大小更大。
www.tinyjpg.com等网站声称(并且确实)通过 没有质量损失 <将xpeg图像的文件大小减少 40%-60% / strong>即可。他们究竟是如何做到的(程序上和程序上)?他们删除了哪些类型的数据,如何在不丢失质量的情况下删除这些数据?这是我可以用Java实现的吗?
非常感谢您给我的任何指导和/或资源!
答案 0 :(得分:2)
在JPEG中,有三个可优化的步骤:
组件的相对抽样。一个以低于Y分量的速率对Cb或Cr组分进行采样。平滑Cb和Cr值,使1,2,4,8或16像素共享相同的Cb或Cr值(官方说,JPEG也支持分数采样率,但大多数解码器不支持它们)。如果使用4:1:1的采样率,则会将要压缩的数据量减少一半。
(最大且最难做的)选择优化的量化表。
生成优化的霍夫曼表(很容易做到,但很多编码器都没有)。
答案 1 :(得分:1)
从Wikipedia - JPG - Lossless further compression我猜想Tiny JPG一直在使用在大多数标准工具创建之后开发的改进算法。改进的算法在PackJPG中实现,这是方便的开源。似乎没有Java实现。
作为旁注:PackJPG声称提高了20%,而Tiny JPG声称提高了70%。这可能是多报,但你可能想要测试这两种说法。
答案 2 :(得分:1)
有一个开源库可实现无损JPEG优化。它称为SlimJPG,您可以在此处找到更多信息:https://github.com/Fewlaps/slim-jpg
要使用它,您只需要这样命名即可:
SlimJpg.file(yourImage).optimize();
yourImage
可以是byte[]
,InputStream
或File
。
免责声明:我是委员之一...:·)