一、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(); } } }