[ImageMagick 学习] Fred's ImageMagick Scripts 转 C++ 的统一解决方案

来源:互联网 发布:ubuntu开机启动脚本 编辑:程序博客网 时间:2024/06/08 19:14

曾经遇到这样一些问题:

  1. Fred's ImageMagick Scripts 提供的脚本,很好很强大,但是不能直接被C++程序调用,并且有license 问题,如果能转译成C++ 版就好了。怎么转译?
  2. Fred's ImageMagick Scripts 提供的脚本很丰富,如果在做“Shell 脚本-> C++代码”转译过程中,对这些脚本没有一个统一的解决方案,而是把每个脚本都当成一个特例来对待,那工作量是巨大的。怎样将转译的工作量降至最低而又不损失代码执行效率?

根据 ImageMagick 命令的中间操作结果 的介绍,答案是:

不要按照Fred's ImageMagick Scripts 脚本中的方法,多次调用convert 命令(即在C++代码中多次调用ConvertImageCommand() 函数),而是参考Fred's ImageMagick Scripts 每个特效的页面的最后一段文字中介绍的等价命令行,写出对应的命令行字符串,作为参数传给下面代码中的 IM_Convert() 函数。就这么简单!

例如,要消除mf-small.jpg 图片中的背景噪声,保存成mf-small-out.jpg,我们临摹 TEXTCLEANER 脚本等价命令行

convert \( $infile -colorspace gray -type grayscale -contrast-stretch 0 \) \\( -clone 0 -colorspace gray -negate -lat ${filtersize}x${filtersize}+${offset}% -contrast-stretch 0 \) \-compose copy_opacity -composite -fill "$bgcolor" -opaque none +matte \-deskew 40% -sharpen 0x1 $outfile
即传给IM_Convert() 函数的字符串是:
convert ( mf-small.jpg -colorspace gray -type grayscale -contrast-stretch 0 ) ( -clone 0 -colorspace gray -negate -lat 25x25+10% -contrast-stretch 0 ) -compose copy_opacity -composite -fill \"white\" -opaque none +matte -deskew 40% -sharpen 0x1 mf-small-out.jpg
示例代码:

#include <wand/MagickWand.h>#include <string>#include <vector>#include <sstream>#include <iostream>#include <string.h>#include <stdlib.h>using namespace std;void AllocArg(const char* cmd, int &argc, char** &argv) {istringstream issCmd(cmd);string sPara;vector<string> vParas;argc = 0;while(issCmd >> sPara) {vParas.push_back(sPara);++argc;}argv = (char**)malloc(argc * sizeof(char*));for(int i = 0; i < argc; ++i) {argv[i] = (char*)malloc(vParas[i].size() + 1);strcpy(argv[i], vParas[i].c_str());}}void FreeArg(int &argc, char** &argv) {if(argv != NULL) {for(int i = 0; i < argc; ++i) {free(argv[i]);}free(argv);argv = NULL;}}MagickBooleanType IM_Convert(const char* cmd) {char** argv = NULL;int argc = 0;AllocArg(cmd, argc, argv);ExceptionInfo *exception = NULL;ImageInfo *image_info = NULL; MagickBooleanType status = MagickTrue;MagickCoreGenesis(*argv, MagickTrue);exception = AcquireExceptionInfo();image_info = AcquireImageInfo();status = MagickCommandGenesis(image_info, ConvertImageCommand, argc, argv, (char **) NULL, exception);image_info = DestroyImageInfo(image_info);exception = DestroyExceptionInfo(exception);MagickCoreTerminus();FreeArg(argc, argv);return(status);}int main(int argc, char* argv[]){IM_Convert("convert ( mf-small.jpg -colorspace gray -type grayscale -contrast-stretch 0 ) ""( -clone 0 -colorspace gray -negate -lat 25x25+10% -contrast-stretch 0 ) ""-compose copy_opacity -composite -fill white -opaque none +matte ""-deskew 40% -sharpen 0x1 mf-small-out.jpg");}

Makefile:

all:        g++ -o im -g `pkg-config --cflags --libs MagickWand` main.cppclean:        rm -f im

注意:

  1. 传给IM_Convert() 的参数字符串有可能也是动态生成的,比如里面的某些参数的取舍、参数值的计算等。对于这些动态因素,可以在IM_Convert() 的外面再封一层函数,用于取舍参数、计算参数值等,最终动态生成命令行字符串,传给IM_Convert()。喜欢玩设计模式的同学,可以在这里发挥特长了。
  2. 上面的动态生成命令行字符串,用stl 的stringstream 就好了。
  3. 其实这样做还是有些多余计算量的——动态生成命令行字符串、解析字符串、销毁解析出来的参数,不过这些消耗相比ConvertImageCommand() 函数本身的计算量,可以忽略不计了。
  4. 既然ConvertImageCommand() 函数提供了临时变量处理、出栈入栈等玩法,我们就没有必要自己重新再做一套类似的东西了。不要想着再从底层做起,一点点地抠代码,定制一个“紧凑小巧高性能” 的自定义图像处理特效函数了,那样做,会得不偿失的……
  5. 命令行中的"\(" 和 "\)" 前后都要有空格,否则ImageMagick 命令不认!这个硬性规定,同样也适用于IM_Convert(),即该函数的输入字符串中的"\(" 和 "\)" 前后都要有空格的!
  6. 这里说的“统一解决方案”,说白了就是,convert 命令调用 ConvertImageCommand(ImageInfo *image_info, int argc,char **argv,char **metadata,ExceptionInfo *exception) 函数,我们的程序也调用它;不同的是前者是给脚本用的,后者给C 程序调用,并且只需要传入一个字符串(命令行)参数。
  7. 这里有对Android 版的ImageMagick 的一些介绍,但貌似每一种特效,都要自己写一堆Java 代码
  8. 对于下面的命令行,在终端直接运行OK,放到IM_Convert() 运行就有下面的错误提示。后来将传给IM_Convert() 的字符串中的 \"white\" 改成 white 就OK了。事实上,命令行中的 "white" 前后带或者不带双引号都是可以的,但传给IM_Convert() 的字符串中不要带,否则ConvertImageCommand() 函数要解析的参数还带着前后的双引号,会让ConvertImageCommand() 找不到匹配项的,从而发生错误。
传给IM_Convert() 的命令行:

convert ( mf-small.jpg -colorspace gray -type grayscale -contrast-stretch 0 ) ( -clone 0 -colorspace gray -negate -lat 25x25+10% -contrast-stretch 0 ) -compose copy_opacity -composite -fill \"white\" -opaque none +matte -deskew 40% -sharpen 0x1 mf-small-out.jpg
错误提示:

im: unable to open image `"white"': No such file or directory @ error/blob.c/OpenBlob/2641.im: no decode delegate for this image format `"white"' @ error/constitute.c/ReadImage/550.


原创粉丝点击