<?xml version='1.0'?>
<!DOCTYPE book PUBLIC "-//Norman Walsh//DTD DocBk XML V3.1.3//EN"
                      "dtd/docbook-xml/docbookx.dtd" [
<!ENTITY gimp "<application><acronym>GIMP</acronym></application>">
<!ENTITY gimph '<ulink url="http://cvs.gnome.org/lxr/source/gimp/libgimp/gimp.h">gimp.h</ulink>'>
<!ENTITY enumsh '<ulink url="http://cvs.gnome.org/lxr/source/gimp/libgimp/gimp.h">gimpenums.h</ulink>'>
<!ENTITY OC "<acronym>OC</acronym>">
<!ENTITY glossary SYSTEM "glossary.xml">
<!ENTITY opl SYSTEM "opl.xml">
<!ENTITY genindex SYSTEM "genindex.xml">
]>
<book>
  <bookinfo> 
    <title>Writing a &gimp; Plug-In</title>
    <author>
      <surname>Turner</surname>
      <firstname>Kevin</firstname>
    </author>
    <affiliation>
      <address><email>acapnotic@users.sourceforge.net</email></address>
    </affiliation>
    <copyright>
      <year>1998-2000</year>
      <holder>Kevin Turner</holder>
    </copyright>
    
    <!-- legalnotice is the OPL -->
    &opl;
  </bookinfo>
  
  <chapter id="chapt-intro">	     
    <title>Introduction</title>
    
    <para>This document is based on my experiences of writing plug-ins
    for the 
      <application><acronym>GNU</acronym> Image Manipulation Program</application>
      in C.  Much of this document is likely relevant to &gimp;
      plug-ins in other languages, but I'm too much of a monoglot to
      know for sure.  A basic working knowledge of C is assumed, but
      extensive experience isn't necessary.</para>

    <formalpara>
      <title>The Source is Your Friend Too</title>
      
      <para>This document contains frequent code snippits, but to get
      any context, you'll probably want to be working through (reading
      and/or writing) some plug-in code alongside it. <ulink url=
      "mailto:meo@netads.com" >Miles O'Neal</ulink> has <ulink url=
      "http://www.rru.com/~meo/gimp/rand-noted.c" >extensively
      annotated his randomize plug-in</ulink>, making it a good place
      to start.  You may want to look at several &mdash; each one will
      have their own peculiar parts that they've done well or poorly
      on.</para>
    </formalpara>
    
    <section id="sect-status">
      <title>Status of this Document</title> 
      
      <para>This document was authored for version 1.0 of &gimp;.  But
      now &gimp; 1.1 is now frozen and on its glacial journey towards
      the 1.2 release.  There have been a few changes and a
      considerable number of additions to libgimp which have yet to
      been documented here.  While that makes this somewhat out of
      date at current, it is still reasonably accurate, and may serve
      as an overview for getting started with your plug-in.
      </para>

      <para>In addition, two valueable new resources have been
      created.  One is the libgimp reference documentation, which
      documents all the functions in the current libgimp.  It is
      distributed in the <filename class="directory"
      >devel-docs</filename> directory of the &gimp; distribution, and
      is also <ulink url=
      "http://gimp-plug-ins.sourceforge.net/doc/libgimp/" >available
      on-line</ulink>.  The second is the &gimp; plug-in template,
      which contains a skeleton of all the files you need to get
      started on you own plug-in, including support for
      <application>autoconf</application>, internationalization using
      <application>gettext</application>, and &gimp;'s on-line help
      system. It's available as the <filename class="directory"
      >gimp-plugin-template</filename> module in the <ulink
      url="http://developer.gnome.org/tools/cvs.html" >GNOME CVS
      repository</ulink> and is mirrored by <ulink
      url="http://sourceforge.net/cvs/?group_id=1850" >&gimp; plug-ins
      CVS</ulink>.</para>

    </section>
    
    <section id="sect-styles">
      <title>Styles in this Document</title>
      
      <para>Depending on your output medium's implementation of style
      sheets, you may notice different parts of this document have
      different styles.</para>
      
      <informalfigure>      
	<programlisting format="linespecific">
printf("This code was quoted from the GIMP sources.");
/* This is a comment in the source code. */
	</programlisting>
      </informalfigure>

      <informalexample>
	<programlisting format="linespecific">
printf("This is example code to illustrate a point.");
/* This is a comment in the source code. */
	</programlisting>
      </informalexample>

      <para>References to the &gimp; source code are linked to the
	<ulink url="http://cvs.gnome.org/lxr/" >LXR engine at
      cvs.gnome.org</ulink>.  Caution: That may be a newer version of
      the source than is is use by the general public, but I couldn't
      find anything else to link to.  If you're developing for the
      stable version of &gimp;, check your own copy of the source.
      Also, line numbers may have changed since I established the
      links &hellip; If you find that to be the case, please <ulink
      url = "mailto:acapnotic@users.sourceforge.net" >let me
      know</ulink>.</para>

      </section>
    </chapter>

  <chapter id="sect-essentials">
    <title>Essentials of a Plug-in</title>
      
    <para>There are some things every plug-in simply
    <emphasis>must</emphasis> have if it is to be considered a
    plug-in, no matter what its purpose.  Mainly, the plug-in has to
    register itself in the &gimp;'s procedure database, and it has to
    have a function to run when &gimp; calls for that procedure.  Here
    we'll look at how these functions are called, and just what
    components they really need.</para>

    <section id="sect-main">
      <title><symbol>MAIN</symbol></title>
	    
      <indexterm significance="preferred" zone="sect-main" id="idx-sect-main">
	<primary>main()</primary>
      </indexterm>
  
      <para>Every C program has a <function>main()</function> function
      &mdash; the first function that is called when the program is
      executed.  The typical &gimp; plug-in's main function is, in its
      entirety, as follows:</para>
	
      <programlisting>
	<symbol>MAIN</symbol>()
      </programlisting>
	  
      <para><symbol>MAIN</symbol> is a macro, defined in <ulink url=
      "http://cvs.gnome.org/lxr/source/gimp/libgimp/gimp.h"
      >libgimp/gimp.h</ulink>, which calls a
      <function>gimp_main</function> function, which in turn does all
      sorts of neat stuff.  It tries to make sure the plug-in is being
      called by &gimp;, sets up some signal handling, sets up
      communication between the plug-in and &gimp;, and queries the
      plug-in if need be.</para>

      <para>&gimp; queries plug-ins on start-up, and it expects them
      to register themselves in the <glossterm linkend="gloss-pdb"
      >procedural database</glossterm> (<acronym>PDB</acronym>).  But
      how does &gimp; know what function to call when it queries?  It
      checks the value of the global variable
      <varname>PLUG_IN_INFO</varname>, of type
      <type>GimpPlugInInfo</type>.  From &gimph;:</para>

      <figure float="0">
	<title>The GimpPlugInInfo Structure</title>
	
