Page 1 of 1

MagickWand Examples

Posted: 2012-02-29T17:42:52-07:00
by anthony
Subject: Clone and Append
anthony wrote:I created a small MagickWand test script to test out various things,
All seems to work as expected (once i checked the manual for each function)

https://dl.dropbox.com/u/9500683/append_test.c.txt

See the comments in the script about how to use MagickAddImage() (image list append)
and MagickAppendImages() (image layout append), which I gleaned from the manual, code, and some testing.
Because of the above I have been generating a series of 'equivalent' programs, which all do exactly same processing, but does so in as many ImageMagick API techniques as I have been comfortable with.

Code: Select all

/*
   Implementation of a CLI command using a MagickWand API

     convert -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 in Source Directory...

       IM_PROG=wand_test
       gcc -I`pwd` -Lwand/.libs -Lmagick/.libs \
         -lMagickWand -lMagickCore  $IM_PROG.c -o $IM_PROG

       sh magick.sh    ./$IM_PROG

*/
#include <stdio.h>
#include "wand/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!
     */

    /* Final output */
    status = MagickWriteImage(output,"show:");
    if (status == MagickFalse)
      ThrowWandException(output);

    output = DestroyMagickWand(output);

    MagickWandTerminus();
}

/*
 * The above can be simplified further.
 *
 * Specifically you can read the 'rose' image directly into the '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.
 */
Perhaps if you know another API you can contribute an example to me to be included.