天天看點

在windows和Linux上安裝ImageMagick與jmagick,Maven配置、Java圖檔壓縮代碼(整理網上、結合自己情況、編寫出來的新安裝方式)

安裝過程(如圖所示) 

2、安裝支援庫

linux伺服器如果沒有安裝jpeg v6b、libpng、freetype庫,要在安裝imagemagick之前先裝好,否則imagemagick沒法讀取jpeg和png圖檔,字型檔案也讀不了.(本次安裝以redhat為例,進行imagemagick的安裝)

----freetype-2.4.4.tar.gz  字型引擎,生産高品質的字形影像輸出,(例如彩色文本渲染,挖空等等)。

----zlib-1.2.5.tar.gz  是zlib通用壓縮庫,圖形格式png使用zlib中的deflate壓縮算法。

---- jpegsrc.v9a.tar.gz 要處理 jpeg 的庫, jpegsrc.v7.tar.gz是必需,還是從源碼安裝

----libpng-1.5.10.tar.gz 要處理 png 的庫,則 libpng-1.5.10.tar.gz 是必需的,還是從源碼安裝

----libjpeg   支援jpeg v1格式(jpegsrc.v8b.tar.gz)

以下可選:

----jasper-1.900.1.zip   支援jpeg2000(檔案擴充名是 .jp2.j2c)

----tiff-3.8.0.tar.gz   支援tif檔案  這個用不到,不要安裝了

3.安裝各種軟體

安裝jpeg包(建議使用jpegsrc.v8b.tar.gz,下載下傳位址可以從網上查找)

執行的指令:

su root

檢查是否已經安裝過了

[root@oracle tpl]# rpm -qa | grep jpeg

openjpeg-libs-1.3-7.el6.x86_64

libjpeg-6b-46.el6.x86_64tar -zxvf jpegsrc.v8b.tar.gz

[root@oracle tpl]# rpm -e --allmatches --nodeps libjpeg-6b-46.el6.x86_64

[root@oracle tpl]# tar -zxvf jpegsrc.v8b.tar.gz

[root@oracle tpl]# cd jpeg-8b/

[root@oracle jpeg-8b]# ./configure --enable-shared --enable-static ; make ; make install

安裝zlib包:

ftp://ftp.graphicsmagick.org/pub/graphicsmagick/delegates

是zlib通用壓縮庫,圖形格式png使用zlib中的deflate壓縮算法,指令如下:

[root@oracle tpl]# rpm -qa | grep zlib

zlib-1.2.3-25.el6.x86_64

[root@oracle tpl]# rpm -e --allmatches --nodeps zlib-1.2.3-25.el6.x86_64

[root@oracle tpl]# tar -zxvf zlib-1.2.5.tar.gz

[root@oracle tpl]# cd zlib-1.2.5

[root@oracle zlib-1.2.5]# ./configure

[root@oracle zlib-1.2.5]#make

[root@oracle zlib-1.2.5]#make install

安裝png包:

<a target="_blank" href="http://www.libpng.org/pub/png/pngcode.html">http://www.libpng.org/pub/png/pngcode.html</a>

指令:

[root@oracle zlib-1.2.5]# rpm -qa | grep png

libpng-1.2.44-1.el6.x86_64

[root@oracle zlib-1.2.5]# rpm -e --allmatches --nodeps libpng-1.2.44-1.el6.x86_64

[root@oracle zlib-1.2.5]#tar -xzvf libpng-1.2.12.tar.gz

[root@oracle zlib-1.2.5]#cd libpng-1.2.12

[root@oracle zlib-1.2.5]#./configure (注意:此處不要使用網上的通過cp script下的makefile的方式執行的那種,不然在安裝imagemagick的時候出錯)

安裝freetype

[root@oracle zlib-1.2.5]# rpm -qa | grep freetype

[root@oracle zlib-1.2.5]# tar –zxvf freetype-2.4.4.tar.gz

[root@oracle zlib-1.2.5]#./configure

[root@oracle zlib-1.2.5]# make

[root@oracle zlib-1.2.5]# make install

安裝tiff包