<programlisting format="linespecific">
typedef void (* GimpInitProc)  (void);
typedef void (* GimpQuitProc)  (void);
typedef void (* GimpQueryProc) (void);
typedef void (* GimpRunProc)   (gchar      *name,
                                gint        nparams,
                                GimpParam  *param,
                                gint       *nreturn_vals,
                                GimpParam **return_vals);

struct _GimpPlugInInfo
{
  /* called when the gimp application initially starts up */
  GimpInitProc  init_proc;

  /* called when the gimp application exits */
  GimpQuitProc  quit_proc;

  /* called by the gimp so that the plug-in can inform the
   *  gimp of what it does. (ie. installing a procedure database
   *  procedure).
   */
  GimpQueryProc query_proc;

  /* called to run a procedure the plug-in installed in the
   *  procedure database.
   */
  GimpRunProc   run_proc;
};
</programlisting>	
	</figure>

      <para>So <varname>PLUG_IN_INFO</varname> consists of pointers to
      four functions.  The first two are ran when &gimp; starts and
      exits, not commonly used among the plug-ins, and so are usually
      set to <symbol>NULL</symbol>.  The third is the
      <function>query</function> function, which many plug-in authors
      have chosen to name <function>query()</function>.  The fourth is
      called when the plug-in's procedure is to be run, and is,
      surprisingly enough, often called <function>run()</function>.
      An example:</para>

      <example>
	<title>Defining PLUG_IN_INFO</title>
<programlisting format="linespecific">
/* Function prototypes */
static void query (void);
static void run (gchar      *name,
		 gint        nparams,
		 GimpParam  *param,
		 gint       *nreturn_vals,
		 GimpParam **return_vals);

/* Setting PLUG_IN_INFO */
GimpPlugInInfo PLUG_IN_INFO =
{
  NULL,    /* init_proc */
  NULL,    /* quit_proc */
  query,   /* query_proc */
  run,     /* run_proc */
};
</programlisting>
	</example>

    </section><!-- MAIN -->
    
    <section id="sect-query-proc">
      <title>The Query Procedure</title>
	
      <para>As mentioned, &gimp; expects plug-ins to register
      themselves in the PDB when they're queried. This is done through
      <function>gimp_install_procedure</function> (again, from
      &gimph;):</para>

      <figure float="0">
	<title>gimp_install_procedure</title>
	  <funcsynopsis>
	    <funcdef>void <function>gimp_install_procedure</function></funcdef>
	    <paramdef>char* <parameter>name</parameter></paramdef>
	    <paramdef>char* <parameter>blurb</parameter></paramdef>
	    <paramdef>char* <parameter>help</parameter></paramdef>
	    <paramdef>char* <parameter>author</parameter></paramdef>
	    <paramdef>char* <parameter>copyright</parameter></paramdef>
	    <paramdef>char* <parameter>menu_path</parameter></paramdef>
	    <paramdef>char* <parameter>image_types</parameter></paramdef>
	    <paramdef>GimpPDBProcType <parameter>type</parameter></paramdef>
	    <paramdef>int <parameter>nparams</parameter></paramdef>
	    <paramdef>int <parameter>nreturn_vals</parameter></paramdef>
	    <paramdef>GimpParamDef* <parameter>params</parameter></paramdef>
	    <paramdef>GimpParamDef* <parameter>return_vals</parameter></paramdef>
	</funcsynopsis>
      </figure>

      <para>Parameters <parameter>name</parameter> through
      <parameter>date</parameter> should be fairly self-explanatory.
      On the rest, I'll make some comment:
	<comment>
	<indexterm><primary>FIXME</primary><secondary>callout</secondary>
	</indexterm>
	  The following list should be a callout list to the
	  programlisting above.</comment>
      </para>

      <variablelist>
	<varlistentry>
	  <term><parameter>menu_path</parameter></term>
	  <listitem>
	    <para>A string describing where in the menu the procedure
	    should be installed. It begins with one of
	    &lt;Toolbox&gt;, &lt;Image&gt;, &lt;Load&gt;, or
	    &lt;Save&gt;, followed by the menu path. For example, the
	    Maze plug-in's menu_path is <quote
	    >&lt;Image&gt;/Filters/Render/Patterns/Maze...</quote
	    >.</para>
	    
	    <para>&gimp; uses this information not only to place the
	    menu, but also to decide what type of procedure it
	    is. This affects its decision on which parameters are
	    necessary for the procedure. Note also that a
	    <parameter>menu_path</parameter> isn't required if you
	    wish to install a procedure without one, but that's not
	    the case for most plug-ins.</para>

	    <para>Source reference: 
	      <indexterm significance="normal"><primary>FIXME</primary>
		<secondary>source ref</secondary>
	      </indexterm>	
	      app/plug_in.c,
	    plug_in_handle_proc_install</para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>image_types</term>
	  <listitem>
	    <para>A string listing what image types the plug-in will
	    accept; any of RGB, RGBA, RGB*, GRAY, GRAYA, GRAY*,
	    INDEXED, INDEXEDA, INDEXED*.  RGB* is simply shorthand for
	    both RGB and RGBA (same applies for GRAY* and
	    INDEXED*). The list may be separated by spaces, tabs, or
	    commas. Example: <quote>RGB*, INDEXED</quote> means the
	    plug-in likes all RGB images (with or without alpha),
	    indexed-color images (only without alpha), but not
	    grayscale images of any sort.</para>

	    <para>Source reference: app/plug_in.c,
	      <indexterm significance="normal"><primary>FIXME</primary>
		<secondary>source ref</secondary>
	      </indexterm>	
	    plug_in_image_types_parse</para>

	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>nparams, nreturn_vals</term>

	  <listitem><para>The number of parameters (or return values)
	  the procedure uses.</para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>nparams, nreturn_vals</term>
	  <listitem><para>See below.</para>
	  </listitem>
	</varlistentry>
      </variablelist>

      <section id="sect-pdb-params">
	<title>PDB Parameters</title>
	
	<para><parameter>*params</parameter> points to an array of
	parameter definitions.  <parameter>nparams</parameter> is an
	integer that tells the number of parameters (equal to the
	length of the array).  A parameter definition is of type
	<type>GimpParamDef</type>, which has three parts &gimph;:</para>

	<informalfigure>
	  <programlisting format="linespecific">
