| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"> |
| <html > |
| <head><title>Function dispatch and plug-ins</title> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
| <meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)"> |
| <meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)"> |
| <!-- 3,html --> |
| <meta name="src" content="vipsmanual.tex"> |
| <meta name="date" content="2010-06-09 21:39:00"> |
| <link rel="stylesheet" type="text/css" href="vipsmanual.css"> |
| </head><body |
| > |
| <!--l. 1--><div class="crosslinks"><p class="noindent">[<a |
| href="vipsmanualse10.html" >next</a>] [<a |
| href="vipsmanualse8.html" >prev</a>] [<a |
| href="vipsmanualse8.html#tailvipsmanualse8.html" >prev-tail</a>] [<a |
| href="#tailvipsmanualse9.html">tail</a>] [<a |
| href="vipsmanualch2.html#vipsmanualse9.html" >up</a>] </p></div> |
| <h3 class="sectionHead"><span class="titlemark">2.3 </span> <a |
| id="x15-590002.3"></a>Function dispatch and plug-ins</h3> |
| <!--l. 3--><p class="noindent" >(This chapter is on the verge of being deprecated. We have |
| started building a replacement based on <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">GObject</span></span></span>, see |
| <span |
| class="cmsy-10">ยง</span><a |
| href="vipsmanualse10.html#x16-670002.4">2.4<!--tex4ht:ref: sec:object --></a>.) |
| <!--l. 6--><p class="indent" > As image processing libraries increase in size it becomes |
| progressively more difficult to build applications which |
| present the operations the library offers to the user. Every |
| time a new operation is added, every user interface |
| needs to be adapted — a job which can rapidly become |
| unmanageable. |
| <!--l. 11--><p class="indent" > To address this problem VIPS includes a simple database |
| which stores an abstract description of every image |
| processing operation. User interfaces, rather than having |
| special code wired into them for each operation, can simply |
| interrogate the database and present what they find to the |
| user. |
| <!--l. 16--><p class="indent" > The operation database is extensible. You can define new |
| operations, and even new types, and add them to VIPS. |
| These new operations will then automatically appear in |
| all VIPS user interfaces with no extra programming |
| effort. Plugins can extend the database at runtime: when |
| VIPS starts, it loads all the plugins in the VIPS library |
| area. |
| <!--l. 22--><p class="noindent" > |
| <h4 class="subsectionHead"><span class="titlemark">2.3.1 </span> <a |
| id="x15-600002.3.1"></a>Simple plugin example</h4> |
| <!--l. 24--><p class="noindent" >As an example, consider this function: |
| <div class="verbatim" id="verbatim-81"> |
| #include <stdio.h> |
|  <br /> |
|  <br />#include <vips/vips.h> |
|  <br /> |
|  <br />/⋆ The function we define. Call this |
|  <br /> ⋆ from other parts of your C |
|  <br /> ⋆ application. |
|  <br /> ⋆/ |
|  <br />int |
|  <br />double_integer( int in ) |
|  <br />{ |
|  <br />  return( in ⋆ 2 ); |
|  <br />} |
| </div> |
| <!--l. 40--><p class="nopar" > |
| <!--l. 42--><p class="noindent" >The source for all the example code in this section is in the |
| vips-examples package. |
| <!--l. 46--><p class="indent" > The first step is to make a layer over this function which |
| will make it look like a standard VIPS function. VIPS |
| insists on the following pattern: |
| <ul class="itemize1"> |
| <li class="itemize">The function should be int-valued, and return 0 |
| for success and non-zero for error. It should set |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_error()</span></span></span>. |
| </li> |
| <li class="itemize">The function should take a single |
| argument: a pointer to a <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span>-terminated array of |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_objects</span></span></span>. |
| </li> |
| <li class="itemize">Each <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_object</span></span></span> represents one argument to |
| the function (either output or input) in the |
| form specified by the corresponding entry in the |
| function’s argument descriptor. |
| </li></ul> |
| <!--l. 66--><p class="indent" > The argument descriptor is an array of structures, |
| each describing one argument. For this example, it |
| is: |
| |
| |
| |
| <div class="verbatim" id="verbatim-82"> |
| /⋆ Describe the type of our function. |
|  <br /> ⋆ One input int, and one output int. |
|  <br /> ⋆/ |
|  <br />static im_arg_desc arg_types[] = { |
|  <br />  IM_INPUT_INT( "in" ), |
|  <br />  IM_OUTPUT_INT( "out" ) |
|  <br />}; |
| </div> |
| <!--l. 77--><p class="nopar" > |
| <!--l. 79--><p class="indent" > <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">IM_INPUT_INT()</span></span></span> and <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">IM_OUTPUT_INT()</span></span></span> are |
| macros defined in <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-"><vips/dispatch.h></span></span></span> which make |
| argument types easy to define. Other macros available are |
| listed in table <a |
| href="#x15-600011">2.1<!--tex4ht:ref: tab:type --></a>. |
| |
| |
| |
| |
| <!--l. 84--><p class="indent" > <a |
| id="x15-600011"></a><hr class="float"><div class="float" |
| > |
| |
| |
| |
| |
| <div class="center" |
| > |
| <!--l. 84--><p class="noindent" > |
| <div class="tabular"> <table id="TBL-5" class="tabular" |
| cellspacing="0" cellpadding="0" rules="groups" |
| ><colgroup id="TBL-5-1g"><col |
| id="TBL-5-1"></colgroup><colgroup id="TBL-5-2g"><col |
| id="TBL-5-2"></colgroup><colgroup id="TBL-5-3g"><col |
| id="TBL-5-3"></colgroup><tr |
| class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr |
| style="vertical-align:baseline;" id="TBL-5-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-1-1" |
| class="td11">Macro </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-1-2" |
| class="td11">Meaning </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-1-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_object </span>has type </td> |
| </tr><tr |
| class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr |
| style="vertical-align:baseline;" id="TBL-5-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-2-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_INT </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-2-2" |
| class="td11">Input int </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-2-3" |
| class="td11"><span |
| class="pcrr7t-">int ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-3-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_INTVEC </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-3-2" |
| class="td11">Input vector of int </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-3-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_intvec</span><span |
| class="pcrr7t-">_object ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-4-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_IMASK </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-4-2" |
| class="td11">Input int array </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-4-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_mask</span><span |
| class="pcrr7t-">_object ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-5-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_INT </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-5-2" |
| class="td11">Output int </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-5-3" |
| class="td11"><span |
| class="pcrr7t-">int ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-6-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_INTVEC </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-6-2" |
| class="td11">Output vector of int </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-6-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_intvec</span><span |
| class="pcrr7t-">_object ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-7-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_IMASK </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-7-2" |
| class="td11">Output int array to file </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-7-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_mask</span><span |
| class="pcrr7t-">_object ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-8-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_DOUBLE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-8-2" |
| class="td11">Input double </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-8-3" |
| class="td11"><span |
| class="pcrr7t-">double ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-9-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_DOUBLEVEC </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-9-2" |
| class="td11">Input vector of double </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-9-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_realvec</span><span |
| class="pcrr7t-">_object ⋆</span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-10-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-10-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_DMASK </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-10-2" |
| class="td11">Input double array </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-10-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_mask</span><span |
| class="pcrr7t-">_object ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-11-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-11-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_DOUBLE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-11-2" |
| class="td11">Output double </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-11-3" |
| class="td11"><span |
| class="pcrr7t-">double ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-12-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-12-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_DOUBLEVEC </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-12-2" |
| class="td11">Output vector of double </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-12-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_realvec</span><span |
| class="pcrr7t-">_object ⋆</span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-13-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-13-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_DMASK </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-13-2" |
| class="td11">Output double array to file </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-13-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_mask</span><span |
| class="pcrr7t-">_object ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-14-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-14-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_DMASK</span><span |
| class="pcrr7t-">_STATS</span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-14-2" |
| class="td11">Output double array to screen</td><td style="white-space:nowrap; text-align:left;" id="TBL-5-14-3" |
| class="td11"> </td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-15-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-15-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_COMPLEX </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-15-2" |
| class="td11">Output complex </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-15-3" |
| class="td11"><span |
| class="pcrr7t-">double ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-16-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-16-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_STRING </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-16-2" |
| class="td11">Input string </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-16-3" |
| class="td11"><span |
| class="pcrr7t-">char ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-17-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-17-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_STRING </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-17-2" |
| class="td11">Output string </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-17-3" |
| class="td11"><span |
| class="pcrr7t-">char ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-18-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-18-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_IMAGE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-18-2" |
| class="td11">Input image </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-18-3" |
| class="td11"><span |
| class="pcrr7t-">IMAGE ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-19-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-19-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_IMAGEVEC </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-19-2" |
| class="td11">Vector of input images </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-19-3" |
| class="td11"><span |
| class="pcrr7t-">IMAGE ⋆⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-20-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-20-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_IMAGE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-20-2" |
| class="td11">Output image </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-20-3" |
| class="td11"><span |
| class="pcrr7t-">IMAGE ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-21-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-21-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_RW</span><span |
| class="pcrr7t-">_IMAGE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-21-2" |
| class="td11">Read-write image </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-21-3" |
| class="td11"><span |
| class="pcrr7t-">IMAGE ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-22-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-22-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_DISPLAY </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-22-2" |
| class="td11">Input display </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-22-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_col</span><span |
| class="pcrr7t-">_display ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-23-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-23-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_DISPLAY </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-23-2" |
| class="td11">Output display </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-23-3" |
| class="td11"><span |
| class="pcrr7t-">im</span><span |
| class="pcrr7t-">_col</span><span |
| class="pcrr7t-">_display ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-24-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-24-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_GVALUE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-24-2" |
| class="td11">Input GValue </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-24-3" |
| class="td11"><span |
| class="pcrr7t-">GValue ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-25-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-25-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_OUTPUT</span><span |
| class="pcrr7t-">_GVALUE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-25-2" |
| class="td11">Output GValue </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-25-3" |
| class="td11"><span |
| class="pcrr7t-">GValue ⋆ </span></td> |
| </tr><tr |
| style="vertical-align:baseline;" id="TBL-5-26-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-26-1" |
| class="td11"><span |
| class="pcrr7t-">IM</span><span |
| class="pcrr7t-">_INPUT</span><span |
| class="pcrr7t-">_INTERPOLATE </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-5-26-2" |
| class="td11">Input VipsInterpolate </td><td style="white-space:nowrap; text-align:left;" id="TBL-5-26-3" |
| class="td11"><span |
| class="pcrr7t-">VipsInterpolate ⋆ </span></td> |
| </tr><tr |
| class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr |
| style="vertical-align:baseline;" id="TBL-5-27-"><td style="white-space:nowrap; text-align:left;" id="TBL-5-27-1" |
| class="td11"> </td></tr></table></div></div> |
| <br /><div class="caption" |
| ><span class="id">Table 2.1: </span><span |
| class="content">Argument type macros</span></div><!--tex4ht:label?: x15-600011 --> |
| |
| |
| |
| |
| </div><hr class="endfloat" /> |
| <!--l. 156--><p class="indent" > The argument to the type macro is the name of the |
| argument. These names are used by user-interface programs |
| to provide feedback, and sometimes as variable names. The |
| order in which you list the arguments is the order in which |
| user-interfaces will present them to the user. You should use |
| the following conventions when selecting names and an |
| order for your arguments: |
| <ul class="itemize1"> |
| <li class="itemize">Names should be entirely in lower-case and |
| contain no special characters, apart from the digits |
| 0-9 and the underscore character ‘_’. |
| </li> |
| <li class="itemize">Names should indicate the function of the |
| argument. For example, <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_add()</span></span></span> has the |
| following argument names: |
| <div class="verbatim" id="verbatim-83"> |
| example% vips -help im_add |
|  <br />vips: args: in1 in2 out |
|  <br />where: |
|  <br />  in1 is of type "image" |
|  <br />  in2 is of type "image" |
|  <br />  out is of type "image" |
|  <br />add two images, from package |
|  <br />  "arithmetic" |
|  <br />flags: |
|  <br />  (PIO function) |
|  <br />  (no coordinate transformation) |
|  <br />  (point-to-point operation) |
| </div> |
| <!--l. 185--><p class="nopar" > |
| </li> |
| <li class="itemize">You should order arguments with large input objects |
| first, then output objects, then any extra arguments or |
| options. For example, <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_extract()</span></span></span> has the |
| following sequence of arguments: |
| |
| |
| |
| <div class="verbatim" id="verbatim-84"> |
| example% vips -help im_extract |
|  <br />vips: args: input output left top |
|  <br />  width height channel |
|  <br />where: |
|  <br />  input is of type "image" |
|  <br />  output is of type "image" |
|  <br />  left is of type "integer" |
|  <br />  top is of type "integer" |
|  <br />  width is of type "integer" |
|  <br />  height is of type "integer" |
|  <br />  channel is of type "integer" |
|  <br />extract area/band, from package |
|  <br />  "conversion" |
|  <br />flags: |
|  <br />  (PIO function) |
|  <br />  (no coordinate transformation) |
|  <br />  (point-to-point operation) |
| </div> |
| <!--l. 210--><p class="nopar" > |
| </li></ul> |
| <!--l. 214--><p class="indent" > This function sits over <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">double_integer()</span></span></span>, providing |
| VIPS with an interface which it can call: |
| <div class="verbatim" id="verbatim-85"> |
| /⋆ Call our function via a VIPS |
|  <br /> ⋆ im_object vector. |
|  <br /> ⋆/ |
|  <br />static int |
|  <br />double_vec( im_object ⋆argv ) |
|  <br />{ |
|  <br />  int ⋆in = (int ⋆) argv[0]; |
|  <br />  int ⋆out = (int ⋆) argv[1]; |
|  <br /> |
|  <br />  ⋆out = double_integer( ⋆in ); |
|  <br /> |
|  <br />  /⋆ Always succeed. |
|  <br />   ⋆/ |
|  <br />  return( 0 ); |
|  <br />} |
| </div> |
| <!--l. 233--><p class="nopar" > |
| <!--l. 235--><p class="indent" > Finally, these two pieces of information (the argument |
| description and the VIPS-style function wrapper) can be |
| gathered together into a function description. |
| |
| |
| |
| <div class="verbatim" id="verbatim-86"> |
| /⋆ Description of double_integer. |
|  <br /> ⋆/ |
|  <br />static im_function double_desc = { |
|  <br />  "double_integer", |
|  <br />  "double an integer", |
|  <br />  0, |
|  <br />  double_vec, |
|  <br />  IM_NUMBER( arg_types ), |
|  <br />  arg_types |
|  <br />}; |
| </div> |
| <!--l. 250--><p class="nopar" > |
| <!--l. 253--><p class="indent" > <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">IM_NUMBER()</span></span></span> is a macro which returns the number of |
| elements in a static array. The <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">flags</span></span></span> field contains hints |
| which user-interfaces can use for various optimisations. At |
| present, the possible values are: |
| <dl class="description"><dt class="description"> |
| <span |
| class="pcrb7t-">IM</span><span |
| class="pcrb7t-">_FN</span><span |
| class="pcrb7t-">_PIO</span> </dt><dd |
| class="description">This function uses the VIPS PIO system |
| (see <span |
| class="cmsy-10">ยง</span><a |
| href="vipsmanualse15.html#x22-920003.3">3.3<!--tex4ht:ref: sec:pio --></a>). |
| </dd><dt class="description"> |
| <span |
| class="pcrb7t-">IM</span><span |
| class="pcrb7t-">_FN</span><span |
| class="pcrb7t-">_TRANSFORM</span> </dt><dd |
| class="description">This the function transforms |
| coordinates. |
| </dd><dt class="description"> |
| <span |
| class="pcrb7t-">IM</span><span |
| class="pcrb7t-">_FN</span><span |
| class="pcrb7t-">_PTOP</span> </dt><dd |
| class="description">This is a point-to-point operation, that |
| is, it can be replaced with a look-up table. |
| </dd><dt class="description"> |
| <span |
| class="pcrb7t-">IM</span><span |
| class="pcrb7t-">_FN</span><span |
| class="pcrb7t-">_NOCACHE</span> </dt><dd |
| class="description">This operation has side effects and |
| should not be cached. Useful for video grabbers, |
| for example. |
| </dd></dl> |
| <!--l. 275--><p class="indent" > This function description now needs to be added to the |
| VIPS function database. VIPS groups sets of related |
| functions together in packages. There is only a single |
| function in this example, so we can just write: |
| <div class="verbatim" id="verbatim-87"> |
| /⋆ Group up all the functions in this |
|  <br /> ⋆ file. |
|  <br /> ⋆/ |
|  <br />static im_function |
|  <br />  ⋆function_list[] = { |
|  <br />  &double_desc |
|  <br />}; |
|  <br /> |
|  <br />/⋆ Define the package_table symbol. |
|  <br /> ⋆ This is what VIPS looks for when |
|  <br /> ⋆ loading the plugin. |
|  <br /> ⋆/ |
|  <br />im_package package_table = { |
|  <br />  "example", |
|  <br />  IM_NUMBER( function_list ), |
|  <br />  function_list |
|  <br />}; |
| </div> |
| <!--l. 297--><p class="nopar" > |
| <!--l. 299--><p class="indent" > The package has to be named <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">package_table</span></span></span>, and |
| has to be exported from the file (that is, not a static). VIPS |
| looks for a symbol of this name when it opens your object |
| file. |
| <!--l. 303--><p class="indent" > This file needs to be made into a dynamically loadable |
| object. On my machine, I can do this with: |
| |
| |
| |
| <div class="verbatim" id="verbatim-88"> |
| example% gcc -fPIC -DPIC -c |
|  <br />  ‘pkg-config vips-7.12 --cflags‘ |
|  <br />  plug.c -o plug.o |
|  <br />example% gcc -shared plug.o |
|  <br />  -o double.plg |
| </div> |
| <!--l. 312--><p class="nopar" > |
| <!--l. 314--><p class="indent" > You can now use <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">double.plg</span></span></span> with any of the |
| VIPS applications which support function dispatch. For |
| example: |
| <div class="verbatim" id="verbatim-89"> |
| example% vips -plugin double.plg \ |
|  <br />  double_integer 12 |
|  <br />24 |
|  <br />example% |
| </div> |
| <!--l. 322--><p class="nopar" > |
| <!--l. 324--><p class="indent" > When VIPS starts up, it looks for a directory in the |
| library directory called <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">vips-</span></span></span>, with the vips major and |
| minor versions numbers as extensions, and loads all files in |
| there with the suffix <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">.plg</span></span></span>. So for example, on my machine, |
| the plugin directory is <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">/usr/lib/vips-7.16</span></span></span> and any |
| plugins in that directory are automatically loaded into any |
| VIPS programs on startup. |
| <h4 class="subsectionHead"><span class="titlemark">2.3.2 </span> <a |
| id="x15-610002.3.2"></a>A more complicated example</h4> |
| <!--l. 332--><p class="noindent" >This section lists the source for <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_extract()</span></span></span>’s function |
| description. Almost all functions in the VIPS library have |
| descriptors — if you are not sure how to write a description, |
| it’s usually easiest to copy one from a similar function in the |
| library. |
| |
| |
| |
| <div class="verbatim" id="verbatim-90"> |
| /⋆ Args to im_extract. |
|  <br /> ⋆/ |
|  <br />static im_arg_desc |
|  <br />  extract_args[] = { |
|  <br />  IM_INPUT_IMAGE( "input" ), |
|  <br />  IM_OUTPUT_IMAGE( "output" ), |
|  <br />  IM_INPUT_INT( "left" ), |
|  <br />  IM_INPUT_INT( "top" ), |
|  <br />  IM_INPUT_INT( "width" ), |
|  <br />  IM_INPUT_INT( "height" ), |
|  <br />  IM_INPUT_INT( "channel" ) |
|  <br />}; |
|  <br /> |
|  <br />/⋆ Call im_extract via arg vector. |
|  <br /> ⋆/ |
|  <br />static int |
|  <br />extract_vec( im_object ⋆argv ) |
|  <br />{ |
|  <br />  IMAGE_BOX box; |
|  <br /> |
|  <br />  box.xstart = ⋆((int ⋆) argv[2]); |
|  <br />  box.ystart = ⋆((int ⋆) argv[3]); |
|  <br />  box.xsize = ⋆((int ⋆) argv[4]); |
|  <br />  box.ysize = ⋆((int ⋆) argv[5]); |
|  <br />  box.chsel = ⋆((int ⋆) argv[6]); |
|  <br /> |
|  <br />  return( im_extract( |
|  <br />    argv[0], argv[1], &box ) ); |
|  <br />} |
|  <br /> |
|  <br />/⋆ Description of im_extract. |
|  <br /> ⋆/ |
|  <br />static im_function |
|  <br />  extract_desc = { |
|  <br />  "im_extract", |
|  <br />  "extract area/band", |
|  <br />  IM_FN_PIO | IM_FN_TRANSFORM, |
|  <br />  extract_vec, |
|  <br />  NUMBER( extract_args ), |
|  <br />  extract_args |
|  <br />}; |
| </div> |
| <!--l. 379--><p class="nopar" > |
| <!--l. 381--><p class="noindent" > <h4 class="subsectionHead"><span class="titlemark">2.3.3 </span> <a |
| id="x15-620002.3.3"></a>Adding new types</h4> |
| <!--l. 383--><p class="noindent" >The VIPS type mechanism is extensible. User plug-ins can |
| add new types and user-interfaces can (to a certain extent) |
| provide interfaces to these user-defined types. |
| <!--l. 387--><p class="indent" > Here is the definition of <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_arg_desc</span></span></span>: |
| |
| |
| |
| <div class="verbatim" id="verbatim-91"> |
| /⋆ Describe a VIPS command argument. |
|  <br /> ⋆/ |
|  <br />typedef struct { |
|  <br />  char ⋆name; |
|  <br />  im_type_desc ⋆desc; |
|  <br />  im_print_obj_fn print; |
|  <br />} im_arg_desc; |
| </div> |
| <!--l. 397--><p class="nopar" > |
| <!--l. 399--><p class="indent" > The <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">name</span></span></span> field is the argument name above. The <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">desc</span></span></span> |
| field points to a structure defining the argument type, and |
| the <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">print</span></span></span> field is an (optionally <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span>) pointer to a |
| function which VIPS will call for output arguments after |
| your function successfully completes and before the |
| object is destroyed. It can be used to print results to |
| the terminal, or to copy results into a user-interface |
| layer. |
| <div class="verbatim" id="verbatim-92"> |
| /⋆ Success on an argument. This is |
|  <br /> ⋆ called if the image processing |
|  <br /> ⋆ function succeeds and should be |
|  <br /> ⋆ used to (for example) print |
|  <br /> ⋆ output. |
|  <br /> ⋆/ |
|  <br />typedef int (⋆im_print_obj_fn) |
|  <br />  ( im_object obj ); |
| </div> |
| <!--l. 415--><p class="nopar" > |
| <!--l. 417--><p class="indent" > <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_type_desc</span></span></span> is defined as: |
| |
| |
| |
| <div class="verbatim" id="verbatim-93"> |
| /⋆ Describe a VIPS type. |
|  <br /> ⋆/ |
|  <br />typedef struct { |
|  <br />  im_arg_type type; |
|  <br />  int size; |
|  <br />  im_type_flags flags; |
|  <br />  im_init_obj_fn init; |
|  <br />  im_dest_obj_fn dest; |
|  <br />} im_type_desc; |
| </div> |
| <!--l. 429--><p class="nopar" > |
| <!--l. 431--><p class="indent" > Where <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_arg_type</span></span></span> is defined as |
| <div class="verbatim" id="verbatim-94"> |
| /⋆ Type names. You may define your |
|  <br /> ⋆ own, but if you use one of these, |
|  <br /> ⋆ then you should use the built-in |
|  <br /> ⋆ VIPS type converters. |
|  <br /> ⋆/ |
|  <br />#define IM_TYPE_IMAGEVEC "imagevec" |
|  <br />#define IM_TYPE_DOUBLEVEC "doublevec" |
|  <br />#define IM_TYPE_INTVEC "intvec" |
|  <br />#define IM_TYPE_DOUBLE "double" |
|  <br />#define IM_TYPE_INT "integer" |
|  <br />#define IM_TYPE_COMPLEX "complex" |
|  <br />#define IM_TYPE_STRING "string" |
|  <br />#define IM_TYPE_IMASK "intmask" |
|  <br />#define IM_TYPE_DMASK "doublemask" |
|  <br />#define IM_TYPE_IMAGE "image" |
|  <br />#define IM_TYPE_DISPLAY "display" |
|  <br />#define IM_TYPE_GVALUE "gvalue" |
|  <br />typedef char ⋆im_arg_type; |
| </div> |
| <!--l. 452--><p class="nopar" > |
| <!--l. 454--><p class="indent" > In other words, it’s just a string. When you add a new |
| type, you just need to choose a new unique string to name it. |
| Be aware that the string is printed to the user by various |
| parts of VIPS, and so needs to be “human-readable”. The |
| flags are: |
| |
| |
| |
| <div class="verbatim" id="verbatim-95"> |
| /⋆ These bits are ored together to |
|  <br /> ⋆ make the flags in a type |
|  <br /> ⋆ descriptor. |
|  <br /> ⋆ |
|  <br /> ⋆ IM_TYPE_OUTPUT: set to indicate |
|  <br /> ⋆ output, otherwise input. |
|  <br /> ⋆ |
|  <br /> ⋆ IM_TYPE_ARG: Two ways of making |
|  <br /> ⋆ an im_object --- with and without |
|  <br /> ⋆ a command-line string to help you |
|  <br /> ⋆ along. Arguments with a string |
|  <br /> ⋆ are thing like IMAGE descriptors, |
|  <br /> ⋆ which require a filename to |
|  <br /> ⋆ initialise. Arguments without are |
|  <br /> ⋆ things like output numbers, where |
|  <br /> ⋆ making the object simply involves |
|  <br /> ⋆ allocating storage. |
|  <br /> ⋆/ |
|  <br /> |
|  <br />typedef enum { |
|  <br />  IM_TYPE_OUTPUT = 0x1, |
|  <br />  IM_TYPE_ARG = 0x2 |
|  <br />} im_type_flags; |
| </div> |
| <!--l. 483--><p class="nopar" > |
| <!--l. 485--><p class="indent" > And the <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">init</span></span></span> and <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">destroy</span></span></span> functions are: |
| <div class="verbatim" id="verbatim-96"> |
| /⋆ Initialise and destroy objects. |
|  <br /> ⋆ The "str" argument to the init |
|  <br /> ⋆ function will not be supplied |
|  <br /> ⋆ if this is not an ARG type. |
|  <br /> ⋆/ |
|  <br />typedef int (⋆im_init_obj_fn) |
|  <br />  ( im_object ⋆obj, char ⋆str ); |
|  <br />typedef int (⋆im_dest_obj_fn) |
|  <br />  ( im_object obj ); |
| </div> |
| <!--l. 497--><p class="nopar" > |
| <!--l. 499--><p class="indent" > As an example, here is the definition for a new type of |
| unsigned integers. First, we need to define the <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">init</span></span></span> and |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">print</span></span></span> functions. These transform objects of the type to |
| and from string representation. |
| |
| |
| |
| <div class="verbatim" id="verbatim-97"> |
| /⋆ Init function for unsigned int |
|  <br /> ⋆ input. |
|  <br /> ⋆/ |
|  <br />static int |
|  <br />uint_init( im_object ⋆obj, char ⋆str ) |
|  <br />{ |
|  <br />  unsigned int ⋆i = (int ⋆) ⋆obj; |
|  <br /> |
|  <br />  if( sscanf( str, "%d", i ) != 1 || |
|  <br />    ⋆i < 0 ) { |
|  <br />    im_error( "uint_init", |
|  <br />      "bad format" ); |
|  <br />    return( -1 ); |
|  <br />  } |
|  <br /> |
|  <br />  return( 0 ); |
|  <br />} |
|  <br /> |
|  <br />/⋆ Print function for unsigned int |
|  <br /> ⋆ output. |
|  <br /> ⋆/ |
|  <br />static int |
|  <br />uint_print( im_object obj ) |
|  <br />{ |
|  <br />  unsigned int ⋆i = |
|  <br />    (unsigned int ⋆) obj; |
|  <br /> |
|  <br />  printf( "%d\n", (int) ⋆i ); |
|  <br /> |
|  <br />  return( 0 ); |
|  <br />} |
| </div> |
| <!--l. 536--><p class="nopar" > |
| <!--l. 538--><p class="indent" > Now we can define the type itself. We make two of |
| these — one for unsigned int used as input, and one for |
| output. |
| <div class="verbatim" id="verbatim-98"> |
| /⋆ Name our type. |
|  <br /> ⋆/ |
|  <br />#define TYPE_UINT "uint" |
|  <br /> |
|  <br />/⋆ Input unsigned int type. |
|  <br /> ⋆/ |
|  <br />static im_type_desc input_uint = { |
|  <br />  TYPE_UINT,        /⋆ Its an int ⋆/ |
|  <br />  sizeof( unsigned int ),/⋆ Memory ⋆/ |
|  <br />  IM_TYPE_ARG,      /⋆ Needs arg ⋆/ |
|  <br />  uint_init,        /⋆ Init ⋆/ |
|  <br />  NULL              /⋆ Destroy ⋆/ |
|  <br />}; |
|  <br /> |
|  <br />/⋆ Output unsigned int type. |
|  <br /> ⋆/ |
|  <br />static im_type_desc output_uint = { |
|  <br />  TYPE_UINT,        /⋆ It's an int ⋆/ |
|  <br />  sizeof( unsigned int ),/⋆ Memory ⋆/ |
|  <br />  IM_TYPE_OUTPUT,   /⋆ It's output ⋆/ |
|  <br />  NULL,             /⋆ Init ⋆/ |
|  <br />  NULL              /⋆ Destroy ⋆/ |
|  <br />}; |
| </div> |
| <!--l. 565--><p class="nopar" > |
| <!--l. 567--><p class="indent" > Finally, we can define two macros to make structures of |
| type <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_arg_desc</span></span></span> for us. |
| |
| |
| |
| <div class="verbatim" id="verbatim-99"> |
| #define INPUT_UINT( S ) \ |
|  <br />  { S, &input_uint, NULL } |
|  <br />#define OUTPUT_UINT( S ) \ |
|  <br />  { S, &output_uint, uint_print } |
| </div> |
| <!--l. 575--><p class="nopar" > |
| <!--l. 577--><p class="indent" > For more examples, see the definitions for the built-in |
| VIPS types. |
| <!--l. 579--><p class="noindent" > |
| <h4 class="subsectionHead"><span class="titlemark">2.3.4 </span> <a |
| id="x15-630002.3.4"></a>Using function dispatch in your application</h4> |
| <!--l. 581--><p class="noindent" >VIPS provides a set of functions for adding new image |
| processing functions to the VIPS function database, finding |
| functions by name, and calling functions. See the manual |
| pages for full details. |
| <!--l. 585--><p class="noindent" > |
| <h5 class="subsubsectionHead"><a |
| id="x15-640002.3.4"></a>Adding and removing functions</h5> |
| <div class="verbatim" id="verbatim-100"> |
| im_package ⋆im_load_plugin( |
|  <br />  const char ⋆name ); |
| </div> |
| <!--l. 590--><p class="nopar" > |
| <!--l. 592--><p class="indent" > This function opens the named file, searches it for a |
| symbol named <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">package_table</span></span></span>, and adds any functions |
| it finds to the VIPS function database. When you search |
| for a function, any plug-ins are searched first, so you |
| can override standard VIPS function with your own |
| code. |
| <!--l. 597--><p class="indent" > The function returns a pointer to the package it added, or |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span> on error. |
| |
| |
| |
| <div class="verbatim" id="verbatim-101"> |
| int im_close_plugins( void ) |
| </div> |
| <!--l. 602--><p class="nopar" > |
| <!--l. 604--><p class="indent" > This function closes all plug-ins, removing then from the |
| VIPS function database. It returns non-zero on error. |
| <!--l. 607--><p class="noindent" > |
| <h5 class="subsubsectionHead"><a |
| id="x15-650002.3.4"></a>Searching the function database</h5> |
| <div class="verbatim" id="verbatim-102"> |
| void ⋆im_map_packages( |
|  <br />  im_list_map_fn fn, void ⋆a ) |
| </div> |
| <!--l. 612--><p class="nopar" > |
| <!--l. 614--><p class="indent" > This function applies the argument function <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">fn</span></span></span> to |
| every package in the database, starting with the most |
| recently added package. As with <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_list_map()</span></span></span>, the |
| argument function should return <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span> to continue |
| searching, or non-<span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span> to terminate the search early. |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_map_packages()</span></span></span> returns <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span> if <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">fn</span></span></span> returned |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">NULL</span></span></span> for all arguments. The extra argument <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">a</span></span></span> is carried |
| around by VIPS for your use. |
| <!--l. 622--><p class="indent" > For example, this fragment of code prints the names of all |
| loaded packages to <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">fd</span></span></span>: |
| |
| |
| |
| <div class="verbatim" id="verbatim-103"> |
| static void ⋆ |
|  <br />print_package_name( im_package ⋆pack, |
|  <br />  FILE ⋆fp ) |
|  <br />{ |
|  <br />  (void) fprintf( fp, |
|  <br />    "package: \"%s\"\n", |
|  <br />    pack->name ); |
|  <br /> |
|  <br />  /⋆ Continue search. |
|  <br />   ⋆/ |
|  <br />  return( NULL ); |
|  <br />} |
|  <br /> |
|  <br />static void |
|  <br />print_packages( FILE ⋆fp ) |
|  <br />{ |
|  <br />  (void) im_map_packages( |
|  <br />    (im_list_map_fn) |
|  <br />    print_package_name, fp ); |
|  <br />} |
| </div> |
| <!--l. 646--><p class="nopar" > |
| <!--l. 648--><p class="indent" > VIPS defines three convenience functions based on |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_map_packages()</span></span></span> which simplify searching for |
| specific functions: |
| <div class="verbatim" id="verbatim-104"> |
| im_function ⋆ |
|  <br />  im_find_function( char ⋆name ) |
|  <br />im_package ⋆ |
|  <br />  im_find_package( char ⋆name ) |
|  <br />im_package ⋆ |
|  <br />  im_package_of_function( char ⋆name ) |
| </div> |
| <!--l. 658--><p class="nopar" > |
| <!--l. 660--><p class="noindent" > |
| <h5 class="subsubsectionHead"><a |
| id="x15-660002.3.4"></a>Building argument structures and running commands</h5> |
| |
| |
| |
| <div class="verbatim" id="verbatim-105"> |
| int im_free_vargv( im_function ⋆fn, |
|  <br />  im_object ⋆vargv ) |
|  <br />int im_allocate_vargv( |
|  <br />  im_function ⋆fn, |
|  <br />  im_object ⋆vargv ) |
| </div> |
| <!--l. 668--><p class="nopar" > |
| <!--l. 670--><p class="indent" > These two functions allocate space for and free VIPS |
| argument lists. The allocate function simply calls |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_malloc()</span></span></span> to allocate any store that the types require |
| (and also initializes it to zero). The free function just calls |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">im_free()</span></span></span> for any storage that was allocated. |
| <!--l. 675--><p class="indent" > Note that neither of these functions calls the <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">init</span></span></span>, |
| <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">dest</span></span></span> or <span class="obeylines-h"><span class="verb"><span |
| class="pcrr7t-">print</span></span></span> functions for the types — that’s up to |
| you. |
| <div class="verbatim" id="verbatim-106"> |
| int im_run_command( char ⋆name, |
|  <br />  int argc, char ⋆⋆argv ) |
| </div> |
| <!--l. 681--><p class="nopar" > |
| <!--l. 683--><p class="indent" > This function does everything. In effect, |
| |
| |
| |
| <div class="verbatim" id="verbatim-107"> |
| im_run_command( "im_invert", 2, |
|  <br />  { "fred.v", "fred2.v", NULL } ) |
| </div> |
| <!--l. 688--><p class="nopar" > |
| <!--l. 690--><p class="indent" > is exactly equivalent to |
| <div class="verbatim" id="verbatim-108"> |
| system( "vips im_invert fred.v " |
|  <br />  "fred2.v" ) |
| </div> |
| <!--l. 695--><p class="nopar" > |
| <!--l. 697--><p class="indent" > but no process is forked. |
| |
| |
| |
| <!--l. 1--><div class="crosslinks"><p class="noindent">[<a |
| href="vipsmanualse10.html" >next</a>] [<a |
| href="vipsmanualse8.html" >prev</a>] [<a |
| href="vipsmanualse8.html#tailvipsmanualse8.html" >prev-tail</a>] [<a |
| href="vipsmanualse9.html" >front</a>] [<a |
| href="vipsmanualch2.html#vipsmanualse9.html" >up</a>] </p></div> |
| <!--l. 1--><p class="indent" > <a |
| id="tailvipsmanualse9.html"></a> |
| </body></html> |