简单介绍
GraphicsMagick是ImageMagick的一个分支,相对于ImageMagick而言,TA处理速度更快,消耗资源更少。GraphicsMagick 是一个用来读写、生成超过90种图像格式的工具集合,支持包括 TIFF, JPEG, JPEG-2000,PNG, PDF, PhotoCD, SVG, 和GIF 等图像格式。GraphicsMagick 是基于 ImageMagick 开发的。
im4java是ImageMagick的另一个Java开源接口。与JMagick不同之处在于im4java只是生成与ImageMagick相对应的命令行,然后将生成的命令行传至选中的IM-command(使用java.lang.ProcessBuilder.start()实现)来执行相应的操作。它支持大部分ImageMagick命令,可以针对不同组的图片多次复用同一个命令行。im4java也是能够高清压缩图片,而且它也特别强大,至少一些基本常见的业务都是可以完美实现的。
Cropper是一款使用简单且功能强大的图片剪裁jQuery插件。该图片剪裁插件支持图片放大缩小,支持鼠标滚轮操作,支持图片旋转,支持触摸屏设备,支持canvas,并且支持跨浏览器使用。
技术选型
ImageCropper + GraphicsMagick + im4java + SpringMVC
ImageCropper官网: http://fengyuanchen.github.io/cropper/
GraphicsMagick官网: http://www.graphicsmagick.org/
im4java下载: http://sourceforge.net/projects/im4java/files/?source=navbar
处理逻辑
1、前端进行图片剪裁,并展示剪裁后的效果图;
2、点击确定后,将参数(x,y坐标,长宽,旋转角度)传到后端,并将图片上传至服务器,在调用im4java api进行图片处理。
3、返回处理后的图片路径,前端展示。
编程实现
图片剪裁处理类
1package org.hcm.utils; 2 3import java.io.File; 4import java.io.FileNotFoundException; 5import java.io.FileOutputStream; 6import java.io.IOException; 7import java.io.InputStream; 8 9import org.apache.commons.logging.Log; 10import org.apache.commons.logging.LogFactory; 11import org.im4java.core.ConvertCmd; 12import org.im4java.core.IM4JavaException; 13import org.im4java.core.IMOperation; 14 15import com.alibaba.fastjson.JSON; 16import com.alibaba.fastjson.JSONObject; 17 18 19public class ImageUtils { 20 21 private static Log logger = LogFactory.getLog(ImageUtils.class); 22 23 /** 24 * 保存文件 25 * 26 * @param inputStream 27 * @param path 28 * @param fileName 29 */ 30 public static void saveFileFromInputStream(InputStream inputStream, String path, String fileName) { 31 File file = new File(path + fileName); 32 FileOutputStream fs = null; 33 try { 34 fs = new FileOutputStream(file); 35 byte[] buffer = new byte[1024 * 1024]; 36 int byteread = 0; 37 while ((byteread = inputStream.read(buffer)) != -1) { 38 fs.write(buffer, 0, byteread); 39 fs.flush(); 40 } 41 } catch (FileNotFoundException e) { 42 logger.error("File Not Found !", e); 43 } catch (IOException e) { 44 logger.error("", e); 45 } finally { 46 try { 47 if (fs != null) { 48 fs.close(); 49 } 50 if (inputStream != null) { 51 inputStream.close(); 52 } 53 } catch (IOException e) { 54 logger.error("", e); 55 } 56 } 57 } 58 59 60 /** 61 * 裁剪图片 62 * 63 * @param imagePath 64 * 源图片路径 65 * @param newPath 66 * 处理后图片路径 67 * @param x 68 * 起始X坐标 69 * @param y 70 * 起始Y坐标 71 * @param width 72 * 裁剪宽度 73 * @param height 74 * 裁剪高度 75 * @return 返回true说明裁剪成功,否则失败 76 */ 77 public static boolean cutImage(String imagePath, String newPath, int x, int y, int width, int height) { 78 boolean flag = false; 79 try { 80 IMOperation op = new IMOperation(); 81 op.addImage(imagePath); 82 /** width:裁剪的宽度 * height:裁剪的高度 * x:裁剪的横坐标 * y:裁剪纵坐标 */ 83 op.crop(width, height, x, y); 84 op.addImage(newPath); 85 ConvertCmd convert = new ConvertCmd(true); 86 convert.run(op); 87 flag = true; 88 } catch (IOException e) { 89 logger.error("读取文件出错", e); 90 } catch (InterruptedException e) { 91 logger.error("", e); 92 } catch (IM4JavaException e) { 93 logger.error("", e); 94 } 95 96 return flag; 97 } 98 99 /** 100 * 根据尺寸缩放图片[等比例缩放:参数height为null,按宽度缩放比例缩放;参数width为null,按高度缩放比例缩放] 101 * 102 * @param imagePath 103 * 源图片路径 104 * @param newPath 105 * 处理后图片路径 106 * @param width 107 * 缩放后的图片宽度 108 * @param height 109 * 缩放后的图片高度 110 * @return 返回true说明缩放成功,否则失败 111 */ 112 public static boolean zoomImage(String imagePath, String newPath, Integer width, Integer height) { 113 boolean flag = false; 114 try { 115 IMOperation op = new IMOperation(); 116 op.addImage(imagePath); 117 if (width == null) { // 根据高度缩放图片 118 op.resize(null, height); 119 } else if (height == null) { // 根据宽度缩放图片 120 op.resize(width); 121 } else { 122 op.resize(width, height); 123 } 124 op.addImage(newPath); 125 ConvertCmd convert = new ConvertCmd(true); 126 convert.run(op); 127 flag = true; 128 } catch (IOException e) { 129 logger.error("读取文件出错", e); 130 } catch (InterruptedException e) { 131 logger.error("", e); 132 } catch (IM4JavaException e) { 133 logger.error("", e); 134 } 135 136 return flag; 137 } 138 139 /** 140 * 图片旋转 141 * 142 * @param imagePath 143 * 源图片路径 144 * @param newPath 145 * 处理后图片路径 146 * @param degree 147 * 旋转角度 148 */ 149 public static boolean rotate(String imagePath, String newPath, double degree) { 150 boolean flag = false; 151 try { 152 // 1.将角度转换到0-360度之间 153 degree = degree % 360; 154 if (degree <= 0) { 155 degree = 360 + degree; 156 } 157 IMOperation op = new IMOperation(); 158 op.addImage(imagePath); 159 op.rotate(degree); 160 op.addImage(newPath); 161 ConvertCmd cmd = new ConvertCmd(true); 162 cmd.run(op); 163 flag = true; 164 } catch (Exception e) { 165 logger.error("图片旋转处理失败!", e); 166 } 167 168 return flag; 169 } 170 171 172 public static boolean imgProcessing(String srcPath, String destPath, int x, int y, int width, int height, double rotate) { 173 boolean flag = false; 174 try { 175 IMOperation op = new IMOperation(); 176 op.addImage(srcPath); 177 /** 旋转 */ 178 op.rotate(rotate); 179 /** width:裁剪的宽度 * height:裁剪的高度 * x:裁剪的横坐标 * y:裁剪纵坐标 */ 180 op.crop(width, height, x, y); 181 op.addImage(destPath); 182 ConvertCmd convert = new ConvertCmd(true); 183 convert.run(op); 184 flag = true; 185 } catch (IOException e) { 186 logger.error("读取文件出错", e); 187 } catch (InterruptedException e) { 188 logger.error("", e); 189 } catch (IM4JavaException e) { 190 logger.error("", e); 191 } 192 193 return flag; 194 } 195 196 public static void main(String[] args) { 197// ImageUtils.zoomImage("f://temp//test.jpg", "f://temp//test5.jpg", 200, 200); 198// ImageUtils.rotate("f://temp//test1.jpg", "f://temp//test2.jpg", -90); 199// ImageUtils.cutImage("f://temp//test5.jpg", "f://temp//test5.jpg", 32, 30, 200, 200); 200 201 String data = "{'x':100.001, 'y':100.9}"; 202 203 System.out.println(data); 204 205 JSONObject jsonData = JSON.parseObject(data); 206 207 208 209 System.out.println(jsonData.getIntValue("x")); 210 System.out.println(jsonData.getIntValue("y")); 211 212 213 } 214 215}
控制类
1package org.hcm.controller; 2 3import java.io.IOException; 4import java.util.HashMap; 5import java.util.Map; 6 7import javax.servlet.http.HttpServletRequest; 8import javax.servlet.http.HttpServletResponse; 9 10import org.apache.commons.lang.StringUtils; 11import org.hcm.utils.ImageUtils; 12import org.springframework.stereotype.Controller; 13import org.springframework.web.bind.annotation.RequestMapping; 14import org.springframework.web.bind.annotation.RequestMethod; 15import org.springframework.web.multipart.MultipartFile; 16import org.springframework.web.multipart.MultipartHttpServletRequest; 17 18import com.alibaba.fastjson.JSON; 19import com.alibaba.fastjson.JSONObject; 20 21 22@Controller 23@RequestMapping(value = "/image") 24public class ImageController { 25 26 @RequestMapping(value = "/upload", method = RequestMethod.POST) 27 public void upload(HttpServletRequest req, HttpServletResponse resp) throws IOException { 28 Map<String, Object> result = new HashMap<String, Object>(); 29 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) req; 30 MultipartFile file = multipartRequest.getFile("avatar_file"); 31 String data = req.getParameter("avatar_data"); 32 String fileName = String.valueOf(System.currentTimeMillis()) + getExtension(file.getOriginalFilename()); 33 String savePath = req.getServletContext().getRealPath("/upload"); 34 if (!file.isEmpty()) { 35 // 保存原图 36 ImageUtils.saveFileFromInputStream(file.getInputStream(), savePath + "\\source\\", fileName); 37 // 处理图片 38 result = imageProcessing(data, savePath, fileName, req.getContextPath()); 39 } 40 41 resp.getWriter().print(JSON.toJSON(result)); 42 } 43 44 private Map<String, Object> imageProcessing(String data, String savePath, String fileName, String contextPath) { 45 Map<String, Object> map = new HashMap<String, Object>(); 46 JSONObject object = JSONObject.parseObject(data); 47 48 int x = (int) object.getIntValue("x"); 49 int y = object.getIntValue("y"); 50 int height = object.getIntValue("height"); 51 int width = object.getIntValue("width"); 52 int rotate = object.getIntValue("rotate"); 53 54 String srcPath = savePath + "\\source\\" + fileName; 55 String destPath = savePath + "\\procesed\\" + fileName; 56 String serverPath = contextPath + "/upload/procesed/" + fileName; 57 58 ImageUtils.imgProcessing(srcPath, destPath, x, y, width, height, rotate); 59 60 map.put("state", 200); 61 map.put("result", serverPath); 62 return map; 63 64 } 65 66 67 private String getExtension(String fileName) { 68 if (StringUtils.INDEX_NOT_FOUND == StringUtils.indexOf(fileName, ".")) 69 return StringUtils.EMPTY; 70 String ext = StringUtils.substring(fileName, StringUtils.lastIndexOf(fileName, ".")); 71 return StringUtils.trimToEmpty(ext); 72 } 73 74}
效果预览
_
_

(完)