項目描述

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),這裏使用了動態版。

java 調用imagemagic處理tif文件_ide

4、下載時注意版本問題。不要到imagemagick官方網站下載imagemagick,這樣會導致下載的imagemagick版本和jmagick版本不對應,導致調用出現異常。比如出現memor allocate not enough 的異常。

這是我下載出來的文件(我公司電腦系統是WIN7-32位,安裝的也是32位的JDK):

java 調用imagemagic處理tif文件_java_02

java 調用imagemagic處理tif文件_文件路徑_03

5、雙擊下載的ImageMagick-6.3.9-0-Q8-windows-dll.exe文件安裝即可,一直點擊下一步就可以。這裏如果勾選了紅框標註的選項,環境變量會自動配好的。

java 調用imagemagic處理tif文件_文件路徑_04

在命令行使用

到這裏就可以在DOS命令窗口中使用了,具體使用命令可以參考這篇博客:http://www.charry.org/docs/linux/ImageMagick/ImageMagick.html,下面截圖演示對桌面圖片的處理:

java 調用imagemagic處理tif文件_ide_05

java 調用imagemagic處理tif文件_java_06

在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 }