IM4Java + GraphicsMagick 實現高清圖片剪裁處理

簡單介紹 前端

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




(完)

相關文章
相關標籤/搜索