入门
支持很多种图片格式。
先去官网下载安装包安装到自己的电脑上面, 如果是服务器使用, 让服务器安装。
引入依赖:
我采用的gradle
implementation ‘org.im4java:im4java:1.4.0’
编写工具类
public class ImageMagickHandler {
private final String imageMagickPath;
public ImageMagickHandler(String imageMagickPath){
this.imageMagickPath = imageMagickPath;
}
@Getter
enum CommandType {
convert("转换处理"),composite("图片合成"),identify("图片信息");
private final String des;
CommandType(String des) {
this.des = des;
}
}
@Getter
public enum GravityType{
northwest("左上","TOP_START"),west("左侧居中","CENTER_START"),southwest("左下","BOTTOM_START"),
north("顶部居中","TOP"),center("居中","CENTER"),south("底部居中","BOTTOM"),
northeast("右上","TOP_END"),east("右侧居中","CENTER_END"),southeast("右下","BOTTOM_END");
private final String des;
private final String name;
GravityType(String des,String name) {
this.des = des;
this.name = name;
}
public static GravityType getInfo(String name){
for (GravityType gravityType : values()) {
if(gravityType.getName().equals(name)){
return gravityType;
}
}
return null;
}
}
@Data
@ToString
public static class ImageInfo{
private Integer width;
private Integer height;
private String path;
private Integer quality;
private String size;
private String format;
private Integer frames;
public ImageInfo(Integer width, Integer height, String path, Integer quality, String size, String format,Integer frames) {
this.width = width;
this.height = height;
this.path = path;
this.quality = quality;
this.size = size;
this.format = format;
this.frames = frames;
}
}
private ImageCommand getImageCommand(CommandType commandType){
ImageCommand convertCmd = null;
switch (commandType){
case convert:
convertCmd =new ConvertCmd();
break;
case composite:
convertCmd =new CompositeCmd();
break;
case identify:
convertCmd =new IdentifyCmd();
break;
}
//windows 需要, linux不需要
if(ObjectUtil.isNotEmpty(convertCmd)){
if(ObjectUtil.isNotEmpty(this.imageMagickPath)){
convertCmd.setSearchPath(this.imageMagickPath);
}
}
return convertCmd;
}
/****
* 获取图片信息
* @param imagePath 原图地址
* @return 返回图片信息
*/
public ImageInfo getImageInfo(String imagePath) {
ImageInfo imageInfo = null;
try {
IMOperation op = new IMOperation();
op.format(",%w,%h,%d/%f,%Q,%B,%e");
op.addImage(imagePath);
ImageCommand identifyCmd = getImageCommand(CommandType.identify);//注意这里,用的是identify
ArrayListOutputConsumer output = new ArrayListOutputConsumer();
identifyCmd.setOutputConsumer(output);
identifyCmd.run(op);
ArrayList<String> cmdOutput = output.getOutput();
String[] result = cmdOutput.get(0).split(",");
if (result.length >= 7) {
String path=result[3];
int frames=0;
for (String s : result) {
if(path.equals(s)){
frames++;
}
}
imageInfo= new ImageInfo(Integer.parseInt(result[1]),
Integer.parseInt(result[2]),
result[3],
Integer.parseInt(result[4]),
result[5],
result[6],
frames);
}
} catch (Exception e) {
log.error("获取图片信息异常:{}", e);
}
return imageInfo;
}
/***
* 仅支持 jpeg,jpg,png,以及静态的webp
* 水印图片-不支持动态图片 比如gif,webp,
* 不支持psd,tiff,svg,ico
* @param srcImagePath 原图
* @param newImagePath 生成水印的新图
* @param appendImagePath 水印图
* @param gravityType 位置
* @param horizontalMargin 横向边距
* @param longitudinalMargin 纵向边距
* @param size 水印大小
* @return 成功还是失败
*/
public boolean compositeImage(String srcImagePath, String newImagePath,String appendImagePath,GravityType gravityType,
int horizontalMargin,int longitudinalMargin,int size,int w1, int h1){
try {
IMOperation op = new IMOperation();
/*op.gravity(gravityType.name());
op.compose("plus");
op.geometry(w1, h1,longitudinalMargin,horizontalMargin);
//op.geometry(w1, h1, w-w1-margin, h-h1-margin);
//op.dissolve(dissolve);
op.addImage(appendImagePath);
op.addImage(srcImagePath);
op.addImage(newImagePath);*/
//op.coalesce();
op.addImage(srcImagePath);
//op.alpha("Set");
//op.dither("None");
op.gravity(gravityType.name());
op.geometry(w1, h1,longitudinalMargin,horizontalMargin);
op.addRawArgs("null:",appendImagePath);
//op.draw("'image over "+w1+","+h1+" "+longitudinalMargin+","+horizontalMargin+" \""+appendImagePath+"\"'");
//op.geometry(longitudinalMargin,horizontalMargin);
//op.addImage(appendImagePath);
op.layers("composite");
//op.layers("optimize");//这种模式会降低图片质量
//op.layers("Flatten");//保持质量 会比原图更好
op.addImage(newImagePath);
ImageCommand composite = getImageCommand(CommandType.convert);
composite.run(op);
}catch (Exception e){
log.error("水印失败异常:{}", e);
return false;
}
return true;
}
/**
* 设置图片颜色色彩空间为RGB模式
*
* @param srcImagePath
* @param targetPath
* @return
*/
public boolean colorSpaceRGB(String srcImagePath, String targetPath) {
try {
IMOperation op = new IMOperation();
op.addImage(srcImagePath);
op.colorspace("sRGB");
op.addImage(targetPath);
ImageCommand composite = getImageCommand(CommandType.convert);
composite.run(op);
} catch (Exception e) {
log.error("色彩空间RGB失败异常:{}", e);
return false;
}
return true;
}
/***
* 仅支持 jpeg,jpg,png,以及静态的webp
* 水印图片-不支持动态图片 比如gif,webp,
* 不支持psd,tiff,svg,ico
* @param srcImagePath 原图
* @param newImagePath 生成水印的新图
* @param appendImagePath 水印图
* @param gravityType 位置
* @param horizontalMargin 横向边距
* @param longitudinalMargin 纵向边距
* @param size 水印大小
* @return 成功还是失败
*/
public boolean compositeAnimatedImage(String srcImagePath, String newImagePath,String appendImagePath,GravityType gravityType,
int horizontalMargin,int longitudinalMargin,int size,int w1, int h1){
try {
IMOperation op = new IMOperation();
op.coalesce();
op.addImage(srcImagePath);
op.gravity(gravityType.name());
op.geometry(w1, h1,longitudinalMargin,horizontalMargin);
op.addRawArgs("null:",appendImagePath);
//op.draw("'image over "+w1+","+h1+" "+longitudinalMargin+","+horizontalMargin+" \""+appendImagePath+"\"'");
//op.geometry(longitudinalMargin,horizontalMargin);
//op.addImage(appendImagePath);
op.layers("composite");
op.layers("optimize");
op.addImage(newImagePath);
ImageCommand composite = getImageCommand(CommandType.convert);
composite.run(op);
}catch (Exception e){
log.error("水印失败异常:{}", e);
return false;
}
return true;
}
/****
* 压缩尺寸-支持各种格式不包含动态图片
* @param imagePath 原图地址
* @param newImagePath 新图地址
* @param width 指定宽度
* @return 成功还是失败
*/
public boolean compress(String imagePath,String newImagePath,int width){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
//imOperation.coalesce();
imOperation.resize(width);
imOperation.colorspace("sRGB");
imOperation.layers("coalesce");
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("压缩失败异常:{}", e);
return false;
}
return true;
}
/****
* 压缩尺寸-支持各种格式不包含动态图片
* @param imagePath 原图地址
* @param newImagePath 新图地址
* @param width 指定宽度
* @param width 指定高度
* @return 成功还是失败
*/
public boolean compress(String imagePath,String newImagePath,int width,int height){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
//imOperation.coalesce();
imOperation.resize(width,height);
imOperation.layers("coalesce");
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("压缩失败异常:{}", e);
return false;
}
return true;
}
/****
* 压缩尺寸-支持gif,webp 动态图片
* @param imagePath 原图地址
* @param newImagePath 新图地址
* @param width 指定宽度
* @return 成功还是失败
*/
public boolean compressGifAndWebp(String imagePath,String newImagePath,int width){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
imOperation.coalesce();
imOperation.resize(width);
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("水印失败异常:{}", e);
return false;
}
return true;
}
/***
* 设置图片透明度
* @param imagePath
* @param newImagePath
* @param dissolve
* @return
*/
public boolean opacityImage(String imagePath,String newImagePath,int dissolve){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
imOperation.alpha("set");
imOperation.channel("A");
imOperation.evaluate("set",dissolve+"%");
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("设置透明度失败异常:{}", e);
return false;
}
return true;
}
/***
* 转换图片格式
* @param imagePath 原图片
* @param newImagePath 转换的图片
* @param imageFormat 图片格式
* @return
*/
public boolean convertFormat(String imagePath,String newImagePath,String imageFormat){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
imOperation.quality(100d);
imOperation.addImage(imageFormat);
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("转换图片格式失败异常:{}", e);
return false;
}
return true;
}
/****
* 裁剪
* @param imagePath 原图
* @param newImagePath 新图
* @param x x坐标
* @param y y坐标
* @param width 宽
* @param height 高
* @return 成功还是失败
*/
public boolean crop(String imagePath,String newImagePath,int x,int y,int width,int height){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
imOperation.crop(width,height,x,y);
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("裁剪失败异常:{}", e);
return false;
}
return true;
}
/***
* 格式转换,如果是动态图转png就会生成多张静态图
* @param imagePath 原图
* @param newImagePath 新图
* @return 成功还是失败
*/
public boolean toFormat(String imagePath,String newImagePath){
try {
IMOperation imOperation = new IMOperation();
imOperation.addImage(imagePath);
imOperation.layers("coalesce");
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("格式转换失败异常:{}", e);
return false;
}
return true;
}
/***
* 合并操作
* 用于多张图合成一张图, 常用于水印gif,webp动态图
* @param srcList
* @param newImagePath
* @return
*/
public boolean merge(List<String> srcList,String newImagePath){
try {
IMOperation imOperation = new IMOperation();
imOperation.delay(0);
for (String imagePath : srcList) {
imOperation.addImage(imagePath);
}
imOperation.loop(0);
imOperation.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(imOperation);
}catch (Exception e){
log.error("合并失败异常:{}", e);
return false;
}
return true;
}
/***
* 转32位
* @param srcImagePath
* @param newImagePath
* @return
*/
public boolean to32Bit(String srcImagePath,String newImagePath){
try {
IMOperation op = new IMOperation();
op.addImage(srcImagePath);
op.depth(32);
op.addImage(newImagePath);
ImageCommand convertCmd = getImageCommand(CommandType.convert);
convertCmd.run(op);
}catch (Exception e){
log.error("转32bit失败异常:{}", e);
return false;
}
return true;
}
}
/**
* 设置透明度
* @param path
* @param out
* @param alphaPercentage
*/
public void adjustTransparency(String path,String out, int alphaPercentage) {
try{
BufferedImage image = ImageIO.read(new File(path));
// 计算新的透明度值
float alpha = (float) (alphaPercentage / 100.0);
// 创建一个新的图片,透明度被应用到所有的像素上
int type = image.getType();
if(type==0){
type=BufferedImage.TYPE_INT_ARGB;
}
BufferedImage adjustedImage = new BufferedImage(image.getWidth(), image.getHeight(), type);
Graphics2D g2d = adjustedImage.createGraphics();
// 设置新的透明度
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
// 绘制原始图片
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
ImageIO.write(adjustedImage, "PNG", new File(out));
adjustedImage.flush();
}catch (IOException e){
log.error("图片设置透明度失败异常:{}", e);
throw new BusinessException("图片设置透明度失败", e);
}
}
注意:
1.在使用的时候, window 使用 要配置imagemagick安装地址
2.linux 上面使用不需要配置imagemagick安装地址
3.在处理图片的时候,要看图片的深度位是多少。
4. 图片的色彩空间也要主要, 不然水印的时候,图片会变色
5. 水印的时候, 不用使用-layers optimize,该参数会导致图片质量降低。
6. 需要设置图片透明度, 我没有使用imagemagick的方式。