下載下傳位址:ftp://ftp.graphicsmagick.org/pub/graphicsmagick/delegates

ftp://ftp.remotesensing.org/libtiff/

安裝後才能處理tiff格式圖檔

tar -xzvf tiff-3.8.0.tar.gz   

cd tiff-3.8.0  

./configure   

make   

make install 

我安裝完成後,在指令行處理圖檔,報錯:libtiff.so.3: cannot open shared object file: no such file ordirectory

這個子產品也用不到, 就不要安裝了. 

安裝jasper包:

安裝後才能處理jpeg2000格式圖檔(檔案擴充名是 .jp2 .j2c)

指令如下:

unzip jasper-1.900.1.zip   

cd jasper-1.900.1  

cflags=-fpic  ./configure   

make cflags=-fpic   

make  cflags=-fpic install

 三、在linux上用源碼編譯安裝imagemagick與jmagick

------------------------------------------------------------------------------------------------------------------

下載下傳imagemagick和jmagick

jmagick在imagemagick官網首頁左側菜單的program interfaces菜單中找到jmagick。進入jmagick的首頁。

我們下載下傳:

imagemagick-6.4.0-0.tar.gz

jmagick-6.4.0-src.tar.gz

解壓imagemagick,檢視imagemagick的安裝說明檔案install-unix.txt就知道怎麼安裝imagemagick了。

解壓jmagick,檢視jmagick的安裝說明檔案install就知道怎麼安裝jmagick了。

4.安裝imagemagick

修改檔案執行權限:chmod -r 755 檔案名

tar zvxf imagemagick-6.4.0-0.tar.gz

cd imagemagick-6.4.0-0

./configure cc=gcc cxx=c++ cppflags='-i/usr/local/include' ldflags='-l/usr/local/lib -r/usr/local/lib' --with-quantum-depth=8 --enable-shared --without-perl

make cflags=-fpic   (紅色字型的是必須的)

make install

若想解除安裝,可以使用:make uninstall

另外,關于configure中的說明,如下:

configure參數說明:

--enable-shared 編譯成共享庫

--disable-static 不編譯成靜态庫

--disable-openmp 禁用多線程,使用多線程性能并沒有提高,但cpu占用達到了100%,是以禁用了。

--with-quantum-depth=8 使用8位色深。我的1200萬像素數位相機,照出的圖檔就是8位色深。

--with-windows-font-dir=目錄 ,指明字型檔案的目錄(後面将人工複制中文字型檔案到這個目錄)

configure 完成後,一定要檢查im支援的圖檔格式種類,configure 完成後出會輸出類似如下圖的資訊,請仔細檢查。(資訊不一定和下圖一樣,請根據實際情況自行分析)

驗證configuration情況:identify -list configure

驗證支援的圖檔格式:identify -list format

關于q8,q16,q32的說明:(建議使用8,現在數位相機照的相片,每一種顔色就是8位深,3種顔色就是24位,是以選8)

支援的參數有3種,分别是 8, 16, or 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

使用convert –version檢查是否已經安裝成功了

若出現下面的輸出說明已經安裝成功了

version: imagemagick 6.4.0 09/25/16 q8 http://www.imagemagick.org

copyright: copyright (c) 1999-2008 imagemagick studio llc

使用convert -list format檢查支援的檔案類型。檢查清單中是否有jpg和png格式的。若沒有這兩個檔案,說明是jpeg包和png包沒裝好,因為imagemagick依賴jpeg包和png包。