struct _GimpParamDef
{
  GimpPDBArgType  type;
  gchar          *name;
  gchar          *description;
};
	    </programlisting>
	</informalfigure>

	<para>Values for GimpPDBArgType are listed in &enumsh;.  Setting
	up parameters can be done like so:</para>

	<example>
	  <title>Establishing an array of parameters.</title>
	  <programlisting format="linespecific">
static GParamDef params[] =
  {
    { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
    { GIMP_PDB_IMAGE, "image_id", "(unused)" },
    { GIMP_PDB_DRAWABLE, "drawable_id", "Drawable to draw on" },
    { GIMP_PDB_COLOR, "fgcolor",  "Color to draw with"}
  }
	  </programlisting>
	</example>

	<para>You may be <emphasis>required</emphasis> to take certain
	parameters, depending on where in the menu you registered.
	You may ignore them once you get them, but they will be passed
	to you, so you must accept them nonetheless.  (app/plug-in.c,
	plug_in_handle_proc_install):
	  <indexterm significance="normal"><primary>FIXME</primary>
	    <secondary>source ref</secondary>
	  </indexterm>	
	</para>

	<table>
	  <title>Menu locations and required parameters</title>
	  <tgroup cols="4">
	    <thead>
	      <row>
		<entry>Menu Location</entry>
		<entry>#</entry>
		<entry>Parameter type</entry>
		<entry>Description</entry>
	      </row>
	    </thead>
	    <tbody>
	      <row>
		<entry>&lt;Toolbox&gt;</entry>
		<entry>0</entry>
		<entry><type>INT32</type></entry>
		<entry>run mode</entry>
	      </row>
	      <!-- Image -->
	      <row>
		<entry morerows="2">&lt;Image&gt;</entry>
		<entry>0</entry>
		<entry><type>INT32</type></entry>
		<entry>run mode</entry>
	      </row>
	      <row>
		<entry>1</entry>
		<entry><type>IMAGE</type></entry>
		<entry>ID of current image</entry>
	      </row>
	      <row>
		<entry>2</entry>
		<entry><type>DRAWABLE</type></entry>
		<entry>ID of current drawable</entry>
	      </row>
	      <!-- Load -->
	      <row>
		<entry morerows="2">&lt;Load&gt;</entry>
		<entry>0</entry>
		<entry><type>INT32</type></entry>
		<entry>run mode</entry>
	      </row>
	      <row>
		<entry>1</entry>
		<entry><type>STRING</type></entry>
		<entry>FIXME
		  <indexterm><primary>FIXME</primary><secondary>Load string</secondary></indexterm>
		</entry>
	      </row>
	      <row>
		<entry>2</entry>
		<entry><type>STRING</type></entry>
		<entry>FIXME
		  <indexterm><primary>FIXME</primary><secondary>Load string</secondary></indexterm>
		</entry>
	      </row>
	      <!-- Save -->
	      <row>
		<entry morerows="4">&lt;Save&gt;</entry>
		<entry>0</entry>
		<entry><type>INT32</type></entry>
		<entry>run mode</entry>
	      </row>
	      <row>
		<entry>1</entry>
		<entry><type>IMAGE</type></entry>
		<entry>ID of current image</entry>
	      </row>
	      <row>
		<entry>2</entry>
		<entry><type>DRAWABLE</type></entry>
		<entry>ID of current drawable</entry>
	      </row>
	      <row>
		<entry>3</entry>
		<entry><type>STRING</type></entry>
		<entry>FIXME
		  <indexterm><primary>FIXME</primary><secondary>Save string</secondary></indexterm>
		</entry>
	      </row>
	      <row>
		<entry>4</entry>
		<entry><type>STRING</type></entry>
		<entry>FIXME
		  <indexterm><primary>FIXME</primary><secondary>Save string</secondary></indexterm>
		</entry>
	      </row>
	    </tbody>
	  </tgroup>
	</table>
	   
	<para>You may take any parameters you like in addition to the
	ones required.  The required parameters must come first and in
	order, however.</para>

	<para>Declaring return values works much the same way, with
	one note: Your procedure will have at least one return value
	(a status code), but that should not be counted in your
	<parameter>nreturn_vals</parameter> or included in your <type
	>GParamDef</type> <parameter >return_vals</parameter>.</para>

	</section><!-- PDB Parameters -->
      </section><!-- Query Procedure -->
	  
    <section id="sect-run-proc" >
      <title>The Run Procedure</title>
      <informalfigure>
	<programlisting format="linespecific">
/* called to run a procedure the plug-in installed in the
 *  procedure database.
 */
typedef void (* GimpRunProc)   (gchar      *name,
                                gint        nparams,
                                GimpParam  *param,
                                gint       *nreturn_vals,
                                GimpParam **return_vals);
	</programlisting>
      </informalfigure>

      <para>The run procedure is where the action begins.  Its
      responsibilities include making sure the plug-in was called
      correctly and setting return values, as well as making sure that
      your plug-in does whatever it is that it's supposed to
      do.</para>

      <note>
	<title>&gimp; 1.1 Compatibility Note</title>

	  <para>In &gimp; 1.1, the run parameter is <emphasis
	  >always</emphasis> called with nparams == 3, when called in
	  the normal interactive fashion (plug_in_callback,
	  app/plug_in.c).
	    <indexterm><primary>FIXME</primary><secondary>source ref</secondary></indexterm>

	    This differs from &gimp; 1.0 behaviour, where nparams was
	    equal to whatever it was set to upon installation of the
	    procedure in the query function.</para>
      </note>      

	<section id="sect-gparam">
	  <title>GimpParam</title>
	<informalfigure>
	  <programlisting>
struct _GimpParam
{
  GimpPDBArgType type;
  GimpParamData  data;
};
	  </programlisting>
	</informalfigure>
	<informalfigure>
	  <programlisting>
union _GimpParamData
{
  gint32            d_int32;
  gint16            d_int16;
  gint8             d_int8;
  gdouble           d_float;
  gchar            *d_string;
  gint32           *d_int32array;
  gint16           *d_int16array;
  gint8            *d_int8array;
  gdouble          *d_floatarray;
  gchar           **d_stringarray;
  GimpParamColor    d_color;
  GimpParamRegion   d_region;
  gint32            d_display;
  gint32            d_image;
  gint32            d_layer;
  gint32            d_layer_mask;
  gint32            d_channel;
  gint32            d_drawable;
  gint32            d_selection;
  gint32            d_boundary;
  gint32            d_path;
  gint32            d_unit;
  GimpParasite      d_parasite;
  gint32            d_tattoo;
  gint32            d_status;
};
	  </programlisting>
	</informalfigure>

	<para>Note that GimpParamData is a union, not a structure.  It
	only holds one value at a time.</para>

	</section><!-- GParam -->
      <section id="sect-returnvals">
	<title>Return values</title>
	<para>It's expected (in app/procedural_db.c 
	  <indexterm><primary>FIXME</primary><secondary>source ref</secondary></indexterm>

	  that you return a status code as the first return value (the
	  zeroth in C land).  That's a <type>GimpPDBArgType</type> of
	  <constant>GIMP_PDB_STATUS</constant>, and a value from
	  <type>GimpPDBStatusType</type>
	  (<constant>GIMP_PDB_EXECUTION_ERROR</constant>, 
	  <constant>GIMP_PDB_CALLING_ERROR</constant>,
	  <constant>GIMP_PDB_PASS_THROUGH</constant>, 
	  <constant>GIMP_PDB_SUCCESS</constant>), or
	  <constant>GIMP_PDB_CANCEL</constant>).
	</para>

	</section><!-- Return values -->
      </section><!-- Run Procedure -->
      
      <section id="sect-review-essentials">
	<title>Review</title>
	<para>What every plug-in needs:</para>
      
      <orderedlist inheritnum="ignore" continuation="restarts">
	<listitem>
	  <simpara>#include &lt;libgimp/gimp.h&gt;</simpara>
	</listitem>
	<listitem><simpara>PLUG_IN_INFO</simpara></listitem>
	<listitem><simpara>MAIN</simpara></listitem>
	<listitem>
	  <simpara>A <function>query</function> function, with a call
	    to <function>gimp_install_procedure</function>.</simpara>
	</listitem>
	<listitem>
	  <simpara>A <function>run</function> function, setting a status code return value.</simpara>
	</listitem>
      </orderedlist>
      
    </section><!-- Review -->

    <section id="sect-run-advice">
      <title>Run: More details</title>

      <para>We've said what's required.  Now, what's a good idea?
      This section previously contained some well-intentioned
      practical advise on how to implement what you just learned, but
      it was so terribly written that I can't bear to bring it back.
      So for learning about implementations, I'm afraid you'll be
      <emphasis>much</emphasis> better off reading source code until
      this gets re-written.</para>

      <para>Move on to the next section to learn more
      things&hellip;</para>

      </section>

    </chapter><!-- Essentials -->

    <chapter id="sect-image">
      <title>Working with the Image</title>

      <para>A plug-in is of limited use if it has nothing to do with
      the image. In this section, we explore the exciting world of the
      &gimp; image hierarchy, and learn how to manipulate it.</para>
      
    <section id="sect-image-intro">
      <title>Intro to Images</title>
      
	<blockquote id="book-of-wilber">
	  <para>In the beginning, there was Wilber, Wilber the
	  gimp. The graphic was without form and void, and darkness
	  was upon the face of the desktop, and the Spirit of Wilber
	  was moving over the face of the bitstream.</para>

	  <para>And Wilber said,
	  <quote>&lt;Toolbox&gt;/File/New,</quote> and there was an
	  image. And Wilber saw that the image was good, and Wilber
	  separated the image into drawables. And Wilber looked down
	  at what he had wrought, and Wilber said, <quote>Oh
	  golly.</quote>
	  For Wilber had made the drawables of the layer according to
	  their kinds, and the drawables of the channel according to
	  their kinds, and the drawables of the mask according to
	  their kinds &hellip;</para>
	
      </blockquote>

      <para>&hellip; or you could look at it the other way around.  We
      have all sorts of silly things like masks, channels, and layers,
      but they're all just a bunch of pixels that can be drawn on, so
      we treat them much the same and lump them all in to the category
      of <quote>drawables</quote>.  And an image, then, is just what
      you get when you put some drawables together.</para>

      <para>Most plug-ins care suprisingly little about these images.
      After all, it's the bunch of pixels on the drawable most of them
      are playing with.  In any case, the most complex data structure
      a plug-in uses for an image is an integer (<type>gint32</type>),
      a simple ID by which the &gimp; knows that image.</para>

      <para>Drawables make life much more exciting.  You have to stay
      on your toes about which data type a function uses, a
      <type>gint32</type> for the drawable's ID, or a
      <type>GimpDrawable</type>, or a pointer to one.  Here's the
      <type>GimpDrawable</type> type (from &gimph;):</para>

      <figure>
	<title>GimpDrawable Definition</title>
	<programlisting>
struct _GimpDrawable
{
  gint32    id;            /* drawable ID */
  guint     width;         /* width of drawble */
  guint     height;        /* height of drawble */
  guint     bpp;           /* bytes per pixel of drawable */
  guint     ntile_rows;    /* # of tile rows */
  guint     ntile_cols;    /* # of tile columns */
  GimpTile *tiles;         /* the normal tiles */
  GimpTile *shadow_tiles;  /* the shadow tiles */
};
	</programlisting>
      </figure>

      <para>(Don't worry about the tile fields, you shouldn't have to
	deal with those directly.)</para>

      <para>One may obtain a <type>GDrawable</type> from a drawable's
      ID by the call <funcsynopsis ><funcdef >GimpDrawable* <function
      >gimp_drawable_get</function ></funcdef ><paramdef >gint32
      <parameter >drawable_ID</parameter ></paramdef ></funcsynopsis>
	which allocates and initializes the GimpDrawable for you, and
	then returns the pointer.</para>

      <note><simpara>When you see a <quote>layer ID</quote> or
      somesuch, this is really a drawable ID which happens to belong
      to a layer.  You may use it anywhere a drawable ID is called
      for.</simpara>
      </note>
      
    </section>
    
    <section id="sect-origins">
      <title>Origins of Coordinates</title>

      <para>If you were looking at a spot on the &gimp; image, you
      might choose to describe its location as the distance from the
      origin of the image, from the origin of the layer, or from the
      origin of the current selection.</para>
      
      <para>&gimp; chooses to measure coordinates from the upper-left
      corner of the drawable (the drawable is usually a layer).  If
      you want to know about the location of the selection or the
      layer offset, use the following calls (&gimph;):</para>

      <figure>
	<title>Functions to obtain coordinates.</title>
	<programlisting>
