一、windows上安装ImageMagick(参考:https://my.oschina.net/roaminlove/blog/96279)
地址:http://ftp.icm.edu.pl/pub/unix/graphics/GraphicsMagick/windows/
关于Q8,Q16(默认),Q32的说明:
Q8表示: 8-bits per pixel quantum
Q16表示:16-bits per pixel quantum
Q32表示:32-bits per pixel quantum
使用16-bit per pixel quantums在处理图片时比8-bit慢15%至50%,并须要更多的内存,处理一张1024x768像素的图片8-bit要使用3.6M内存,16-bit要使用7.2M内存,计算方法是: (5 * Quantum Depth * Rows * Columns) / 8。建议使用8,现在数码相机照的相片,每一种颜色就是8位深,3种颜色就是24位。注意事项:windows下运行,需要配置ImageMagick的安装路径,可用配置文件方式,也可配环境变量“PATH:D:\Program Files\GraphicsMagick-1.3.18-Q8”。
二. Linux下的安装与配置ImageMagick(Centos64、Redhat下测试成功)(参考:http://blog.csdn.net/blackonline/article/details/61195842)
1、查看所需依赖是否安装
yum install -y gcc libpng libjpeg libpng-devel libjpeg-devel ghostscript libtiff libtiff-devel freetype freetype-devel
或:rpm -q libjpeg libjpeg-devel libpng libpng-devel freetype freetype- devel libtiff
2.下载GraphicsMagick
wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.25.tar.gz
3、新建文件夹graphicsMagick,在文件夹内解压GraphicsMagick-1.3.25.tar.gz
tar -zxvf GraphicsMagick-1.3.25.tar.gz
4、编译
./configure --with-quantum-depth=8 --enable-shared
5、安装
make
make install
6、验证
gm -version
7、测试,新建测试文件夹test,在测试文件夹储存一张测试图片testin.jpg,运行如下命名,查看是否成功
gm convert -scale 100x100 testin.jpg testout.jpg
8、常用命令介绍
http://blog.csdn.net/cbbbc/article/details/52175559
http://blog.csdn.net/haima1998/article/details/73951312
三、下载 im4java(参考:http://blog.csdn.net/tangpengtao/article/details/9208047)
地址:http://sourceforge.net/projects/im4java/?source=directory
im4java的思路是通过线程或者进程执行graphicsmagick的命令,它的api只是为了能生成命令,而不是调用graphicsmagick的库。IM4JAVA是同时支持ImageMagick和GraphicsMagick的,这里是bool值,如果为true则使用GM,如果为false支持IM。
四、常用工具类
1.工具类
package img.GraphicsMagick; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.ResourceBundle; import org.apache.commons.lang.SystemUtils; 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 Test1 { public static String imageMagickPath = null; private static boolean is_windows = false; /**获取ImageMagick的路径,获取操作系统是否为WINDOWS*/ static{ // 通过ResourceBundle.getBundle()静态方法来获取,这种方式来获取properties属性文件不需要加.properties后缀名,只需要文件名即可。 ResourceBundle resource = ResourceBundle.getBundle("config"); //src文件夹下的配置文件直接写文件名 imageMagickPath = resource.getString("imageMagickPath"); is_windows = SystemUtils.IS_OS_WINDOWS; } public static int getSize(String imagePath) { int size = 0; FileInputStream inputStream = null; try { inputStream = new FileInputStream(imagePath); size = inputStream.available(); inputStream.close(); inputStream = null; } catch (FileNotFoundException e) { size = 0; System.out.println("文件未找到!"); } catch (IOException e) { size = 0; System.out.println("读取文件大小错误!"); } finally { // 可能异常为关闭输入流,所以需要关闭输入流 if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { System.out.println("关闭文件读入流异常"); } inputStream = null; } } return size; } public static int getWidth(String imagePath) { int line = 0; try { IMOperation op = new IMOperation(); op.format("%w"); // 设置获取宽度参数 op.addImage(1); IdentifyCmd identifyCmd = new IdentifyCmd(true); ArrayListOutputConsumer output = new ArrayListOutputConsumer(); identifyCmd.setOutputConsumer(output); if (is_windows) { identifyCmd.setSearchPath(imageMagickPath); } identifyCmd.run(op, imagePath); ArrayList<String> cmdOutput = output.getOutput(); assert cmdOutput.size() == 1; line = Integer.parseInt(cmdOutput.get(0)); } catch (Exception e) { line = 0; System.out.println("运行指令出错!"+e.toString()); } return line; } public static int getHeight(String imagePath) { int line = 0; try { IMOperation op = new IMOperation(); op.format("%h"); // 设置获取高度参数 op.addImage(1); IdentifyCmd identifyCmd = new IdentifyCmd(true); ArrayListOutputConsumer output = new ArrayListOutputConsumer(); identifyCmd.setOutputConsumer(output); if (is_windows) { identifyCmd.setSearchPath(imageMagickPath); } identifyCmd.run(op, imagePath); ArrayList<String> cmdOutput = output.getOutput(); assert cmdOutput.size() == 1; line = Integer.parseInt(cmdOutput.get(0)); } catch (Exception e) { line = 0; System.out.println("运行指令出错!"+e.toString()); } return line; } 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); if (is_windows) { identifyCmd.setSearchPath(imageMagickPath); } 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 imagePath 源图片路径 * @param newPath 处理后图片路径 * @param x 起始X坐标 * @param y 起始Y坐标 * @param width 裁剪宽度 * @param height 裁剪高度 * @return 返回true说明裁剪成功,否则失败 */ public static boolean cutImage1(String imagePath, String newPath, int x, int y, int width, int height) { boolean flag = false; try { IMOperation op = new IMOperation(); op.addImage(imagePath); op.crop(width, height, x, y);/** width:裁剪的宽度 * height:裁剪的高度 * x:开始裁剪的横坐标 * y:开始裁剪纵坐标 */ op.addImage(newPath); ConvertCmd convert = new ConvertCmd(true); if (is_windows) { convert.setSearchPath(imageMagickPath); } convert.run(op); flag = true; } catch (IOException e) { System.out.println("文件读取错误!"); flag = false; } catch (InterruptedException e) { flag = false; } catch (IM4JavaException e) { flag = false; } return flag; } /** * 根据坐标裁剪图片 * @param srcPath 要裁剪图片的路径 * @param newPath 裁剪图片后的路径 * @param x 起始横坐标 * @param y 起始挫坐标 * @param x1 结束横坐标 * @param y1 结束挫坐标 */ public static void cutImage2(String srcPath, String newPath, int x, int y, int x1, int y1) { try { IMOperation op = new IMOperation(); int width = x1 - x; // 裁剪的宽度 int height = y1 - y;//裁剪的高度 op.addImage(srcPath); op.crop(width, height, x, y); op.addImage(newPath); ConvertCmd convert = new ConvertCmd(true); if (is_windows) { convert.setSearchPath(imageMagickPath); } convert.run(op); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IM4JavaException e) { e.printStackTrace(); } } /** * 根据尺寸等比例缩放图片 大边达到指定尺寸 * [参数height为null,按宽度缩放比例缩放;参数width为null,按高度缩放比例缩放] * @param imagePath 源图片路径 * @param newPath 处理后图片路径 * @param width 缩放后的图片宽度 * @param height 缩放后的图片高度 * @return 返回true说明缩放成功,否则失败 */ public static boolean zoomImage1(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); // IM4JAVA是同时支持GraphicsMagick和ImageMagick的,如果为true则使用GM,如果为false支持IM。 ConvertCmd convert = new ConvertCmd(true); // 判断系统 String osName = System.getProperty("os.name").toLowerCase(); if(osName.indexOf("win") >= 0) { convert.setSearchPath(imageMagickPath); } convert.run(op); flag = true; } catch (IOException e) { System.out.println("文件读取错误!"); flag = false; } catch (InterruptedException e) { flag = false; } catch (IM4JavaException e) { System.out.println(e.toString()); flag = false; } return flag; } /** * 根据像素缩放图片 * @param width 缩放后的图片宽度 * @param height 缩放后的图片高度 * @param srcPath 源图片路径 * @param newPath 缩放后图片的路径 * @param type 1大小 2比例 */ public static String zoomImage2(int width, int height, String srcPath, String newPath, int type, String quality) throws Exception { IMOperation op = new IMOperation(); op.addImage(); String raw = ""; if (type == 1) { // 按像素大小 raw = width + "x" + height + "^"; } else { // 按像素百分比 raw = width + "%x" + height + "%"; } ConvertCmd cmd = new ConvertCmd(true); op.addRawArgs("-sample", raw); if ((quality != null && !quality.equals(""))) { op.addRawArgs("-quality", quality); } op.addImage(); String osName = System.getProperty("os.name").toLowerCase(); if (osName.indexOf("win") != -1) { cmd.setSearchPath(imageMagickPath); } try { cmd.run(op, srcPath, newPath); } catch (Exception e) { e.printStackTrace(); } return newPath; } /** * 图片旋转 * @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); if (is_windows) { cmd.setSearchPath(imageMagickPath); } cmd.run(op); flag = true; } catch (Exception e) { flag = false; System.out.println("图片旋转失败!"); } return flag; } /** * 给图片加水印 * @param srcPath 源图片路径 * @param destPath 目标图片路径 */ public static void addImgText(String srcPath, String destPath) throws Exception { try { IMOperation op = new IMOperation(); op.font("Arial").gravity("southeast").pointsize(150).fill("#BCBFC8").draw("text 100,100 co188.com"); op.quality(85d); //压缩质量 op.addImage(srcPath); op.addImage(destPath); ConvertCmd cmd = new ConvertCmd(true); if (is_windows) { cmd.setSearchPath(imageMagickPath); } cmd.run(op); } catch (Exception e) { e.printStackTrace(); } } /** * 先等比例缩放,后居中切割图片 * @param srcPath 源图路径 * @param desPath 目标图保存路径 * @param rectw 待切割在宽度 * @param recth 待切割在高度 */ public static void cropImageCenter(String srcPath, String desPath, int width, int height) { try { IMOperation op = new IMOperation(); op.addImage(); op.resize(width, height, '^').gravity("center").extent(width, height); //op.resize(width, height).background("gray").gravity("center").extent(width, height); op.addImage(); ConvertCmd convert = new ConvertCmd(true); if (is_windows) { convert.setSearchPath(imageMagickPath); } convert.run(op, srcPath, desPath); } catch (IOException | InterruptedException | IM4JavaException e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { Long start = System.currentTimeMillis(); // System.out.println("原图片宽度:" + getWidth("D:\\test\\map.jpg")); // System.out.println("原图片高度:" + getHeight("D://test//map.jpg")); // System.out.println("原图片信息:" + getImageInfo("D://test//map.jpg")); // cutImage2("D://test//map.jpg", "D://test//m.jpg", 10, 10, 200, 200); // rotate("D://test//map.jpg", "D://test//m.jpg", 10); // drawImg("D://test//map.jpg", "D://test//ma.jpg", 1500, 1500); // zoomImage1( "D://test//map.jpg", "D://test//mapppp.jpg",280, 200); // zoomImage2(280, 200 ,"D://test//map.jpg", "D://test//mapppppppappp.jpg",1,null); // addImgText("D://test//map1.jpg", "D://test//map111.jpg"); cropImageCenter("D://test//haidilao.jpg", "D://test//haidilao1112.jpg", 400, 400); Long end = System.currentTimeMillis(); System.out.println("time:" + (end - start)); } }
2.配置文件: /Test/src/config.properties
imageMagickPath=D:\\Program Files\\GraphicsMagick-1.3.28-Q16
五、返回输入输出流
package img.GraphicsMagick; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.lang.SystemUtils; import org.im4java.core.ConvertCmd; import org.im4java.core.IM4JavaException; import org.im4java.core.IMOperation; import org.im4java.process.Pipe; /** * 将图片装换压缩成固定的大小格式的图片 * im4java + GraphicsMagick-1.3.24-Q16 */ public class GraphicsMagicUtilOfIM4Java { private static final String GRAPHICS_MAGICK_PATH = "D:\\Program Files\\GraphicsMagick-1.3.28-Q16"; private static final boolean IS_WINDOWS = SystemUtils.IS_OS_WINDOWS; // 压缩图片,返回输出流 public static OutputStream zoomPic(OutputStream os, InputStream is, String contentType, Integer width, Integer height) throws IOException, InterruptedException, IM4JavaException { IMOperation op = buildIMOperation(contentType, width, height); Pipe pipeIn = new Pipe(is, null); Pipe pipeOut = new Pipe(null, os); ConvertCmd cmd = new ConvertCmd(true); if (IS_WINDOWS) { // linux下不要设置此值,不然会报错 cmd.setSearchPath(GRAPHICS_MAGICK_PATH); } cmd.setInputProvider(pipeIn); cmd.setOutputConsumer(pipeOut); cmd.run(op); return os; } // 压缩图片,返回输入流 public static InputStream convertThumbnailImage(InputStream is, String contentType, double width, double height) { try { IMOperation op = buildIMOperation(contentType, width, height); Pipe pipeIn = new Pipe(is, null); ByteArrayOutputStream os = new ByteArrayOutputStream(); Pipe pipeOut = new Pipe(null, os); ConvertCmd cmd = new ConvertCmd(true); if (IS_WINDOWS) { cmd.setSearchPath(GRAPHICS_MAGICK_PATH); } cmd.setInputProvider(pipeIn); cmd.setOutputConsumer(pipeOut); cmd.run(op); return new ByteArrayInputStream(os.toByteArray()); } catch (Exception e) { System.out.println(e.getMessage()); return null; } } // 构建IMOperation private static IMOperation buildIMOperation(String contentType, Number width, Number height) { IMOperation op = new IMOperation(); String widHeight = width + "x" + height; op.addImage("-"); // 命令:从输入流中读取图片 op.addRawArgs("-scale", widHeight); // 按照给定比例缩放图片 op.addRawArgs("-gravity", "center"); // 缩放参考位置 对图像进行定位 op.addRawArgs("-extent", widHeight); // 限制JPEG文件的最大尺寸 op.addRawArgs("+profile", "*"); // 去除Exif信息 // 设置图片压缩格式 op.addImage(contentType.substring(contentType.indexOf("/") + 1) + ":-"); return op; } /** * 先等比例缩放,后居中切割图片 * @param os * @param is * @param width * @param height */ public static void zoomPic(InputStream is, OutputStream os, Integer width, Integer height) { try { IMOperation op = new IMOperation(); op.addImage("-"); // 命令:从输入流中读取图片 op.resize(width, height, '^').gravity("center").extent(width, height); op.addRawArgs("+profile", "*"); // 去除Exif信息 op.addImage("jpg" + ":-"); // 设置图片压缩格式 Pipe pipeIn = new Pipe(is, null); is.close(); Pipe pipeOut = new Pipe(null, os); os.close(); ConvertCmd cmd = new ConvertCmd(true); if (IS_WINDOWS) { // Linux下不要设置此值,不然会报错 cmd.setSearchPath(GRAPHICS_MAGICK_PATH); } cmd.setInputProvider(pipeIn); cmd.setOutputConsumer(pipeOut); cmd.run(op); } catch (IOException | InterruptedException | IM4JavaException e) { e.printStackTrace(); } } /** * 图片旋转 * @param is * @param os * @param degree */ public static byte[] rotate(InputStream is, double degree) { ByteArrayOutputStream os = new ByteArrayOutputStream(); try { // 将角度转换到0-360度之间 degree = degree % 360; if (degree <= 0) { degree = 360 + degree; } IMOperation op = new IMOperation(); op.addImage("-"); op.rotate(degree); op.addImage("jpg" + ":-"); Pipe pipeIn = new Pipe(is, null); is.close(); Pipe pipeOut = new Pipe(null, os); os.close(); ConvertCmd cmd = new ConvertCmd(true); if (IS_WINDOWS) { cmd.setSearchPath(GRAPHICS_MAGICK_PATH); } cmd.setInputProvider(pipeIn); cmd.setOutputConsumer(pipeOut); cmd.run(op); } catch (IOException | InterruptedException | IM4JavaException e) { e.printStackTrace(); return null; } return os.toByteArray(); } public static void main(String[] args) throws Exception { // 输入输出文件路径/文件 File srcFile = new File("D:\\test\\wKgB-1pycFOAAGicAAUp98UmwuU169.jpg"); File destFile = new File("D:\\test\\www1211211.jpg"); byte[] bytes = getByte(srcFile); ByteArrayInputStream is = new ByteArrayInputStream(bytes); ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] rotate = rotate(is, 300); FileOutputStream fis = new FileOutputStream(destFile); fis.write(rotate); } /** * 将file文件转为字节数组 */ public static byte[] getByte(File file){ byte[] bytes = null; try { FileInputStream fis = new FileInputStream(file); bytes = new byte[fis.available()]; fis.read(bytes); fis.close(); } catch (IOException e) { e.printStackTrace(); } return bytes; } /** * 将字节流写到指定文件 */ public static void writeFile(ByteArrayOutputStream os, File file){ try { if (file.exists()) { file.delete(); } FileOutputStream fos = new FileOutputStream(file); fos.write(os.toByteArray()); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }