市面上常用的压缩技术选型
技术 | 性能 | 可靠性 | 可维护性 | 活跃度 | 总分 |
JDK Image IO | 7 | 1 | 6 | 2 | 16 |
ImageMagick | 2 | 7 | 3 | 5 | 17 |
GraphicsMagick | 10 | 8 | 6 | 5 | 29 |
结论:
- JDK Image IO 有一个非常明显的问题是,在处理大图片时,很容易在内存中存在很多大对象而导致OOM
- ImageMagick 性能着实不容乐观
- GraphicsMagick 从 ImageMagick 中派生出来,在稳定性和性能上都更加优秀
- 首先安装GraphicsMagick.exe软件,根据提示直接Next安装即可
- 在项目中导入im4java依赖
<dependency>
<groupId>org.im4java</groupId>
<artifactId>im4java</artifactId>
<version>1.4.0</version>
</dependency>
- 把压缩图片帮助类放到工具类中
package com.glyphbit.baiduocr;
import org.im4java.core.ConvertCmd;
import org.im4java.core.IM4JavaException;
import org.im4java.core.IMOperation;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
public class ImageCompressionUtils {
/**
* 获取图像的原始尺寸(宽度和高度)
*
* @param filePath 图像文件的路径
* @return int[] 包含两个元素的数组,第一个元素是宽度,第二个元素是高度
* @throws IOException 如果文件无法打开或读取时抛出异常
*/
public static int[] getImgSize(String filePath) throws IOException {
// 初始化一个长度为2的数组用于存储图像的宽度和高度
int[] size = new int[2];
// 使用ImageIO创建一个ImageInputStream对象,该对象可以从给定的文件路径中读取图像数据
try (ImageInputStream input = ImageIO.createImageInputStream(new File(filePath))) {
// 如果无法创建ImageInputStream,则抛出IOException异常
if (input == null) {
throw new IOException("File cannot be opened!");
}
// 获取能够读取输入流的所有ImageReader迭代器
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
// 从迭代器中获取第一个可用的ImageReader实例
ImageReader reader = readers.next();
try {
// 设置ImageReader的输入源,并指示是否忽略元数据
reader.setInput(input, true);
// 获取最小索引处的图像宽度和高度
int width = reader.getWidth(reader.getMinIndex());
int height = reader.getHeight(reader.getMinIndex());
// 将宽度和高度分别赋值给size数组的第一个和第二个元素
size[0] = width;
size[1] = height;
} finally {
// 确保在任何情况下都会调用reader.dispose()来释放资源
reader.dispose();
}
}
// 返回包含图像宽度和高度的数组
return size;
}
/**
* 根据尺寸缩放图片[等比例缩放:参数height为null,按宽度缩放比例缩放;参数width为null,按高度缩放比例缩放]
*
* @param imagePath 源图片路径
* @param newPath 处理后图片路径
* @param quality 压缩质量(0-100)数值越大,缩略图越清晰
* @throws InterruptedException the interrupted exception
* @throws IOException the io exception
* @throws IM4JavaException the im 4 java exception
*/
public static void zoomImage(String imagePath, String newPath, Double quality) {
// 定义变量用于存储图像宽度和高度
int[] targetImgSize = null;
try {
// 获取图像原始尺寸
targetImgSize = getImgSize(imagePath);
} catch (IOException e) {
e.printStackTrace();
}
int w = targetImgSize[0];
int h = targetImgSize[1];
IMOperation op = new IMOperation();
op.addImage(imagePath);
// 使用原始尺寸进行调整
op.resize(w, h);
if (quality != null) {
op.quality(quality);
}
op.addImage(newPath);
ConvertCmd convert = new ConvertCmd(true);
String osName = System.getProperty("os.name").toLowerCase();
try {
if (osName.contains("win")) {
// Windows下设置GraphicsMagick的安装路径
convert.setSearchPath("C:\\Program Files\\GraphicsMagick-1.3.45-Q8");
}
// 执行转换操作
convert.run(op);
} catch (IOException | InterruptedException | IM4JavaException e) {
e.printStackTrace();
}
}
}