上篇文章所述,最近有一个项目,需要在linux环境下生成透明的gif图。考虑到画图的质量,采用了cairo来画图。但是cairo并没有gif格式,所以必须使用一个库来进行格式的转换。之前是采用cximage,千辛万苦编好cximage库之后(参考64位Linux下编译cximage动态库),悲催的发现,cximage的构造方法会使cairo绘图过程中无法分配内存。因此,不得不放弃cximage,寻找别的库。
很快,发现另外一个很强大的图像处理库ImageMagick,除了直接使用命令行来进行图像处理,还对C提供了一个API库供使用(参考官网关于API的介绍http://www.imagemagick.org/script/magick-wand.php?cm_mc_uid=55515229409514829062783&cm_mc_sid_50200000=1487237946)。遍寻网络,想走捷径,找到编好的so库,然而,残酷的事实证明,只能自己编译。花了将近一个星期,才编译好可用的库,过程如下:
1、下载可用的ImageMagick包,官网地址:http://www.imagemagick.org/script/install-source.php#unix,官网中不仅提供了下载地址,还有安装步骤。
需要注意的是,默认安装目录是/usr/local/。项目需要,我设置了自定义安装目录为/usr/。命令如下:
tar xvzf ImageMagick.tar.gz
cd ImageMagick-7.0.5
./configure --prefix=/usr
make
make install
convert --version
显示如下:
有时,可能会碰到显示连接不到动态库的错误,此时需要输入如下命令,即可
/sbin/ldconfig /usr/lib
请注意,我是自定义目录为/usr/lib。如果是默认 目录的,请输入
/sbin/ldconfig /usr/local/lib
2、由此安装结束。尝试通过命令行进行图片转换,查看是否有效:
convert 1.png 1.gif
这条命令的意思是将当前目录下1.png转换为1.gif。
然而,输入命令后显示错误:
no decode delegate for this image format PNG意思是 没有PNG这种格式。
出现这种类型的error时,需要自己安装一下缺失的格式包,可以通过安装二进制方式,也可以自己编译源代码。我选择的是编译源代码
下载页面地址:https://sourceforge.net/projects/libpng/files/。
下载最新版本libpng1.6.28,安装、编译后,运行
tar xvzf libpng-1.6.28.tar.xz
cd libpng-1.6.28
./configure --prefix=/usr
make
make install
实际上,在make时,我这里就出现了一个error:
我的zlib版本是1.2.11。
注意:安装成功后,需要重新安装imagemagick,进入imagemagick目录,清空之前的所有操作,然后重新make,命令如下:
make uninstall
make distclean
./configure --prefix=/usr
make
make install
3、基本工作算是完成了,接下来需要在我们的C程序中引用imagemagick API 方法了。
首先:在makefile中,引入imagemagick动态库,注意,在usr/lib目录下,可以看到生成了两个动态库,其中“libMagickCore-7.Q16HDRI.so”这个是底层库,
“libMagickWand-7.Q16HDRI.so”这个是提供了基本图像操作的API库,我们需要的就是这个库。
完整的makefile如下:
CC = gcc
XX = g++
LD = ld
AR = ar
CFLAGS = -fPIC -Wall -O -DLINUX -DPTHREADS
LDFLAGS = -shared -L/usr/lib64 -lcairo -ldl -lxml2 -lglib-2.0 -L/usr/lib -lMagickWand-7.Q16HDRI
ARFLAGS = -rcs
DIR_INC = ../include
DIR2_INC = ../include/glib-2.0
DIR3_INC = ../include/cairo
DIR4_INC = ../ImageMagick/ImageMagick-7.0.4-9
DIR2_LIB = ../Demo
DIR_SYS = /lib64
LIB_NAME = libs
INC = -I${DIR_INC} -I${DIR2_INC} -I${DIR3_INC} -I${DIR4_INC}
%.o:%.cpp
$(XX) $(CFLAGS) $(INC) -c $< -o $@
SOURCES = $(wildcard *.cpp)
OBJS = *.o
SHARE_LIB = $(LIB_NAME).so
DYNAMIC_LIB = $(LIB_NAME).a
all:$(OBJS)
$(LD) $(LDFLAGS) -o $(SHARE_LIB) $(OBJS)
#${AR} ${ARFLAGS} $(DYNAMIC_LIB) $(OBJS)
cp $(SHARE_LIB) $(DIR2_LIB)
cp $(SHARE_LIB) $(DIR_SYS)
#cp $(DYNAMIC_LIB) $(DIR2_LIB)
clean:
rm -rf *.o $(SHARE_LIB) $(DYNAMIC_LIB)
#include "MagickWand/MagickWand.h"
void ThrowWandException(MagickWand *wand)
{
char *description;
ExceptionType severity;
description=MagickGetException(wand,&severity);
printf(description);
printf("\n");
description=(char *) MagickRelinquishMemory(description);
}
void MakeSealTransparentAndConvertToGIF()
{
MagickBooleanType status;
MagickWand *magick_wand = NULL;
// Set default fuzz to zero (see below)
double fuzz = 0.;
PixelWand *target;
MagickWandGenesis();
magick_wand = NewMagickWand();
status = MagickReadImageBlob(magick_wand, eseal_data, eseal_data_length);
if (status == MagickFalse)
ThrowWandException(magick_wand);
// A larger fuzz value allows more colours "near" white to be
// modified. A fuzz of zero only allows an exact match with the
// given colour
fuzz = 10.;
// Set up the pixelwand containing the colour to be "targeted"
// by transparency
target = NewPixelWand();
PixelSetColor(target,"white");
// Change the transparency of all colours which match target (with
// fuzz applied). In this case they are made completely transparent (0)
// but you can set this to any value from 0 to 1.
status = MagickTransparentPaintImage(magick_wand,target,0,fuzz,MagickFalse);
if (status == MagickFalse)
ThrowWandException(magick_wand);
status = MagickWriteImage(magick_wand,"cairo2.gif");
if (status == MagickFalse)
ThrowWandException(magick_wand);
/* Clean up */
if(magick_wand)magick_wand = DestroyMagickWand(magick_wand);
if(target) target = DestroyPixelWand(target);
MagickWandTerminus();
}
最后,说句闲话。在网上看到过一个问题,是问cairo和ImageMagick这两个图像库,使用哪个更好。一个大牛最终总结:
Use Cairo if you need to do scalable vector graphics.
Use ImageMagick if you are ouputting to bitmap or raster formats.
实际中比较了一下,cairo绘图的效果确实是比imagemagick要好。这个就看实际项目需要吧。