2013年10月12日星期六

使用Imagemagick和Jmagick拼接图片并打水印

安装

注:本文参考系统:2.6.32-279.el6.x86_64, CentOS6.x
首先需要安装jpeg库和freetype库来支持imagemagick安装。
1. 安装libjpeg
2. 安装Imagemagick,执行configure
#>./configure --without-perl
执行之后查看configure结果
Shared libraries  --enable-shared=yes           yes
Static libraries  --enable-static=yes           yes
Module support    --with-modules=yes            yes
GNU ld            --with-gnu-ld=yes             yes
Quantum depth     --with-quantum-depth=16       16
High Dynamic Range Imagery
                  --enable-hdri=no              no

Delegate Configuration:
BZLIB             --with-bzlib=yes              no
DJVU              --with-djvu=no                no
DPS               --with-dps=yes                no
FlashPIX          --with-fpx=yes                no
FontConfig        --with-fontconfig=no          no
FreeType          --with-freetype=yes           yes
GhostPCL          None                          pcl6 (unknown)
GhostXPS          None                          gxps (unknown)
Ghostscript       None                          gs (8.70)
result_ghostscript_font_dir='none'
Ghostscript fonts --with-gs-font-dir=default
Ghostscript lib   --with-gslib=yes              no
Graphviz          --with-gvc=yes                no
JBIG              --with-jbig=yes               no
JPEG v1           --with-jpeg=yes               yes
JPEG-2000         --with-jp2=yes                no
LCMS              --with-lcms=yes               no
LQR               --with-lqr=no         no
Magick++          --with-magick-plus-plus=yes   yes
OpenEXR           --with-openexr=yes            no
PERL              --with-perl=no                no
PNG               --with-png=yes                no
RSVG              --with-rsvg=no                no
TIFF              --with-tiff=yes               no
result_windows_font_dir='none'
Windows fonts     --with-windows-font-dir=
WMF               --with-wmf=yes                no
X11               --with-x=                     no
XML               --with-xml=no         no
ZLIB              --with-zlib=yes               yes
发现JPEG和FreeType已经是yes
然后make && make install
此时可以使用命令测试:
#>montage test.jpg test1.jpg test2.jpg -tile 3X1 -geometry 480x360+0+0 output.jpg
如果出现:sh:gs not found 安装yum install ghostscript
3. 安装Jmagick-6.4.0
安装结束后,拷贝jmagick-6.4.0.jar到$JAVA_HOMT/jre/lib/ext下,将jmagick-6.4.0.so拷贝到$JAVA_HOME/jre/lib/amd64下
4. 执行java程序,拼接图片,发现会有fatal error出现:反复测试发现setGeometry之后获取getGeometry出现数据不一致。
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f0d20471889, pid=11404, tid=139694626883328
#
# JRE version: 6.0_37-b06
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.12-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libMagickCore.so.1+0x131889]  imaginary long double+0x39
#
# An error report file with more information is saved as:
# /opt/deploy/papaq/papaq-pic/hs_err_pid11404.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.


或

java: magick/montage.c:425: MontageImageList: Assertion `montage_info->signature == 0xabacadabUL' failed. 

此时需要查看JMagick源码,实现在src/magick/jmagick.h的setstringmethod,此处set值可能有问题,重写实现代码,实现类:src/magick/magick_Montage.c,重写方法:
setStringMethod(Java_magick_MontageInfo_getGeometry,
  geometry,
  "montageInfoHandle",
  MontageInfo)

JNIEXPORT void JNICALL Java_magick_MontageInfo_setGeometry
(JNIEnv *env, jobject self, jstring geometryValue)
{
    MontageInfo *montageInfo = NULL;
    const char *cstr = NULL;
    
    montageInfo = (MontageInfo*) getHandle(env, self,
                                           "montageInfoHandle", NULL);
    
    if (montageInfo == NULL) {
        throwMagickException(env, "Unable to obtain MontageInfo handle");
        return;
    }
    
    cstr = (*env)->GetStringUTFChars(env, geometryValue, 0);
    strcpy(montageInfo->geometry, cstr);
    (*env)->ReleaseStringUTFChars(env, geometryValue, cstr);

}
重新编译,替换之前的so文件之后再测试,测试通过;