StupidBeauty
Read times:3905Posted at: - no title specified

GIMP开发文档翻译:如何编写一个GIMP插件,How to write a GIMP plug-in

作者  Dave Neary

在这篇文档中,我会说明GIMP 插件相关的基础知识,并且介绍libgimp API。我还会说明,如何使用PDB 来让其它的插件作者也能利用我们的插件。

介绍

新来的开发者,经常会被GIMP 的体积和声望所吓住。他们觉得,编写一个插件,太困难了。这些文档的目的就是,展示给读者知道,编写一个C 插件有多么容易,以打消开发者们的这些念头。

在这个部分,我首先展示一个插件的基本元素。我们还将会看到,如何安装一个插件,以及,如何获取一张图片中的数据,如何直接操作图片。

架构

架构

GIMP 脚本接口,是围绕着过程数据库(Procedural database (PDB))而建立的。启动时,GIMP 会检查若干预定义的位置,以查找脚本和插件,并且要求每个新的脚本报上自己的信息。

插件就是在那个阶段向PDB 声明自己的存在,并且传递各个信息:它想要在菜单层级中出现的位置;输入参数;和输出参数。

如果哪个脚本或插件想要使用我们的插件,它会通过PDB来做到,PDB 会透明地管理好不同插件之间双向的参数传递过程。

那些想要被暴露给插件使用的内部函数,需要做两件事:首先要在核心中打包,以注册到PDB;然后要在libgimp 中注册,使得该函数能够当作普通函数被调用。

介绍完毕——现在,我们来仔细看看我们的第一个插件,一个“世界妳好!”。

编译插件

要想编译GIMP 的简单插件,妳需要libgimp 头文件,以及一个相关的工具,名为gimptool。

利用那个工具,妳可以将插件安装到一个私有目录(~/.gimp-2.0/plug-ins),或者安装到全局的插件目录。

语法如下

gimptool-2.0 --install plugin.c gimptool-2.0 --install-admin plugin.c

在传入其它参数的情况下,也可以利用这个工具来安装脚本或者卸载插件。

行为

一般情况下,单个GIMP 插件可能表现出三种不同的行为。它可以接收图片数据输入,对该数据进行修改,然后将修改过的图片返回,例如边缘检测。它可以生成一张图片,然后将该图片返回,例如某些script-fu脚本,或者文件输入插件(例如jpeg)。或者,它可以获取一张图片,然后在不修改数据的情况下对该图片进行处理,例如一个文件保存插件。

必写代码

#include <libgimp/gimp.h>

这个头文件中,包含了我们所需要的所有基本插件元素。

GimpPlugInInfo PLUG_IN_INFO = {

init,

quit,

query,

run

};

这个结构体,必须定义成这个名字。它包含了四个函数指针,那些函数会在插件生命周期的适当时机被调用。init 和quit 是可选的,因而可以写成NULL,但是,后面两个函数,query 和run,是必选的。

每当GIMP 启动的时候,都会调用init()函数。一般情况下,这个函数不会被用到。某些插件,会利用这个函数来进行一次额外的搜索,以完成某些未被核心程序完成的事。标准的GIMP 插件中,都不会使用这个函数。不过,在某些情形下使用这个函数还是狠有用的,例如,某个插件,要根据某些文件的存在性来决定是否要注册某些过程。

同样地,quit()函数用得也不多。在 GIMP 即将关闭时,会调用这个函数,以便释放某些资源。script-fu 插件中会使用这个函数。

当插件第一次出现时,query()函数会被调用,之后,每当该插件发生变动时会再次调用此函数。

run()函数是每个插件的中心部分。每当需要该插件运行的时候,就会调用该函数。它会做这么多事:获取插件名字(因为,一个插件可以注册多个过程);获取输入参数;获取指向输出参数的指针;确定它是运行于交互模式还是被脚本运行;最后,做出该插件该做的所有事。它的原型如下

void run (const gchar      *name,

gint              nparams,

const GimpParam  *param,

gint             *nreturn_vals,

GimpParam       **return_vals);

MAIN ()

MAIN 是一个C 语言宏,其内部有某些黑科技,使得它能够用来初始化各个参数。另外,它会在适当的时机调用PLUG_IN_INFO 中对应的函数。妳的插件中,需要这个宏。