/* Find the bounding box of the current selection in relation to the
 * specified drawable.  Returns TRUE if there is a selection. */

gint          gimp_drawable_mask_bounds  (gint32     drawable_ID,
                                          gint      *x1,
                                          gint      *y1,
                                          gint      *x2,
                                          gint      *y2);

/* Returns the offsets of the drawable. */
void          gimp_drawable_offsets      (gint32     drawable_ID,
                                          gint      *offset_x,
                                          gint      *offset_y);
	</programlisting>
      </figure>

    </section><!-- end Origins of Coordinates -->
    
    <section id="sect-pixelrgns">
      <title>Pixel Regions</title>
      
      <para>The method through which a plug-in accesses a drawable is
      by way of what's known as a <firstterm>pixel
      region</firstterm>.</para>
      
      <para>Before working with a pixel region, initialize it with the
	following call:</para>
      <funcsynopsis>
	<funcprototype>
	  <funcdef>void <function>gimp_pixel_rgn_init</function>
	  </funcdef>
	  <paramdef>GimpPixelRgn* <parameter>pr</parameter></paramdef>
	  <paramdef>GimpDrawable* <parameter>drawable</parameter></paramdef>
	  <paramdef>int <parameter>x</parameter></paramdef>
	  <paramdef>int <parameter>y</parameter></paramdef>
	  <paramdef>int <parameter>width</parameter></paramdef>
	  <paramdef>int <parameter>height</parameter></paramdef>
	  <paramdef>int <parameter>dirty</parameter></paramdef>
	  <paramdef>int <parameter>shadow</parameter></paramdef>
	</funcprototype>
      </funcsynopsis>

      <variablelist>
	<varlistentry id="dirty">
	  <term>dirty</term>
	  <listitem><simpara>A <quote>dirty</quote> tile is one that
	  has been changed. Tiles that are not dirty won't be written
	  back to &gimp;, whereas dirty ones will be. Initializing a
	  pixel region as <quote>dirty</quote> indicates to
	  <function>gimp_pixel_rgns_process</function> that it should
	  treat tiles in that region as if you've dirtied them.
	  </simpara></listitem>
	</varlistentry>
	<varlistentry id="shadow">
	  <term>shadow</term>
	  <listitem><simpara>	      
	      <quote>Shadow tiles are merely an indication of the
	      desire to use a temporary buffer for writing in
	      to,</quote> says Peter. <quote>The advantage of using
	      shadow tiles are that A) you won't muck up the original
	      image, B) undo is handled properly, and C) the
	      modifications to the image are correctly masked by the
	      selection.</quote> </simpara></listitem>
	</varlistentry>
      </variablelist>

      <para>In short, if you're writing to a pixel region, the dirty
      and shadow flags should be TRUE, TRUE. If you need a clean copy
      to read from, use FALSE, FALSE. TRUE, FALSE can be used for
      writing directly to the image (not recommended), and FALSE, TRUE
      could be used to read from shadow tiles that you've just written
      to (possibly when using a multi-pass algorithm of some sort, as
      in gauss_iir.c).</para>

      <para>There are calls for <function>pixel_rgn_get_</function>
      <function>pixel</function>, <function>row</function>,
      <function>col</function>, and <function>rect</function>, which
      grab data from the image and dump it into a buffer that you've
      pre-allocated. And there are set calls to match. Look for "Pixel
      Regions" in gimp.h.</para>

      <para>Note that these calls are relatively slow, they can easily
      be the slowest thing in your plug-in. Do not get (or set) pixels
      one at a time using
      <function>pixel_rgn_[get|set]_pixel</function> if there is any
      other way. Tips for improving efficiency are in the <!-- FIXME:
      provide ref --> next chapter.</para>

    </section>

    <section id="sect-datafmt">
      <title>Data format</title> 

      <para>The data in your buffer depends on the image
      type. Grayscale is an array of values. Grayscale-alpha has gray
      value, alpha value, gray, alpha, etc. RGB and RGBA are just
      that.</para>
    </section>
      
    <section id="sect-drawmerge">
      <title>Drawable mergin' and stuff</title>
	
      <para>Once your plug-in is through munging the drawable, it has
      to go through the process of making sure &gimp; has been brought
      up to date. That sequence typically goes something like
      this:</para>

      <example>
	<title>Tidying up dirty drawables.</title>
	<programlisting>
