1/*
2   Implementation of a CLI command using a MagickWand API
3
4     magick -size 100x100 xc:red \
5            \( rose: -rotate -90 \) \
6            +append   show:
7
8
9   Compile with ImageMagick-devlop installed...
10
11     gcc -lMagickWand -lMagickCore wand.c -o wand
12
13   Compile and run directly in Source Directory...
14
15     IM_PROG=api_examples/wand
16     gcc -I`pwd` -LMagickWand/.libs -LMagickCore/.libs \
17       -lMagickWand -lMagickCore  $IM_PROG.c -o $IM_PROG
18
19     sh magick.sh    $IM_PROG
20
21*/
22#include <stdio.h>
23#include "MagickWand/MagickWand.h"
24
25/* Simplify the exception handling
26 * technically we should abort the program if
27 *      severity >= ErrorException
28 */
29void ThrowWandException(MagickWand *wand)
30{ char
31  *description;
32
33  ExceptionType
34  severity;
35
36  description=MagickGetException(wand,&severity);
37  (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description);
38  description=(char *) MagickRelinquishMemory(description);
39}
40
41/* useful function especially after appending two wands together */
42#define SwapWands(a,b) { MagickWand *tmp=a; a=b; b=tmp; }
43
44int main(int argc, char *argv[])
45{
46    MagickWand
47      *red,     /* red image wand */
48      *rose,    /* rose image wand */
49      *output;  /* the appended output image */
50
51    PixelWand
52      *color;
53
54    MagickBooleanType
55      status;
56
57    MagickWandGenesis();
58
59    /* read in the red image */
60    red = NewMagickWand();
61    MagickSetSize(red,100,100);
62    status = MagickReadImage(red, "xc:red" );
63    if (status == MagickFalse)
64      ThrowWandException(red);
65    /* NOTE ABOUT MagickReadImage()
66     * Unless the wand is empty set the first/last iterator to determine
67     * if the read image(s) are to be prepend/append into that wand image
68     * list.
69     *
70     * Setting a specific index always 'inserts' before that image.
71     */
72
73    /* read in the rose image */
74    rose = NewMagickWand();
75    status = MagickReadImage(rose, "rose:" );
76    if (status == MagickFalse)
77      ThrowWandException(rose);
78
79    /* rotate the rose image - one image only */
80    color=NewPixelWand();
81    PixelSetColor(color, "white");
82    status = MagickRotateImage(rose,color,-90.0);
83    if (status == MagickFalse)
84      ThrowWandException(rose);
85    color = DestroyPixelWand(color);
86
87    /* append rose image into the red image wand */
88    MagickSetLastIterator(red);
89    MagickAddImage(red,rose);
90    rose = DestroyMagickWand(rose);  /* finished with 'rose' wand */
91    /* NOTE ABOUT MagickAddImage()
92     *
93     * Always set the first/last image in the destination wand so that
94     * IM knows if you want to prepend/append the images into that wands
95     * image list.
96     *
97     * Setting a specific index always 'inserts' before that image.
98     */
99
100    /* append all images together to create the output wand */
101    MagickSetFirstIterator(red);
102    output = MagickAppendImages(red,MagickFalse);
103    red = DestroyMagickWand(red);  /* finished with 'red' wand */
104    /* NOTE ABOUT MagickAppendImages()
105     *
106     * It is important to either set first or reset the iterator before
107     * appending images, as only images from current image onward are
108     * appended together.
109     *
110     * Also note how a new wand is created by this operation, and that want
111     * does not inherit any settings from the previous wand (at least not at
112     * this time).
113     */
114
115    /* Final output */
116    status = MagickWriteImage(output,"show:");
117    if (status == MagickFalse)
118      ThrowWandException(output);
119
120    output = DestroyMagickWand(output);
121
122    MagickWandTerminus();
123}
124
125/*
126 * The above can be simplified further.
127 *
128 * Specifically you can read the 'rose' image directly into the 'red' image
129 * wand.  Then process just that rose image, even though it is sharing the
130 * same wand as another image.
131 *
132 * Remember in MagickWand, simple image operators are only applied to the
133 * current image in the wand an to no other image!  To apply a simple image
134 * operator (like MagickRotateImage()) to all the images in a wand you must
135 * iterate over all the images yourself.
136 */
137
138