imagemagick的使用(參考百度:http://jingyan.baidu.com/article/948f59245ec02dd80ff5f989.html):

參考指令:

轉換格式指令:

# convert -format demo.jpg demo.png 

将jpg轉換成png

指定大小縮放:

# convert -resize "500x300&gt;" demo.jpg  demo_500.jpg

如果圖檔比500x300小就保持原樣,以防小圖檔被放大失真

去除多餘資訊:

#convert -strip input.jpg output.jpg

将多餘的資訊去除:攝影時的光圈、快門、iso、日期時間等各種與當時攝影條件相關的訊息,相機品牌型号,色彩編碼,拍攝時錄制的聲音以及全球定位系統(gps)等資訊。

壓縮比:

#convert -quality 75% demo.jpg demo_75.jpg

imagemagick的指令很多 具體可以檢視官方手冊 

http://www.imagemagick.org/script/command-line-tools.php

5.安裝jdk,參考博文如下:

安裝jdk,參考博文:http://blog.csdn.net/tototuzuoquan/article/details/18188109

6、安裝jmagick

tar zvxf jmagick-6.4.0-src.tar.gz

cd 6.4.0

./configure --prefix=/usr/local/lib/jmagick-6.4.0 --with-java-home=/usr/java/jdk1.6.0_45 -with-magick-home=/usr/local/lib/imagemagick-6.4.0

make all

下面幾步測試可以不執行

make simpletest 因沒有junit的jar包報2個錯誤,不用管。

make test

make javadoc

安裝成功後,在/usr/local/lib/jmagick-6.4.0/lib/有一個jmagick-6.4.0.jar檔案,在你的java項目中就使用這個jar檔案處理圖檔。

記住jmagick-6.4.0.jar是使用前面你指定的jdk1.6編譯出來的,是以不能在jdk為1.5的環境下使用jmagick-6.4.0.jar。

如果你執行了make javadoc,在/usr/local/lib/jmagick-6.4.0/share/doc目錄下就有文檔。

另外:部署項目後,會發現會報: could not initializeclass magick.imageinfo的問題,

解決辦法

步驟1::進入/usr/local/lib/jmagick-6.4.0

[root@oracle lib]# cd /usr/local/lib/jmagick-6.4.0/lib

[root@oracle lib]# ls

jmagick-6.4.0.jar  libjmagick-6.4.0.so  libjmagick.so

[root@oracle lib]#cp jmagick-6.4.0.jar /newdisk/ucmsserver/tomcat/bin/    (将jmagick-6.4.0.jar放到tomcat中的bin中一份)

cp /newdisk/ucmsserver/tomcat/webapps/app-tpl-webapp/web-inf/lib/jmagick-6.4.0.jar /usr/java/jdk1.6.0_45/jre/lib/ext   (将jar包拷貝一份到jdk中的jre/lib/ext中)

注意把自己工程lib包中的jmagick的jar包也改成jmagick-6.4.0.jar。

步驟2:編寫test.java

public class test {

    public static void main(string[] args) {

        system.out.println(system.getproperty("java.library.path"));

    }

}

執行指令:javac test.java   java test

[root@oracle tpl]# javac test.java

[root@oracle tpl]# java test

/usr/java/jdk1.6.0_45/jre/lib/amd64/server:/usr/java/jdk1.6.0_45/jre/lib/amd64:/usr/java/jdk1.6.0_45/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

[root@oracle tpl]# cd /usr/local/lib/jmagick-6.4.0/lib

jmagick-6.4.0.jar  libjmagick-6.4.0.so  libjmagick.so

風别把上面的.so檔案放到/usr/java/jdk1.6.0_45/jre/lib/amd64/server:/usr/java/jdk1.6.0_45/jre/lib/amd64:/usr/java/jdk1.6.0_45/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib中的各包下,指令如下:

[root@oracle lib]# cp *.so /usr/java/jdk1.6.0_45/jre/lib/amd64/server

[root@oracle lib]# cp *.so /usr/java/jdk1.6.0_45/jre/lib/amd64

[root@oracle lib]# cp *.so /usr/java/packages/lib/amd64

[root@oracle lib]# cp *.so /usr/lib64

[root@oracle lib]# cp *.so /lib64

[root@oracle lib]# cp *.so /lib

[root@oracle lib]# cp *.so /usr/lib

最後重新開機tomcat,重新通路自己的工程,發現裁剪效果正常了。

四、在windows上安裝imagemagick與jmagick

 --------------------------------------------------------------------------

在windows安裝很簡單,關于q8與q16差別,前有說明是一樣的。

有動态版(dll),有靜态版(static),建議使用動态版。

如果安裝q8,請使用檔案:

imagemagick-6.3.9-0-q8-windows-dll.exe

jmagick-win-6.3.9-q8.zip

如果安裝q16,請使用檔案:

imagemagick-6.3.9-0-q16-windows-dll.exe

jmagick-win-6.3.9-q16.zip

我們以q8為例:

1、運作imagemagick-6.3.9-0-q8-windows-dll.exe,一路下一步,imagemagick就安裝好了

2、解壓jmagick-win-6.3.9-q8.zip,把jmagick.dll放入system32,在你的java項目中使用jmagick.jar包處理圖檔。

當将dll放到system32中後、需要重新開機一下電腦。

将jmagick-6.2.4.jar放到tomcat\lib中。

maven中在pom檔案中添加上依賴:

&lt;dependency&gt;

&lt;groupid&gt;jmagick&lt;/groupid&gt;

&lt;artifactid&gt;jmagick&lt;/artifactid&gt;

&lt;version&gt;6.2.4&lt;/version&gt;

&lt;/dependency&gt;

六、常見問題以及解決方法:

--------------------------------------------------------------------------

1、system.out.println(system.getproperty("java.library.path")). 

直接用system.out.println(system.getproperty("java.library.path")). 

列印出目前環境的路徑,然後再把jmagick.dll或jmagick.so 複制到其中的一個路徑檔案夾中問題解決。

2、magick.magickexception: no image to scale

版本不比對,要像下面這們,都是同一個版本号

3、magick.magickexception: unable to retrieve handle

要調用 magick.magickimage.destroyimages() 來關閉

4、no decode delegate for this image format

使用:identify -list format

判斷有支援幾種圖檔格式,沒有的則需要安裝對應的格式庫

5、單線程轉換每張圖檔大概50ms,兩個線程卻需要500ms

用convert --version  指令檢視

看是否出現openmp字樣,出現的話,是因為機器不支援openmp導緻的。

需要重新編譯./configure --disable-openmp  在進行安裝

首先檢查一下電腦裡已經安裝的imagemagick版本:

convert -version

6、exceptionin thread "main" java.lang.unsatisfiedlinkerror:c:\windows\system32\jmagick.dll: can't find dependent libraries

我在windows xp上按照上面的流程安裝完成,按理說應該沒有問題了,但出現了以上錯誤。

我打開eclipse已工作數個小時,然後在開發機器(我本機)windows xp上安裝imagemagick-6.3.9-0-q16-windows-dll.exe。也把jmagick.dll放入system32,在你的java項目中使用jmagick.jar包處理圖檔。

就這麼幾步當然不會錯,但在運作程式時還是出現了上面的錯誤。

解決:重新開機eclipse。加載新的環境變量。

七、代碼實作

package com.xxx.tpl.utils;

import java.awt.dimension;

import java.awt.point;

import java.awt.rectangle;

import java.io.file;

import java.io.ioexception;

import magick.compositeoperator;

import magick.compressiontype;

import magick.drawinfo;

import magick.imageinfo;

import magick.magickexception;

import magick.magickimage;

import magick.pixelpacket;

import magick.previewtype;

public class jmagickutil {

         public static void main(string[] args) throws magickexception, ioexception {

                   // test for function imageresize

                   jmagickutil.imageresize("e:/ucmsserver/tomcat/webapps/temp/tpl/snapshot/2016/9/25955ea769ff47ada6b84f7b39cee904.png",

                                                     "d:/installed/tomcat/webapps/tpl/special/2016/9/d26076f602284c3eac1abaa71d2378b2/thumbnail/big/2016/9/25955ea769ff47ada6b84f7b39cee904.png", 160, 160);

                   // jmagicjwrapper.imageresize("pics.jpg", "resize250x200.jpeg", 250,

                   // 200);

                   // jmagicjwrapper.imageresize("pics.jpg", "resize50x50.jpg", 50, 50);

                   // jmagicjwrapper.imageresize("pics.jpg", "resize120x120.bmp", 120,

                   // 120);

                   // jmagicjwrapper.imageresize("pics.jpg", "resize.tif", 20, 30);//not

                   // create file

                   //           

                   // test for function createwaterprintbyimg

//               jmagickutil.createwaterprintbyimg("f://1.jpg", "f://4.jpg",

//                                 "f://watermark.gif", new point(0, 0));

                   // jmagicjwrapper.imageresize("wpl.gif", "logo250x200.gif", 250, 200);

                   // because file "wpl.gif" may not be release, the later function cause a

                   // error, can not open file handle.

                   // jmagicjwrapper.createwaterprintbyimg("pics.jpg", "wpl.gif",

                   // "logofull.jpg", new point(1680,1050));//not create file

                   // jmagicjwrapper.createwaterprintbyimg("pics.jpg", "wpl.gif",

                   // "logoext.jpg", new point(2000,1000));//not create file

                   // test for function createwaterprintbytext

                   // this function can not handle chinese character, i'll continue to

                   // takle the issue

                   // jmagicjwrapper.createwaterprintbytext("pics1.jpg", "wpt.gif",

                   // "for test", new point(300,300), 100);

         }

         private static final string[] type = { ".jpg", ".jpeg", ".bmp", ".gif",

                            ".png" };

         public static boolean checktype(string path) {

                   for (int i = 0; i &lt; type.length; i++) {

                            if (path.touppercase().endswith(type[i])) {

                                     return true;

                            } else {

                                     continue;

                            }

                   }

                   return false;

         /**

          * 改變圖檔大小

          *

          * @param filepath

          *            原圖檔位置 topath 新圖檔位置 width 新圖檔的寬度 height 新圖檔的高度

          * @return

          * @throw

          * @author  2010-8-11

          * @throws ioexception

          */

         public static void imageresize(string filepath, string topath, int width,

                            int height) throws magickexception, ioexception {

                   //必須寫,否則jmagick.jar的路徑找不到

        system.setproperty("jmagick.systemclassloader","no");

        file fileori = new file(filepath);

        file filedes = new file(topath);

        if (!fileori.exists()) {

                            return;

        if (!filedes.exists()) {

                            string parentpath = filedes.getparent();

                            new file(parentpath).mkdirs();

                            filedes.createnewfile();

                   imageinfo info = null;

                   magickimage image = null;

                   dimension imagedim = null;

                   magickimage scaled = null;

                   if (!checktype(filepath) || !checktype(topath)) {

                   try {

                            info = new imageinfo(filepath);

                            image = new magickimage(info);

                            imagedim = image.getdimension();

                            if (width &lt;= 0 || height &lt;= 0) {

                                     height = 120;

                                     width = 120;

                            scaled = image.scaleimage(width, height);

                            scaled.setfilename(topath);

                            scaled.writeimage(info);

                   } finally {

                            if (scaled != null) {

                                     scaled.destroyimages();

          * 建立圖檔水印

          *            源檔案路徑 toimg 生成檔案位置 logopath logo路徑 pos logo在源圖檔中的相對位置,以像素點為機關

          * @throw magickexception

         public static void createwaterprintbyimg(string filepath, string toimg,

                            string logopath, point pos) throws magickexception {

                   if (!checktype(filepath) || !checktype(toimg) || !checktype(logopath)) {

                   imageinfo info = new imageinfo();

                   magickimage fimage = null;

                   magickimage simage = null;

                   magickimage flogo = null;

                   magickimage slogo = null;

                   dimension logodim = null;

                            // 原來圖檔

                            fimage = new magickimage(new imageinfo(filepath));

                            imagedim = fimage.getdimension();

                            int width = imagedim.width;

                            int height = imagedim.height;

                            simage = fimage.scaleimage(width, height);

                            flogo = new magickimage(new imageinfo(logopath));

                            logodim = flogo.getdimension();

                            int lw = logodim.width;

                            int lh = logodim.height;

                            slogo = flogo.scaleimage(lw, lh);

                            // 開始打水印,從左上角開始;如果到右邊界則重新開始一行的列印(x=0,y=y+h)

                            int startx = 0;

                            int starty = 0;

                            do {

                                     simage.compositeimage(compositeoperator.atopcompositeop, slogo,

                                                        startx, starty);

                                     startx += (logodim.width + 60);

                                     if (startx &gt;= width) {

                                               starty += logodim.height * 2;

                                               startx = 0;

                                     }

                            } while (starty &lt;= height);

                            simage.setfilename(toimg);

                            simage.writeimage(info);

                            if (fimage != null) {

                                     fimage.destroyimages();

                            if (simage != null) {

                                     simage.destroyimages();

                            if (flogo != null) {

                                     flogo.destroyimages();

                            if (slogo != null) {

                                     slogo.destroyimages();

          * 建立文字水印

          *            源檔案路徑 toimg 生成檔案位置 text 水印文本 pos logo在源圖檔中的相對位置,以像素點為機關

          *            pointsize 用于設定點陣大小

         public static void createwaterprintbytext(string filepath, string toimg,

                            string text, point pos, int pointsize) throws magickexception {

                   if (!checktype(filepath) || !checktype(toimg)) {

                   if (null == text || "".equals(text)) {

                            text = "";

                   imageinfo info = new imageinfo(filepath);

                   if (filepath.touppercase().endswith("jpg")

                                     || filepath.touppercase().endswith("jpeg")) {

                            info.setcompression(compressiontype.jpegcompression); // 壓縮類别為jpeg格式

                            info.setpreviewtype(previewtype.jpegpreview); // 預覽格式為jpeg格式

                            info.setquality(95);

                   magickimage aimage = new magickimage(info);

                   dimension imagedim = aimage.getdimension();

                   int width = imagedim.width;

                   int height = imagedim.height;

                   if (width &lt;= (int) pos.getx() || height &lt;= (int) pos.gety()) {

                            pos.setlocation(0, 0);

                   int a = 0;

                   int b = 0;

                   string[] as = text.split("");

                   for (string string : as) {

                            if (string.matches("[/u4e00-/u9fa5]")) {

                                     a++;

                            if (string.matches("[a-za-z0-9]")) {

                                     b++;

                   int tl = a * 12 + b * 6;// 字元長度

                   magickimage scaled = aimage.scaleimage(width, height);

                   if (width &gt; tl &amp;&amp; height &gt; 5) {

                            drawinfo ainfo = new drawinfo(info);

                            ainfo.setfill(pixelpacket.querycolordatabase("white"));

                            ainfo.setundercolor(new pixelpacket(65535, 65535, 65535, 65535));// 設定為透明顔色

                            ainfo.setpointsize(pointsize);

                            // 解決中文亂碼問題,自己可以去随意定義個自己喜歡字型,我在這用的微軟雅黑

                            string fontpath = "c:/windows/fonts/msimhei.ttf";

                            // string fontpath = "/usr/maindata/msyh.ttf";

                            ainfo.setfont(fontpath);

                            ainfo.settextantialias(true);

                            ainfo.setopacity(0);// 透明度

                            ainfo.settext(text);

                            ainfo

                                               .setgeometry("+"

                                                                 + ((int) pos.getx() + "+" + (int) pos.gety()));

                            scaled.annotateimage(ainfo);

                   scaled.setfilename(toimg);

                   scaled.writeimage(info);

                   scaled.destroyimages();

          * 切取圖檔

          * @param imgpath

          *            原圖路徑 topath 生成檔案位置 w 左上位置橫坐标 h 左上位置豎坐标 x 右下位置橫坐标 y 右下位置豎坐标

         public static void cutimg(string imgpath, string topath, int w, int h,

                            int x, int y) throws magickexception {

                   imageinfo infos = null;

                   magickimage cropped = null;

                   rectangle rect = null;

                            infos = new imageinfo(imgpath);

                            image = new magickimage(infos);

                            rect = new rectangle(x, y, w, h);

                            cropped = image.cropimage(rect);

                            cropped.setfilename(topath);

                            cropped.writeimage(infos);

                            if (cropped != null) {

                                     cropped.destroyimages();

          * 删除圖檔檔案

          * @param src 圖檔位置

          * @author 2010-8-11

         public static boolean removefile(string src) throws securityexception {

                            if (!checktype(src)) {

                                     return false;

                            file file = new file(src);

                            return file.delete();

                   } catch (exception e) {

                            e.printstacktrace();

                            return false;