GimpDrawable *drawable;
  /* . . . */

  /* Ensure any dirty tiles are flushed to GIMP. */
  gimp_drawable_flush (drawable);

  /* Merge in what you've written to the shadow tiles. 
     If the second arguement is TRUE, the action will be undoable. */
  /* Without this, anything you've written on the shadow tiles may be lost,
     and drawable will be filled with uninitialized memory instead. */
  gimp_drawable_merge_shadow (drawable->id, TRUE);

  /* Update a portion of a drawable you've modified. 
     Updates the displays and drawable previews. */
  gimp_drawable_update (drawable->id, x1, y1, width, height);

  /* Flush the updates to the on-screen displays. */
  /* (Not always desirable when called non-interactively.) */
  gimp_displays_flush();

  /* And if you're all done with the drawable, free the memory
  allocated by gimp_drawable_get, and any tiles the drawable was using. */
  gimp_drawable_detach(drawable);

	</programlisting>
      </example>
      
    </section>
    
    <section id="sect-select">
      <title>More on Selections</title>
      
      <para>Selections are drawables too.
      <function>gimp_image_get_selection(image_ID)</function>; returns
      the drawable ID of the selection mask.</para>

      <para>FIXME: Hmm, selection mask's 0,0 is drawable_mask_bounds'
      x1,y1, izit? Also find out what feathered/anti-aliased
      selections mean to us.</para>

      <para>See also: Appendix A: Premultiplied Alpha</para>
    </section>
    
    <section id="sect-image-misc">
      <title>Misc</title> 

      <para>There are many joyous functions for the handling of
      selections and layers and whatnot, which you may find by reading
      gimp.h or using the db_browser. One that I should warn you about
      is adding new layers to images: A layer created with
      <function>gimp_layer_new</function> must still be added to the
      image with <function>gimp_image_add_layer</function> before it
      will do any good. Be sure you pass the same image ID to both
      functions. And don't create layers without an alpha channel that
      aren't background layers if you're not looking for
      trouble.</para>

    </section>
    
  </chapter><!-- Working with the Image -->
  
  <chapter id="sect-tiles">
    <title>Efficient Image Handling: Tiles</title>
    
    <para>Whether you knew it or not, lots of blood, sweat, and tears
    have gone into making the modern &gimp; a <firstterm
    >tile-based</firstterm > graphics application. And no, that
    doesn't have anything to do with the <quote>Tile of the
    Day</quote>.  What does it mean?</para>

    <para>Well, our graphics are two dimensional, but the memory
    they're stored in is accessed by a one-dimensional index.  The
    usual approach to storing a graphic is to store the whole thing as
    one long array, stringing one row on after another. This works
    fine, until your images get rather large. Say you have a 1000 x
    1000 RGBA layer, that takes 4 MB. Drawing a vertical line down the
    image requires loading the entire thing into active memory, every
    row from top to bottom.</para>

    <para>&gimp;'s approach is to break the image up into a series of
    tiles. Now when you draw that vertical line, only the affected
    tiles need be in memory.</para>

    <para>What's that mean to the user? Smoother handling of large
    images, hopefully. What's that mean to you, the plug-in developer?
    It's just something to keep in mind if you're at all concerned
    about the speed with which you communicate with &gimp;. If you can
    view the world in a similar fashion, things go much smoother for
    the two of you. Otherwise you'll be running around picking up
    pieces from different tiles&hellip; Also, if it's practical for
    you to work on a single tile at a time instead of the entire
    image, you'll use less memory yourself.</para>

    <section id="sect-tile-cache">
      <title>Tile Cache</title>

      <para>If you're going through the image a row or column at a
      time, you're repeatedly accessing the same tiles over and over
      again. That means &gimp; keeps sending you the tile, you use
      1/64th of the information on it, ask for the next tile over,
      only to want that tile back again when you need the next
      row. This is rather inefficient, and consequently, slow.</para>

      <para>One way to solve this problem would be to restructure your
      plug-in so it's not so troublesome in what it requests&mdash;
      we'll talk about that in a moment. But there's another way to
      solve it which is often much easier, from the programmer's
      prospective. And that's to use a tile cache.</para>
      <!-- FIXME: Don't categorize by "easy" and "hard" -->
      
      <para>This tile cache is separate from &gimp;'s tile cache, and
      is local to the plug-in. The plug-in will store tiles here after
      receiving them from &gimp; (if there is room for them). That way,
      the next time you need data from that tile, it's already handy.</para>

      <para>Enabling a tile cache is easy. You have a choice of two
      calls. From gimp.h:<!-- FIXME: source ref --></para>
	
      <funcsynopsis>
	<funcdef>void <function>gimp_tile_cache_size</function></funcdef>
	<paramdef>gulong <parameter>kilobytes</parameter></paramdef>
      </funcsynopsis>
      <funcsynopsis>
	<funcdef>void <function>gimp_tile_cache_ntiles</function></funcdef>
	<paramdef>gulong <parameter>ntiles</parameter></paramdef>
      </funcsynopsis>
     
      <para>The first sets the cache size in kilobytes, the second
      sets the cache size based on number of tiles&hellip; more or
      less. Here's what gimp_tile_cache_ntiles does
      (libgimp/gimptile.c, v1.0.0):<!-- FIXME: source ref --></para>

      <programlisting>
	gimp_tile_cache_size ((ntiles * _gimp_tile_width * _gimp_tile_height * 4) / 1024);
      </programlisting>

      <para>A couple things with this&hellip; The integer division by
      1024 here may cause it to round down, which probably isn't a
      good thing. Also, the multiplication by four assumes four bytes
      per pixel, which isn't a good assumption if you're not always
      dealing with RGBA images. In short, you may want to do these
      calculations and call gimp_tile_cache_size yourself.</para>

      <para>How big a tile cache to make? As many tiles as you'll be
      using at once. If you're going by row, for example, cache
      however many tiles are in one row. If you're both reading from
      tiles and writing to shadow tiles, double the size of the
      cache. You can find out the tile size by calling
      <function>gimp_tile_width()</function> and
      <function>gimp_tile_height()</function>.</para>

      <note><title>Stuff you Don't Need to Know</title>
	<para>Tile size is defined at compile time in app/tile.h. The
	size 64x64 is optimal for an Intel x86 because their memory
	page size is 4096 bytes (64x64x1). You could change the tile
	size, but there are currently a few things which will break if
	you do, because they have some assumptions built in.</para>
      </note>

      <para>FIXME: Write about common data access methods, such as the
      row-buffer technique.</para>

    </section><!-- end Tile Cache -->

    <section id="sect-iterators">
      <title>Tile Iterators</title>

      <para>The first time I looked at plug-in code, I crept bravely
      in, until I hit a line that looked something like this:

	<programlisting>
	  for(pr=gimp_pixel_rgns_register(1,&amp;dest_rgn);pr!=NULL;pr=gimp_pixel_rgns_process(pr))
	</programlisting>

      at which point I ran away screaming.</para>

      <para>After a while, I came back, sat down, and found out it's
      what Quartic refers to as a tile iterator.  Its job is to go
      through the pixel region one tile at a time. You do not have to
      use this method, you may use the
      <function>pixel_rgn_[get|set]_</function> calls as described
      above. But the reason it's useful is because a tile at a time is
      the most efficient way for &gimp; to do things, and these two
      functions take care of the messy stuff for you.</para>

      <para><function>gimp_pixel_rgns_register</function>'s first
      parameter tells it how many pixel regions you're going to be
      iterating over, followed by pointers to those pixel
      regions. After some hocus-pocus, it returns a pointer which is
      used by <function>gimp_pixel_rgns_process</function>.</para>

      <para>Looking back at that plug-in's code:</para>

      <example>
	<title>Using the tile iterator.</title>
	<programlisting>
	  
  GimpPixelRgn region;
  GimpDrawable *drawable;

  drawable = gimp_drawable_get(drawable_ID);

  gimp_pixel_rgn_init (&amp;region, drawable, 
                       x1, y1, (x2 - x1), (y2 - y1), 
                       TRUE, TRUE);

  for (pr = gimp_pixel_rgns_register (1, &amp;region); 
       pr != NULL; 
       pr = gimp_pixel_rgns_process (pr)) {
          /* Fun Goes On Here */
      }
	</programlisting>
      </example>
      
      <para>The upshot of all that
      <function>gimp_pixel_rgns_</function> magic is, if while in the
      loop, you look back inside your region, you'll find all sorts of
      goodies. region.data now holds the image data for the area
      beginning at <varname>region.x</varname>,
      <varname>region.y</varname>, with a width of
      <varname>region.w</varname> and height
      <varname>region.h</varname>. Here, take a look at the data
      structure (gimp.h):</para>

      <programlisting>
