anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 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 | |
Anthony Thyssen | 5b7198d | 2016-12-20 11:05:09 +1000 | [diff] [blame] | 13 | Compile and run directly from Source Directory... |
anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 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 | |
Anthony Thyssen | 5b7198d | 2016-12-20 11:05:09 +1000 | [diff] [blame] | 19 | sh ./magick.sh $IM_PROG |
anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 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 | * |
Anthony Thyssen | 5b7198d | 2016-12-20 11:05:09 +1000 | [diff] [blame] | 106 | * It is important to either 'set first' or 'reset' the iterator before |
anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 107 | * appending images, as only images from current image onward are |
| 108 | * appended together. |
| 109 | * |
Anthony Thyssen | 5b7198d | 2016-12-20 11:05:09 +1000 | [diff] [blame] | 110 | * Also note how a new wand is created by this operation, and that new |
| 111 | * wand does not inherit any settings from the previous wand (at least not |
| 112 | * at this time). |
anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 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 | /* |
Anthony Thyssen | 5b7198d | 2016-12-20 11:05:09 +1000 | [diff] [blame] | 126 | * The above can be simplified further, though that is not what "magick" |
| 127 | * command would do which we are simulating. |
anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 128 | * |
Anthony Thyssen | 5b7198d | 2016-12-20 11:05:09 +1000 | [diff] [blame] | 129 | * Specifically you can read the 'rose' image directly on the end of of |
| 130 | * 'red' image wand. Then process just that rose image, even though it is |
| 131 | * sharing the same wand as another image. |
anthony | 25247ae | 2013-03-18 05:05:40 +0000 | [diff] [blame] | 132 | * |
| 133 | * Remember in MagickWand, simple image operators are only applied to the |
| 134 | * current image in the wand an to no other image! To apply a simple image |
| 135 | * operator (like MagickRotateImage()) to all the images in a wand you must |
| 136 | * iterate over all the images yourself. |
| 137 | */ |
| 138 | |