簡單介紹 前端
GraphicsMagick是ImageMagick的一個分支,相對於ImageMagick而言,TA處理速度更快,消耗資源更少。GraphicsMagick 是一個用來讀寫、生成超過90種圖像格式的工具集合,支持包括 TIFF, JPEG, JPEG-2000,PNG, PDF, PhotoCD, SVG, 和GIF 等圖像格式。GraphicsMagick 是基於 ImageMagick 開發的。 java
im4java是ImageMagick的另外一個Java開源接口。與JMagick不一樣之處在於im4java只是生成與ImageMagick相對應的命令行,而後將生成的命令行傳至選中的IM-command(使用java.lang.ProcessBuilder.start()實現)來執行相應的操做。它支持大部分ImageMagick命令,能夠針對不一樣組的圖片屢次複用同一個命令行。im4java也是可以高清壓縮圖片,並且它也特別強大,至少一些基本常見的業務都是能夠完美實現的。 git
Cropper是一款使用簡單且功能強大的圖片剪裁jQuery插件。該圖片剪裁插件支持圖片放大縮小,支持鼠標滾輪操做,支持圖片旋轉,支持觸摸屏設備,支持canvas,而且支持跨瀏覽器使用。
github
技術選型 web
ImageCropper + GraphicsMagick + im4java + SpringMVC
ImageCropper官網: http://fengyuanchen.github.io/cropper/
GraphicsMagick官網: http://www.graphicsmagick.org/
im4java下載: http://sourceforge.net/projects/im4java/files/?source=navbar
處理邏輯
一、前端進行圖片剪裁,並展現剪裁後的效果圖;
二、點擊肯定後,將參數(x,y座標,長寬,旋轉角度)傳到後端,並將圖片上傳至服務器,在調用im4java api進行圖片處理。
三、返回處理後的圖片路徑,前端展現。
spring
編程實現
apache
圖片剪裁處理類 編程
package org.hcm.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.im4java.core.ConvertCmd; import org.im4java.core.IM4JavaException; import org.im4java.core.IMOperation; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; public class ImageUtils { private static Log logger = LogFactory.getLog(ImageUtils.class); /** * 保存文件 * * @param inputStream * @param path * @param fileName */ public static void saveFileFromInputStream(InputStream inputStream, String path, String fileName) { File file = new File(path + fileName); FileOutputStream fs = null; try { fs = new FileOutputStream(file); byte[] buffer = new byte[1024 * 1024]; int byteread = 0; while ((byteread = inputStream.read(buffer)) != -1) { fs.write(buffer, 0, byteread); fs.flush(); } } catch (FileNotFoundException e) { logger.error("File Not Found !", e); } catch (IOException e) { logger.error("", e); } finally { try { if (fs != null) { fs.close(); } if (inputStream != null) { inputStream.close(); } } catch (IOException e) { logger.error("", e); } } } /** * 裁剪圖片 * * @param imagePath * 源圖片路徑 * @param newPath * 處理後圖片路徑 * @param x * 起始X座標 * @param y * 起始Y座標 * @param width * 裁剪寬度 * @param height * 裁剪高度 * @return 返回true說明裁剪成功,不然失敗 */ public static boolean cutImage(String imagePath, String newPath, int x, int y, int width, int height) { boolean flag = false; try { IMOperation op = new IMOperation(); op.addImage(imagePath); /** width:裁剪的寬度 * height:裁剪的高度 * x:裁剪的橫座標 * y:裁剪縱座標 */ op.crop(width, height, x, y); op.addImage(newPath); ConvertCmd convert = new ConvertCmd(true); convert.run(op); flag = true; } catch (IOException e) { logger.error("讀取文件出錯", e); } catch (InterruptedException e) { logger.error("", e); } catch (IM4JavaException e) { logger.error("", e); } return flag; } /** * 根據尺寸縮放圖片[等比例縮放:參數height爲null,按寬度縮放比例縮放;參數width爲null,按高度縮放比例縮放] * * @param imagePath * 源圖片路徑 * @param newPath * 處理後圖片路徑 * @param width * 縮放後的圖片寬度 * @param height * 縮放後的圖片高度 * @return 返回true說明縮放成功,不然失敗 */ public static boolean zoomImage(String imagePath, String newPath, Integer width, Integer height) { boolean flag = false; try { IMOperation op = new IMOperation(); op.addImage(imagePath); if (width == null) { // 根據高度縮放圖片 op.resize(null, height); } else if (height == null) { // 根據寬度縮放圖片 op.resize(width); } else { op.resize(width, height); } op.addImage(newPath); ConvertCmd convert = new ConvertCmd(true); convert.run(op); flag = true; } catch (IOException e) { logger.error("讀取文件出錯", e); } catch (InterruptedException e) { logger.error("", e); } catch (IM4JavaException e) { logger.error("", e); } return flag; } /** * 圖片旋轉 * * @param imagePath * 源圖片路徑 * @param newPath * 處理後圖片路徑 * @param degree * 旋轉角度 */ public static boolean rotate(String imagePath, String newPath, double degree) { boolean flag = false; try { // 1.將角度轉換到0-360度之間 degree = degree % 360; if (degree <= 0) { degree = 360 + degree; } IMOperation op = new IMOperation(); op.addImage(imagePath); op.rotate(degree); op.addImage(newPath); ConvertCmd cmd = new ConvertCmd(true); cmd.run(op); flag = true; } catch (Exception e) { logger.error("圖片旋轉處理失敗!", e); } return flag; } public static boolean imgProcessing(String srcPath, String destPath, int x, int y, int width, int height, double rotate) { boolean flag = false; try { IMOperation op = new IMOperation(); op.addImage(srcPath); /** 旋轉 */ op.rotate(rotate); /** width:裁剪的寬度 * height:裁剪的高度 * x:裁剪的橫座標 * y:裁剪縱座標 */ op.crop(width, height, x, y); op.addImage(destPath); ConvertCmd convert = new ConvertCmd(true); convert.run(op); flag = true; } catch (IOException e) { logger.error("讀取文件出錯", e); } catch (InterruptedException e) { logger.error("", e); } catch (IM4JavaException e) { logger.error("", e); } return flag; } public static void main(String[] args) { // ImageUtils.zoomImage("f://temp//test.jpg", "f://temp//test5.jpg", 200, 200); // ImageUtils.rotate("f://temp//test1.jpg", "f://temp//test2.jpg", -90); // ImageUtils.cutImage("f://temp//test5.jpg", "f://temp//test5.jpg", 32, 30, 200, 200); String data = "{'x':100.001, 'y':100.9}"; System.out.println(data); JSONObject jsonData = JSON.parseObject(data); System.out.println(jsonData.getIntValue("x")); System.out.println(jsonData.getIntValue("y")); } }
控制類 json
package org.hcm.controller; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.hcm.utils.ImageUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; @Controller @RequestMapping(value = "/image") public class ImageController { @RequestMapping(value = "/upload", method = RequestMethod.POST) public void upload(HttpServletRequest req, HttpServletResponse resp) throws IOException { Map<String, Object> result = new HashMap<String, Object>(); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) req; MultipartFile file = multipartRequest.getFile("avatar_file"); String data = req.getParameter("avatar_data"); String fileName = String.valueOf(System.currentTimeMillis()) + getExtension(file.getOriginalFilename()); String savePath = req.getServletContext().getRealPath("/upload"); if (!file.isEmpty()) { // 保存原圖 ImageUtils.saveFileFromInputStream(file.getInputStream(), savePath + "\\source\\", fileName); // 處理圖片 result = imageProcessing(data, savePath, fileName, req.getContextPath()); } resp.getWriter().print(JSON.toJSON(result)); } private Map<String, Object> imageProcessing(String data, String savePath, String fileName, String contextPath) { Map<String, Object> map = new HashMap<String, Object>(); JSONObject object = JSONObject.parseObject(data); int x = (int) object.getIntValue("x"); int y = object.getIntValue("y"); int height = object.getIntValue("height"); int width = object.getIntValue("width"); int rotate = object.getIntValue("rotate"); String srcPath = savePath + "\\source\\" + fileName; String destPath = savePath + "\\procesed\\" + fileName; String serverPath = contextPath + "/upload/procesed/" + fileName; ImageUtils.imgProcessing(srcPath, destPath, x, y, width, height, rotate); map.put("state", 200); map.put("result", serverPath); return map; } private String getExtension(String fileName) { if (StringUtils.INDEX_NOT_FOUND == StringUtils.indexOf(fileName, ".")) return StringUtils.EMPTY; String ext = StringUtils.substring(fileName, StringUtils.lastIndexOf(fileName, ".")); return StringUtils.trimToEmpty(ext); } }
效果預覽 canvas
(完)