struct _GimpPixelRgn
{
  guchar       *data;          /* pointer to region data */
  GimpDrawable *drawable;      /* pointer to drawable */
  guint         bpp;           /* bytes per pixel */
  guint         rowstride;     /* bytes per pixel row */
  guint         x, y;          /* origin */
  guint         w, h;          /* width and height of region */
  guint         dirty : 1;     /* will this region be dirtied? */
  guint         shadow : 1;    /* will this region use the shadow or normal tiles */
  guint         process_count; /* used internally */
};
      </programlisting>

      <para>To write to the image using this technique, all you have
      to do is change <varname>region.data</varname>, provided that
      you flagged your region as "dirty" (and hopefully "shadow" as
      well) when you initialized it.</para>

    </section>
  </chapter><!-- end Tiles -->
  
  <chapter id="sect-ui">
    <title>User Interface</title>
    
    <para>Firstly, see the <ulink url="http://www.gtk.org/tutorial/"
    >GTK Tutorial</ulink>.  This document does not and will not take
    its place.</para>
    
    <section id="sect-libgimpui">
      <title>libgimpui</title> 

      <para>New Ground Being Broken.  Word is that Mitch will have
      some docs for us <quote>as soon as the set of widget
      constructors in libgimp is really consistant</quote>
      (2000-01-30).</para>
  
      <section>
	<title>GimpConstraintFunc</title>

	<para>When you have have a drawable menu created for you,
	&gimp; makes use of a constraint function to ask you if what
	should be listed in the menu. This way you can filter out
	drawables that are the wrong size, image, type, etc. From
	gimpmenu.h:<!-- FIXME: source ref --></para>

	<programlisting>
