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  */
29 void 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 
44 int 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