借鉴淘宝的架构
图片尺寸输出采用原图压缩输出
采用:GraphicsMagick+im4java
测试博文:http://yunduxiaocheng-gmail-com.iteye.com/blog/919457
http://my.oschina.net/lidonghao/blog/90188
GraphicsMagick下载地址:
http://www.graphicsmagick.org/
im4java下载地址:
http://sourceforge.net/projects/im4java/files/
package com.wokejia.util; import java.io.IOException; import java.util.ArrayList; import org.im4java.core.CompositeCmd; import org.im4java.core.ConvertCmd; import org.im4java.core.IM4JavaException; import org.im4java.core.IMOperation; import org.im4java.core.IdentifyCmd; import org.im4java.process.ArrayListOutputConsumer; public class Magick { /** * 居中切割图片(不支持gif图片切割) 1、如果源图宽高都小于目标宽高,则只压缩图片,不做切割 * 2、如果源图宽高都大于目标宽度,则根据宽度等比压缩后再居中切割 3、其它条件下,则压缩图片(不做缩放)后再居中切割 * * 该方法在知道源图宽度(sw)和高度(sh)的情况下使用 * * @param srcPath * 源图路径 * @param desPath * 切割图片保存路径 * @param sw * 源图宽度 * @param sh * 源图高度 * @param dw * 切割目标宽度 * @param dh * 切割目标高度 * @throws Exception */ public void cropImage(String srcPath, String desPath, int sw, int sh, int dw, int dh) throws Exception { if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) return; IMOperation op = new IMOperation(); op.addImage(srcPath); if ((sw <= dw) && (sh <= dh)) // 如果源图宽度和高度都小于目标宽高,则仅仅压缩图片 { op.resize(sw, sh); } if ((sw <= dw) && (sh > dh))// 如果源图宽度小于目标宽度,并且源图高度大于目标高度 { op.resize(sw, sh); // 压缩图片 op.append().crop(sw, dh, 0, (sh - dh) / 2);// 切割图片 } if ((sw > dw) && (sh <= dh))// 如果源宽度大于目标宽度,并且源高度小于目标高度 { op.resize(sw, sh); op.append().crop(dw, sh, (sw - dw) / 2, 0); } if (sw > dw && sh > dh) // 如果源图宽、高都大于目标宽高 { float ratiow = (float) dw / sw; // 宽度压缩比 float ratioh = (float) dh / sh; // 高度压缩比 if (ratiow >= ratioh) // 宽度压缩比小(等)于高度压缩比(是宽小于高的图片) { int ch = (int) (ratiow * sh); // 压缩后的图片高度 op.resize(dw, null); // 按目标宽度压缩图片 op.append().crop(dw, dh, 0, (ch > dh) ? ((ch - dh) / 2) : 0); // 根据高度居中切割压缩后的图片 } else // (宽大于高的图片) { int cw = (int) (ratioh * sw); // 压缩后的图片宽度 op.resize(cw, null); // 按计算的宽度进行压缩 op.append().crop(dw, dh, (cw > dw) ? ((cw - dw) / 2) : 0, 0); // 根据宽度居中切割压缩后的图片 } } op.addImage(desPath); ConvertCmd convert = new ConvertCmd(true); convert.run(op); } /** * * 根据坐标裁剪图片 * * @param srcPath 要裁剪图片的路径 * @param newPath 裁剪图片后的路径 * @param x 起始横坐标 * @param y 起始挫坐标 * @param x1 结束横坐标 * @param y1 结束挫坐标 */ public static void cutImage(String srcPath, String newPath, int x, int y, int x1, int y1) throws Exception { int width = x1 - x; int height = y1 - y; IMOperation op = new IMOperation(); op.addImage(srcPath); /** * width: 裁剪的宽度 * height:裁剪的高度 * x: 裁剪的横坐标 * y: 裁剪的挫坐标 */ op.crop(width, height, x, y); op.addImage(newPath); ConvertCmd convert = new ConvertCmd(); // linux下不要设置此值,不然会报错 convert.run(op); } /** * * 根据尺寸缩放图片 * @param width 缩放后的图片宽度 * @param height 缩放后的图片高度 * @param srcPath 源图片路径 * @param newPath 缩放后图片的路径 */ public static void cutImage(int width, int height, String srcPath, String newPath) throws Exception { IMOperation op = new IMOperation(); op.addImage(srcPath); op.resize(width, height); op.addImage(newPath); ConvertCmd convert = new ConvertCmd(); convert.run(op); } /** * 根据宽度缩放图片 * * @param width 缩放后的图片宽度 * @param srcPath 源图片路径 * @param newPath 缩放后图片的路径 */ public static void cutImage(int width, String srcPath, String newPath) throws Exception { IMOperation op = new IMOperation(); op.addImage(srcPath); op.resize(width, null); op.addImage(newPath); ConvertCmd convert = new ConvertCmd(); convert.run(op); } /** * 给图片加水印 * @param srcPath 源图片路径 */ public static void addImgText(String srcPath) throws Exception { IMOperation op = new IMOperation(); op.font("宋体").gravity("southeast").pointsize(18).fill("#BCBFC8").draw("text 5,5 juziku.com"); op.addImage(); op.addImage(); ConvertCmd convert = new ConvertCmd(); convert.run(op, srcPath, srcPath); } /** * 图片信息 * * @param imagePath * @return */ public static String getImageInfo(String imagePath) { String line = null; try { IMOperation op = new IMOperation(); op.format("width:%w,height:%h,path:%d%f,size:%b%[EXIF:DateTimeOriginal]"); op.addImage(1); IdentifyCmd identifyCmd = new IdentifyCmd(true); ArrayListOutputConsumer output = new ArrayListOutputConsumer(); identifyCmd.setOutputConsumer(output); identifyCmd.run(op, imagePath); ArrayList<String> cmdOutput = output.getOutput(); assert cmdOutput.size() == 1; line = cmdOutput.get(0); } catch (Exception e) { e.printStackTrace(); } return line; } /** * 根据尺寸缩放图片[等比例缩放:参数height为null,按宽度缩放比例缩放;参数width为null,按高度缩放比例缩放] * * @param imagePath * 源图片路径 * @param newPath * 处理后图片路径 * @param width * 缩放后的图片宽度 * @param height * 缩放后的图片高度 * @return 返回true说明缩放成功,否则失败 */ public 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) { System.out.println("文件读取错误!"); flag = false; } catch (InterruptedException e) { flag = false; } catch (IM4JavaException e) { flag = false; } finally { } return flag; } /** * 图片旋转 * * @param imagePath * 源图片路径 * @param newPath * 处理后图片路径 * @param degree * 旋转角度 */ public 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) { flag = false; System.out.println("图片旋转失败!"); } return flag; } /** * 根据尺寸缩放图片 * @param width 缩放后的图片宽度 * @param height 缩放后的图片高度 * @param srcPath 源图片路径 * @param newPath 缩放后图片的路径 */ public static void zoomImage(Integer width, Integer height, String srcPath, String newPath) throws Exception { IMOperation op = new IMOperation(); op.addImage(srcPath); if(width == null){//根据高度缩放图片 op.resize(null, height); }else if(height == null){//根据宽度缩放图片 op.resize(width, null); }else { op.resize(width, height); } op.addImage(newPath); ConvertCmd convert = new ConvertCmd(true); convert.run(op); } /** * 给图片加水印 * @param srcPath 源图片路径 */ public static void addImgText(String srcPath,String content) throws Exception { IMOperation op = new IMOperation(); op.font("微软雅黑"); op.gravity("southeast"); op.pointsize(18).fill("#BCBFC8").draw("text 0,0 "+content); //("x1 x2 x3 x4") x1 格式,x2 x轴距离 x3 y轴距离 x4名称 op.addImage(); op.addImage(); ConvertCmd convert = new ConvertCmd(true); try { convert.run(op,srcPath,srcPath); } catch (Exception e) { e.printStackTrace(); } } /** * 图片水印 * * @param srcImagePath 源图片 * @param waterImagePath 水印 * @param destImagePath 生成图片 * @param gravity 图片位置 * @param dissolve 水印透明度 */ public static void waterMark(String waterImagePath, String srcImagePath, String destImagePath, String gravity, int dissolve) { IMOperation op = new IMOperation(); op.gravity(gravity); op.dissolve(dissolve); op.addImage(waterImagePath); op.addImage(srcImagePath); op.addImage(destImagePath); CompositeCmd cmd = new CompositeCmd(true); try { cmd.run(op); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IM4JavaException e) { e.printStackTrace(); } } /** * 图片信息 * * @param imagePath * @return */ public static String showImageInfo(String imagePath) { String line = null; try { IMOperation op = new IMOperation(); op.format("width:%w,height:%h,path:%d%f,size:%b%[EXIF:DateTimeOriginal]"); op.addImage(1); IdentifyCmd identifyCmd = new IdentifyCmd(true); ArrayListOutputConsumer output = new ArrayListOutputConsumer(); identifyCmd.setOutputConsumer(output); identifyCmd.run(op, imagePath); ArrayList<String> cmdOutput = output.getOutput(); assert cmdOutput.size() == 1; line = cmdOutput.get(0); } catch (Exception e) { e.printStackTrace(); } return line; } /** * 图片合成 * @param args * @param maxWidth * @param maxHeight * @param newpath * @param mrg * @param type 1:横,2:竖 */ public static void montage(String[] args,Integer maxWidth,Integer maxHeight,String newpath,Integer mrg,String type) { IMOperation op = new IMOperation(); ConvertCmd cmd = new ConvertCmd(true); String thumb_size = maxWidth+"x"+maxHeight+"^"; String extent = maxWidth+"x"+maxHeight; if("1".equals(type)){ op.addRawArgs("+append"); }else if("2".equals(type)){ op.addRawArgs("-append"); } op.addRawArgs("-thumbnail",thumb_size); op.addRawArgs("-gravity","center"); op.addRawArgs("-extent",extent); Integer border_w = maxWidth / 40; op.addRawArgs("-border",border_w+"x"+border_w); op.addRawArgs("-bordercolor","#ccc"); op.addRawArgs("-border",1+"x"+1); op.addRawArgs("-bordercolor","#fff"); for(String img : args){ op.addImage(img); } if("1".equals(type)){ Integer whole_width = ((mrg / 2) +1 + border_w + maxWidth + border_w + (mrg / 2) +1)*args.length - mrg; Integer whole_height = maxHeight + border_w + 1; op.addRawArgs("-extent",whole_width + "x" +whole_height); }else if("2".equals(type)){ Integer whole_width = maxWidth + border_w + 1; Integer whole_height = ((mrg / 2) +1 + border_w + maxHeight + border_w + (mrg / 2) +1)*args.length - mrg; op.addRawArgs("-extent",whole_width + "x" +whole_height); } op.addImage(newpath); try { cmd.run(op); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { String f1 = "F:\\226\\aa.jpg"; String f2 = "F:\\226\\bb\\imgupload.png"; String f3 = "F:\\226\\bb\\imgupload2.png"; waterMark(f2, f1, f3, "southeast", 70); // Magick magick = new Magick(); // String[] files = new String[5]; // files[0] = f1; // files[1] = f2; // montage(files, 280, 200, f3, 0,"1"); } }