typedef gint (*GimpConstraintFunc) (gint32   image_id,
                                    gint32   drawable_id,
                                    gpointer data);
GtkWidget* gimp_drawable_menu_new (GimpConstraintFunc constraint,
                                   GimpMenuCallback   callback,
                                   gpointer           data,
                                   gint32             active_drawable);
	</programlisting>

	<para>For every image, <function>_menu_new</function> calls
	the constraint function with the corresponding image ID and a
	drawable ID of -1. If the constraint function likes that image
	and returns TRUE, it's then called and asked about each
	drawable in the image, one at a time. If the function returns
	TRUE again, the drawable is added to the menu.</para>
      </section>
    </section>
    
    <section id="sect-dialog">
      <title>gimp_dialog</title>
      <para>New Ground Being Broken</para>
      
    </section>
    
    <section id="sect-i18n">
      <title>Internationalisation</title>

      <para>Internationalisation (abbreviated <abbrev>I18N</abbrev>)
      is the process of allowing your program to be viewed by users in
      their native language.  Daniel Egger and Marc Lehmann maintain
      the <ulink url=
      "http://gimp-plug-ins.sourceforge.net/doc/i18n.html"
      >documentation for I18N of &gimp; plug-ins</ulink>.
      </para>
      
    </section>
    
    <section id="sect-help">
      <title>The Help System</title>
      <para>&hellip;</para>
    </section>
    
    <section id="sect-ui-standards">
      <title>Standards</title>
      <para>&hellip;</para>
    </section>
  </chapter>
  
  <appendix id="appendix-alpha">
    <docinfo>
      <!-- FIXME: This isn't rendered by the stylesheets currently in
      use. -->
      <author>
	<firstname>Raph</firstname>
	<surname>Levien</surname>
      </author>
    </docinfo>
    <title>Premultiplied Alpha</title>

    <para>Premultiplied alpha is just a different way of representing
    alphified pixels. If the separate alpha pixel is (r, g, b, a),
    then the premultiplied alpha pixel is (ar, ag, ab, a).</para>

    <para>The reason why it's interesting is that linear combinations
    of pixels (i.e. a1p1 + a2p2) work better in premultiplied alpha
    space than in separate alpha space. </para>
      
    <para>For example, taking the 50/50 blend of white and transparent
    works like this: White is (1, 1, 1, 1) and transparent is (0, 0,
    0, 0) in both spaces.  So the 50/50 blend is (0.5, 0.5, 0.5, 0.5).
    In separated space, that's half-transparent
    <emphasis>gray</emphasis>, but in premultiplied space, that's
    half-transparent white, which is what you expect.</para>

    <para>Linear combinations of pixels occur in a lot of contexts,
    including:
      <orderedlist inheritnum="ignore" continuation="restarts">
	<listitem><simpara>layer compositing</simpara></listitem>
	<listitem><simpara>blurring and sharpening</simpara></listitem>
	<listitem><simpara>interpolation</simpara></listitem>
	<listitem><simpara>scaling</simpara></listitem>
	<listitem><simpara>rotation, perspective, and other
	    transformations</simpara></listitem>
      </orderedlist>
      and probably one or two others.</para>

    <para>The symptom of getting alpha wrong is gray fringes when you
    work with transparent layers.</para>
  </appendix>

  <appendix id="appendix-threading">
    <title>Threading</title>
    
    <para>This section is pretty bare, but Emil Briggs has started
    work on threading some few plug-ins.  He says he sees an 80% speed
    improvement with a threaded version of guass_iir on his
    multiprocessor machine. If there's no reason why your plug-in
    couldn't process several areas simultaniously instead of
    sequentially, consider taking a look at <ulink url=
    "http://nemo.physics.ncsu.edu/~briggs/gimp/index.html" >his
    page</ulink> and following his example.</para>

  </appendix>

  <!-- Include a glossary -->
  &glossary;

  <!-- Include an index (autogenerated) -->
  &genindex;

  <colophon id="colophon">
    <para>This text was written in DocBook 3.1 (<acronym >XML</acronym
    >) format, under <acronym>PSGML</acronym> mode of <ulink url=
    "http://www.xemacs.org/" ><application >XEmacs</application
    ></ulink> 21.  Output was produced with <ulink url=
    "http://www.jclark.com/jade/" ><application >jade</application
    ></ulink> version 1.2.1, using Norman Walsh's <ulink url=
    "http://nwalsh.com/docbook/dsssl/" >DocBook DSSSL
    Stylesheets</ulink>.</para>
  </colophon>
</book>