項目描述
imagemagick是功能強大的圖片處理庫,以穩定及高效率著稱,眾多語言對該庫進行封裝處理。比如php、java。由於我們是java項目,直接使用java通過JNI技術調用ImageMagick是不行的。因為ImageMagick開發時沒有使用java JNI生成的頭文件。可以使用JMagick解決,JMagick是由c語言開發的,開發時使用了java JNI生成的頭文件,所以java可以通過JNI技術調用JMagick。JMagick再調用ImageMagick。這裏我們處理圖片使用的是JMagick暴露的java接口。
下載和安裝
Windows安裝使用Jmagick及imagemagick步驟如下:
1、訪問jmagick網站下載:
2、目前JMagick只有32位的,所以只能選擇32位的ImageMagick,並且版本支持很低,目前只到ImageMagick-6.3.9-0,只能使用32位的JDK,64位進程不能夠調用32位的dll,想在64位的系統上用jmagick不僅要將jdk換成32位,而且jmagick.dll也得放到SysWOW64下面,不能放到System32中。
3、下載兩個文件:紅框的兩個或者綠框的兩個。
關於Q8,Q16,Q32的説明:(建議使用8,現在數碼相機照的相片,每一種顏色就是8位深,3種顏色就是24位,所以選8)
支持的參數有3種,分別是 8,16,32。默認值是16。
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-bit per pixel quantums。使用16-bit per pixel quantums在處理圖片時比8-bit慢15%至50%,並須要更多的內存。比如處理一張1024x768像素的圖片8-bit要使用3M內存,16-bit要使用8M內存。8-bit可表示0-255種值,16-bit可表示0-65535種值。默認值是8-bit。
另外Windows下有動態版(dll),有靜態版(static),這裏使用了動態版。
4、下載時注意版本問題。不要到imagemagick官方網站下載imagemagick,這樣會導致下載的imagemagick版本和jmagick版本不對應,導致調用出現異常。比如出現memor allocate not enough 的異常。
這是我下載出來的文件(我公司電腦系統是WIN7-32位,安裝的也是32位的JDK):
5、雙擊下載的ImageMagick-6.3.9-0-Q8-windows-dll.exe文件安裝即可,一直點擊下一步就可以。這裏如果勾選了紅框標註的選項,環境變量會自動配好的。
在命令行使用
到這裏就可以在DOS命令窗口中使用了,具體使用命令可以參考這篇博客:http://www.charry.org/docs/linux/ImageMagick/ImageMagick.html,下面截圖演示對桌面圖片的處理:
在Java中使用
1、將ImageMagick安裝目錄下的所有的.dll文件複製到 C:/ windows/System32的目錄下(這一步有可能省略,等待驗證)
2、解壓jmagick-win-6.3.9-Q8.zip , 將jmagick.dll放到 C:/windows/System32 目錄下。這裏是為了能在Java中使用jmagick的類進行操作ImageMagick,如果不復制的話,會報UnsatisfiedLinkError: no JMagick in java.library.path.異常。
3、將jmagick.jar加入到eclipse下相關項目的build path中的libraries 中即完成了相應的安裝。接下來就可以在java項目中使用了。
4、Java中通過jmagick操作ImageMagick,示例代碼:
1 package com.demo.test;
2
3 import java.awt.Dimension;
4 import java.awt.Rectangle;
5 import java.text.SimpleDateFormat;
6 import java.util.Date;
7
8
9 import magick.CompositeOperator;
10 import magick.CompressionType;
11 import magick.DrawInfo;
12 import magick.ImageInfo;
13 import magick.MagickException;
14 import magick.MagickImage;
15 import magick.PixelPacket;
16 import magick.PreviewType;
17
18 public class ImageTools {
19
20 static{
21 //不能漏掉這個,不然jmagick.jar的路徑找不到
22 //System.setProperty("jmagick.systemclassloader","no");
23 }
24
25 /**
26 * 壓縮圖片
27 * @param filePath 源文件路徑
28 * @param toPath 縮略圖路徑
29 */
30 public static void createThumbnail(String filePath, String toPath) throws MagickException{
31 ImageInfo info = null;
32 MagickImage image = null;
33 Dimension imageDim = null;
34 MagickImage scaled = null;
35 try{
36 info = new ImageInfo(filePath);
37 image = new MagickImage(info);
38 imageDim = image.getDimension();
39 int wideth = imageDim.width;
40 int height = imageDim.height;
41 if (wideth > height) {
42 height = 660 * height / wideth;
43 wideth = 660;
44 }
45 scaled = image.scaleImage(wideth, height);//小圖片文件的大小.
46 scaled.setFileName(toPath);
47 scaled.writeImage(info);
48 }finally{
49 if(scaled != null){
50 scaled.destroyImages();
51 }
52 }
53 }
54
55 /**
56 * 水印(圖片logo)
57 * @param filePath 源文件路徑
58 * @param toImg 修改圖路徑
59 * @param logoPath logo圖路徑
60 * @throws MagickException
61 */
62 public static void initLogoImg(String filePath, String toImg, String logoPath) throws MagickException {
63 ImageInfo info = new ImageInfo();
64 MagickImage fImage = null;
65 MagickImage sImage = null;
66 MagickImage fLogo = null;
67 MagickImage sLogo = null;
68 Dimension imageDim = null;
69 Dimension logoDim = null;
70 try {
71 fImage = new MagickImage(new ImageInfo(filePath));
72 imageDim = fImage.getDimension();
73 int width = imageDim.width;
74 int height = imageDim.height;
75 if (width > 660) {
76 height = 660 * height / width;
77 width = 660;
78 }
79 sImage = fImage.scaleImage(width, height);
80
81 fLogo = new MagickImage(new ImageInfo(logoPath));
82 logoDim = fLogo.getDimension();
83 int lw = width / 8;
84 int lh = logoDim.height * lw / logoDim.width;
85 sLogo = fLogo.scaleImage(lw, lh);
86
87 sImage.compositeImage(CompositeOperator.AtopCompositeOp, sLogo, width-(lw + lh/10), height-(lh + lh/10));
88 sImage.setFileName(toImg);
89 sImage.writeImage(info);
90 } finally {
91 if(sImage != null){
92 sImage.destroyImages();
93 }
94 }
95 }
96
97 /**
98 * 水印(文字)
99 * @param filePath 源文件路徑
100 * @param toImg 修改圖路徑
101 * @param text 名字(文字內容自己隨意)
102 * @throws MagickException
103 */
104 public static void initTextToImg(String filePath, String toImg, String text) throws MagickException{
105 ImageInfo info = new ImageInfo(filePath);
106 if (filePath.toUpperCase().endsWith("JPG") || filePath.toUpperCase().endsWith("JPEG")) {
107 info.setCompression(CompressionType.JPEGCompression); //壓縮類別為JPEG格式
108 info.setPreviewType(PreviewType.JPEGPreview); //預覽格式為JPEG格式
109 info.setQuality(95);
110 }
111 MagickImage aImage = new MagickImage(info);
112 Dimension imageDim = aImage.getDimension();
113 int wideth = imageDim.width;
114 int height = imageDim.height;
115 if (wideth > 660) {
116 height = 660 * height / wideth;
117 wideth = 660;
118 }
119 int a = 0;
120 int b = 0;
121 String[] as = text.split("");
122 for (String string : as) {
123 if(string.matches("[\u4E00-\u9FA5]")){
124 a++;
125 }
126 if(string.matches("[a-zA-Z0-9]")){
127 b++;
128 }
129 }
130 int tl = a*12 + b*6 + 300;
131 MagickImage scaled = aImage.scaleImage(wideth, height);
132 if(wideth > tl && height > 5){
133 DrawInfo aInfo = new DrawInfo(info);
134 aInfo.setFill(PixelPacket.queryColorDatabase("white"));
135 aInfo.setUnderColor(new PixelPacket(0,0,0,100));
136 aInfo.setPointsize(12);
137 //解決中文亂碼問題,自己可以去隨意定義個自己喜歡字體,我在這用的微軟雅黑
138 String fontPath = "C:/WINDOWS/Fonts/MSYH.TTF";
139 //String fontPath = "/usr/maindata/MSYH.TTF";
140 aInfo.setFont(fontPath);
141 aInfo.setTextAntialias(true);
142 aInfo.setOpacity(0);
143 aInfo.setText(" " + text + "於 " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " 上傳於我的相冊網,版權歸作者所有!");
144 aInfo.setGeometry("+" + (wideth-tl) + "+" + (height-5));
145 scaled.annotateImage(aInfo);
146 }
147 scaled.setFileName(toImg);
148 scaled.writeImage(info);
149 scaled.destroyImages();
150 }
151
152 /**
153 * 切圖
154 * @param imgPath 源圖路徑
155 * @param toPath 修改圖路徑
156 * @param w
157 * @param h
158 * @param x
159 * @param y
160 * @throws MagickException
161 */
162 public static void cutImg(String imgPath, String toPath, int w, int h, int x, int y) throws MagickException {
163 ImageInfo infoS = null;
164 MagickImage image = null;
165 MagickImage cropped = null;
166 Rectangle rect = null;
167 try {
168 infoS = new ImageInfo(imgPath);
169 image = new MagickImage(infoS);
170 rect = new Rectangle(x, y, w, h);
171 cropped = image.cropImage(rect);
172 cropped.setFileName(toPath);
173 cropped.writeImage(infoS);
174
175 } finally {
176 if (cropped != null) {
177 cropped.destroyImages();
178 }
179 }
180 }
181
182 /**
183 * 測試
184 * @param args
185 */
186 public static void main(String[] args) {
187 try {
188 cutImg("C:\\Users\\Administrator\\Desktop\\test\\new3.jpg", "C:\\Users\\Administrator\\Desktop\\test\\new5.jpg", 100, 100, 300, 150);
189 } catch (MagickException e) {
190 e.printStackTrace();
191 }
192 }
193 }