/* Implementation of a CLI command using a MagickWand API magick -size 100x100 xc:red \ \( rose: -rotate -90 \) \ +append show: Compile with ImageMagick-devlop installed... gcc -lMagickWand -lMagickCore wand.c -o wand Compile and run directly from Source Directory... IM_PROG=api_examples/wand gcc -I`pwd` -LMagickWand/.libs -LMagickCore/.libs \ -lMagickWand -lMagickCore $IM_PROG.c -o $IM_PROG sh ./magick.sh $IM_PROG */ #include <stdio.h> #include "MagickWand/MagickWand.h" /* Simplify the exception handling * technically we should abort the program if * severity >= ErrorException */ void ThrowWandException(MagickWand *wand) { char *description; ExceptionType severity; description=MagickGetException(wand,&severity); (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); description=(char *) MagickRelinquishMemory(description); } /* useful function especially after appending two wands together */ #define SwapWands(a,b) { MagickWand *tmp=a; a=b; b=tmp; } int main(int argc, char *argv[]) { MagickWand *red, /* red image wand */ *rose, /* rose image wand */ *output; /* the appended output image */ PixelWand *color; MagickBooleanType status; MagickWandGenesis(); /* read in the red image */ red = NewMagickWand(); MagickSetSize(red,100,100); status = MagickReadImage(red, "xc:red" ); if (status == MagickFalse) ThrowWandException(red); /* NOTE ABOUT MagickReadImage() * Unless the wand is empty set the first/last iterator to determine * if the read image(s) are to be prepend/append into that wand image * list. * * Setting a specific index always 'inserts' before that image. */ /* read in the rose image */ rose = NewMagickWand(); status = MagickReadImage(rose, "rose:" ); if (status == MagickFalse) ThrowWandException(rose); /* rotate the rose image - one image only */ color=NewPixelWand(); PixelSetColor(color, "white"); status = MagickRotateImage(rose,color,-90.0); if (status == MagickFalse) ThrowWandException(rose); color = DestroyPixelWand(color); /* append rose image into the red image wand */ MagickSetLastIterator(red); MagickAddImage(red,rose); rose = DestroyMagickWand(rose); /* finished with 'rose' wand */ /* NOTE ABOUT MagickAddImage() * * Always set the first/last image in the destination wand so that * IM knows if you want to prepend/append the images into that wands * image list. * * Setting a specific index always 'inserts' before that image. */ /* append all images together to create the output wand */ MagickSetFirstIterator(red); output = MagickAppendImages(red,MagickFalse); red = DestroyMagickWand(red); /* finished with 'red' wand */ /* NOTE ABOUT MagickAppendImages() * * It is important to either 'set first' or 'reset' the iterator before * appending images, as only images from current image onward are * appended together. * * Also note how a new wand is created by this operation, and that new * wand does not inherit any settings from the previous wand (at least not * at this time). */ /* Final output */ status = MagickWriteImage(output,"show:"); if (status == MagickFalse) ThrowWandException(output); output = DestroyMagickWand(output); MagickWandTerminus(); } /* * The above can be simplified further, though that is not what "magick" * command would do which we are simulating. * * Specifically you can read the 'rose' image directly on the end of of * 'red' image wand. Then process just that rose image, even though it is * sharing the same wand as another image. * * Remember in MagickWand, simple image operators are only applied to the * current image in the wand an to no other image! To apply a simple image * operator (like MagickRotateImage()) to all the images in a wand you must * iterate over all the images yourself. */