query()函数

query()处理的是,过程的注册和输入参数的定义。这些信息会被储存起来,以加快启动过程,日后,只在插件被修改的时候才刷新。

对于我们的“世界,妳好!”插件,查询(query)函数会是这样的:

static void

query (void)

{

static GimpParamDef args[] = {

{

GIMP_PDB_INT32,

"run-mode",

"Run mode"

},

{

GIMP_PDB_IMAGE,

"image",

"Input image"

},

{

GIMP_PDB_DRAWABLE,

"drawable",

"Input drawable"

}

};

gimp_install_procedure (

"plug-in-hello",

"Hello, world!",

"Displays \"Hello, world!\" in a dialog",

"David Neary",

"Copyright David Neary",

"2004",

"_Hello world...",

"RGB*, GRAY*",

GIMP_PLUGIN,

G_N_ELEMENTS (args), 0,

args, NULL);

gimp_plugin_menu_register ("plug-in-hello",

"/Filters/Misc");

}

GimpParamDef包含着三样信息——参数类型、名字、以及一个用来描述参数的字符串。

gimp_install_procedure声明了以下东西:过程名字;一些描述字符串和帮助字符串;要放置插件入口的菜单路径;该插件所处理的图片类型;输入/输出参数的个数;后参数本身的描述符。

"RGB*, GRAY*"声明的就是插件能够处理的图片类型。它可以是RGB、INDEXED 或GRAY,并且还可以带上透明值(Alpha)。因此,"RGB*, GRAY*"表示的是,RGB、 RGBA、GRAY 或GRAY 图片类型。

GIMP_PLUGIN声明了这个过程是外部过程,因而不应当在GIMP 核心中执行。

现在,我们先写上一个原始的run 函数,以确保我们的插件具有所有的必要元素,并且通过"Xtns->Plug-in Details"插件来检测出它是否已经在PDB 中注册了自身。

插件详情

我们的插件已经出现在菜单中

run()函数

PLUG_IN_INFO 中的另一个必写的函数是run。插件的核心功能就位于这个函数里。

输出值中(即,原型中的return_vals),必须最少关联一个值——插件的状态值。一般情况下,这个参数的值会是"GIMP_PDB_SUCCESS"。

运行模式

插件可以以多种模式运行:当GIMP 处于交互模式时,可以通过GIMP 菜单来运行它;也可通过脚本或批处理来运行它;或者,通过“滤镜->重复上次”快捷方式来运行它。

“运行模式”("run_mode")这个输入参数,可以取以下取值:"GIMP_RUN_INTERACTIVE"、"GIMP_RUN_NONINTERACTIVE"或"GIMP_RUN_WITH_LAST_VALS"。

一般情况下,"GIMP_RUN_INTERACTIVE"是唯一一种需要创建选项对话框的情形。其它情况下,应当直接使用来自输入参数或内存的值来进行处理。

在我们的尝试型插件中,我们只是简单地显示出一个包含“世界妳好!”("Hello, world!")消息的对话框。幸运的是,这在GTK+中狠容易实现。我们的run 函数是这样的:

static void

run (const gchar      *name,

gint              nparams,

const GimpParam  *param,

gint             *nreturn_vals,

GimpParam       **return_vals)

{

static GimpParam  values[1];

GimpPDBStatusType status = GIMP_PDB_SUCCESS;

GimpRunMode       run_mode;

/* 设置必要的输出值 */

*nreturn_vals = 1;

*return_vals  = values;

values[0].type = GIMP_PDB_STATUS;

values[0].data.d_status = status;

/* 获取运行模式(run_mode)——如果我们是处于“非交互”(NONINTERACTIVE)模式,

* 则不显示对话框 */

run_mode = param[0].data.d_int32;

if (run_mode != GIMP_RUN_NONINTERACTIVE)

g_message("Hello, world!\n");

}

现在,当我们运行这个插件的时候,会产生效果:

参考一下完整的 hello.c 插件代码。

下一部分

下一部分 中,我们会再进一步,编写一个更有用处的插件,它会对图片数据进行操作。 我们将会学习到,如何利用GIMP 的图片架构来提升该插件的性能,将图片一砣砣地处理。

李亮瑾

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands