]> granicus.if.org Git - imagemagick/blob - Magick++/lib/Image.cpp
(no commit message)
[imagemagick] / Magick++ / lib / Image.cpp
1 // This may look like C code, but it is really -*- C++ -*-
2 //
3 // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003
4 //
5 // Implementation of Image
6 //
7
8 #define MAGICKCORE_IMPLEMENTATION  1
9 #define MAGICK_PLUSPLUS_IMPLEMENTATION 1
10
11 #include <cstdlib>
12 #include <string>
13 #include <string.h>
14 #include <errno.h>
15 #include <math.h>
16 #include "Magick++/Include.h"
17
18 using namespace std;
19
20 #include "Magick++/Image.h"
21 #include "Magick++/Functions.h"
22 #include "Magick++/Pixels.h"
23 #include "Magick++/Options.h"
24 #include "Magick++/ImageRef.h"
25
26 #define AbsoluteValue(x)  ((x) < 0 ? -(x) : (x))
27 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
28
29 MagickPPExport const char *Magick::borderGeometryDefault = "6x6+0+0";
30 MagickPPExport const char *Magick::frameGeometryDefault  = "25x25+6+6";
31 MagickPPExport const char *Magick::raiseGeometryDefault  = "6x6+0+0";
32
33 static bool magick_initialized=false;
34
35 //
36 // Explicit template instantiations
37 //
38
39 //
40 // Friend functions to compare Image objects
41 //
42
43 MagickPPExport int Magick::operator == ( const Magick::Image& left_,
44                                         const Magick::Image& right_ )
45 {
46   // If image pixels and signature are the same, then the image is identical
47   return ( ( left_.rows() == right_.rows() ) &&
48            ( left_.columns() == right_.columns() ) &&
49            ( left_.signature() == right_.signature() )
50            );
51 }
52 MagickPPExport int Magick::operator != ( const Magick::Image& left_,
53                                         const Magick::Image& right_ )
54 {
55   return ( ! (left_ == right_) );
56 }
57 MagickPPExport int Magick::operator >  ( const Magick::Image& left_,
58                                         const Magick::Image& right_ )
59 {
60   return ( !( left_ < right_ ) && ( left_ != right_ ) );
61 }
62 MagickPPExport int Magick::operator <  ( const Magick::Image& left_,
63                                         const Magick::Image& right_ )
64 {
65   // If image pixels are less, then image is smaller
66   return ( ( left_.rows() * left_.columns() ) <
67            ( right_.rows() * right_.columns() )
68            );
69 }
70 MagickPPExport int Magick::operator >= ( const Magick::Image& left_,
71                                         const Magick::Image& right_ )
72 {
73   return ( ( left_ > right_ ) || ( left_ == right_ ) );
74 }
75 MagickPPExport int Magick::operator <= ( const Magick::Image& left_,
76                                         const Magick::Image& right_ )
77 {
78   return ( ( left_ < right_ ) || ( left_ == right_ ) );
79 }
80
81 //
82 // Image object implementation
83 //
84
85 // Construct from image file or image specification
86 Magick::Image::Image( const std::string &imageSpec_ )
87   : _imgRef(new ImageRef)
88 {
89   try
90     {
91       // Initialize, Allocate and Read images
92       read( imageSpec_ );
93     }
94   catch ( const Warning & /*warning_*/ )
95     {
96       // FIXME: need a way to report warnings in constructor
97     }
98   catch ( const Error & /*error_*/ )
99     {
100       // Release resources
101       delete _imgRef;
102       throw;
103     }
104 }
105
106 // Construct a blank image canvas of specified size and color
107 Magick::Image::Image( const Geometry &size_,
108                       const Color &color_ )
109   : _imgRef(new ImageRef)
110 {
111   // xc: prefix specifies an X11 color string
112   std::string imageSpec("xc:");
113   imageSpec += color_;
114
115   try
116     {
117       // Set image size
118       size( size_ );
119
120       // Initialize, Allocate and Read images
121       read( imageSpec );
122     }
123   catch ( const Warning & /*warning_*/ )
124     {
125       // FIXME: need a way to report warnings in constructor
126     }
127   catch ( const Error & /*error_*/ )
128     {
129       // Release resources
130       delete _imgRef;
131       throw;
132     }
133 }
134
135 // Construct Image from in-memory BLOB
136 Magick::Image::Image ( const Blob &blob_ )
137   : _imgRef(new ImageRef)
138 {
139   try
140     {
141       // Initialize, Allocate and Read images
142       read( blob_ );
143     }
144   catch ( const Warning & /*warning_*/ )
145     {
146       // FIXME: need a way to report warnings in constructor
147     }
148   catch ( const Error & /*error_*/ )
149     {
150       // Release resources
151       delete _imgRef;
152       throw;
153     }
154 }
155
156 // Construct Image of specified size from in-memory BLOB
157 Magick::Image::Image ( const Blob &blob_,
158                        const Geometry &size_ )
159   : _imgRef(new ImageRef)
160 {
161   try
162     {
163       // Read from Blob
164       read( blob_, size_ );
165     }
166   catch ( const Warning & /*warning_*/ )
167     {
168       // FIXME: need a way to report warnings in constructor
169     }
170   catch ( const Error & /*error_*/ )
171     {
172       // Release resources
173       delete _imgRef;
174       throw;
175     }
176 }
177
178 // Construct Image of specified size and depth from in-memory BLOB
179 Magick::Image::Image ( const Blob &blob_,
180                        const Geometry &size_,
181                        const size_t depth_ )
182   : _imgRef(new ImageRef)
183 {
184   try
185     {
186       // Read from Blob
187       read( blob_, size_, depth_ );
188     }
189   catch ( const Warning & /*warning_*/ )
190     {
191       // FIXME: need a way to report warnings in constructor
192     }
193   catch ( const Error & /*error_*/ )
194     {
195       // Release resources
196       delete _imgRef;
197       throw;
198     }
199 }
200
201 // Construct Image of specified size, depth, and format from in-memory BLOB
202 Magick::Image::Image ( const Blob &blob_,
203                        const Geometry &size_,
204                        const size_t depth_,
205                        const std::string &magick_ )
206   : _imgRef(new ImageRef)
207 {
208   try
209     {
210       // Read from Blob
211       read( blob_, size_, depth_, magick_ );
212     }
213   catch ( const Warning & /*warning_*/ )
214     {
215       // FIXME: need a way to report warnings in constructor
216     }
217   catch ( const Error & /*error_*/ )
218     {
219       // Release resources
220       delete _imgRef;
221       throw;
222     }
223 }
224
225 // Construct Image of specified size, and format from in-memory BLOB
226 Magick::Image::Image ( const Blob &blob_,
227                        const Geometry &size_,
228                        const std::string &magick_ )
229   : _imgRef(new ImageRef)
230 {
231   try
232     {
233       // Read from Blob
234       read( blob_, size_, magick_ );
235     }
236   catch ( const Warning & /*warning_*/ )
237     {
238       // FIXME: need a way to report warnings in constructor
239     }
240   catch ( const Error & /*error_*/ )
241     {
242       // Release resources
243       delete _imgRef;
244       throw;
245     }
246 }
247
248 // Construct an image based on an array of raw pixels, of specified
249 // type and mapping, in memory
250 Magick::Image::Image ( const size_t width_,
251                        const size_t height_,
252                        const std::string &map_,
253                        const StorageType type_,
254                        const void *pixels_ )
255   : _imgRef(new ImageRef)
256 {
257   try
258     {
259       read( width_, height_, map_.c_str(), type_, pixels_ );
260     }
261   catch ( const Warning & /*warning_*/ )
262     {
263       // FIXME: need a way to report warnings in constructor
264     }
265   catch ( const Error & /*error_*/ )
266     {
267       // Release resources
268       delete _imgRef;
269       throw;
270     }
271 }
272
273 // Default constructor
274 Magick::Image::Image( void )
275   : _imgRef(new ImageRef)
276 {
277 }
278
279 // Destructor
280 /* virtual */
281 Magick::Image::~Image()
282 {
283   bool doDelete = false;
284   {
285     Lock( &_imgRef->_mutexLock );
286     if ( --_imgRef->_refCount == 0 )
287       doDelete = true;
288   }
289
290   if ( doDelete )
291     {
292       delete _imgRef;
293     }
294   _imgRef = 0;
295 }
296
297 // Adaptive-blur image
298 void Magick::Image::adaptiveBlur( const double radius_, const double sigma_ )
299 {
300   ExceptionInfo exceptionInfo;
301   GetExceptionInfo( &exceptionInfo );
302   MagickCore::Image* newImage =
303     AdaptiveBlurImage( image(), radius_, sigma_, image()->bias, &exceptionInfo);
304   replaceImage( newImage );
305   throwException( exceptionInfo );
306   (void) DestroyExceptionInfo( &exceptionInfo );
307 }
308
309 // Local adaptive threshold image
310 // http://www.dai.ed.ac.uk/HIPR2/adpthrsh.htm
311 // Width x height define the size of the pixel neighborhood
312 // offset = constant to subtract from pixel neighborhood mean
313 void Magick::Image::adaptiveThreshold ( const size_t width_,
314                                         const size_t height_,
315                                         const ssize_t offset_ )
316 {
317   ExceptionInfo exceptionInfo;
318   GetExceptionInfo( &exceptionInfo );
319   MagickCore::Image* newImage =
320     AdaptiveThresholdImage( constImage(), width_, height_, offset_, &exceptionInfo );
321   replaceImage( newImage );
322   throwException( exceptionInfo );
323   (void) DestroyExceptionInfo( &exceptionInfo );
324 }
325
326 // Add noise to image
327 void Magick::Image::addNoise( const NoiseType noiseType_ )
328 {
329   ExceptionInfo exceptionInfo;
330   GetExceptionInfo( &exceptionInfo );
331   MagickCore::Image* newImage =
332     AddNoiseImage ( image(),
333                     noiseType_, 1.0,
334                     &exceptionInfo );
335   replaceImage( newImage );
336   throwException( exceptionInfo );
337   (void) DestroyExceptionInfo( &exceptionInfo );
338 }
339
340 void Magick::Image::addNoiseChannel( const ChannelType channel_,
341                                      const NoiseType noiseType_ )
342 {
343   ExceptionInfo exceptionInfo;
344   GetExceptionInfo( &exceptionInfo );
345   ChannelType channel_mask = SetPixelChannelMask( image(), channel_);
346   MagickCore::Image* newImage =
347     AddNoiseImage ( image(),
348                            noiseType_, 1.0,
349                            &exceptionInfo );
350   (void) SetPixelChannelMapMask( image(), channel_mask );
351   replaceImage( newImage );
352   throwException( exceptionInfo );
353   (void) DestroyExceptionInfo( &exceptionInfo );
354 }
355
356 // Affine Transform image
357 void Magick::Image::affineTransform ( const DrawableAffine &affine_ )
358 {
359   ExceptionInfo exceptionInfo;
360   GetExceptionInfo( &exceptionInfo );
361   
362   AffineMatrix _affine;
363   _affine.sx = affine_.sx();
364   _affine.sy = affine_.sy();
365   _affine.rx = affine_.rx();
366   _affine.ry = affine_.ry();
367   _affine.tx = affine_.tx();  
368   _affine.ty = affine_.ty();
369   
370   MagickCore::Image* newImage =
371     AffineTransformImage( image(), &_affine, &exceptionInfo);     
372   replaceImage( newImage );
373   throwException( exceptionInfo );
374   (void) DestroyExceptionInfo( &exceptionInfo );
375 }
376
377 // Annotate using specified text, and placement location
378 void Magick::Image::annotate ( const std::string &text_,
379                                const Geometry &location_ )
380 {
381   annotate ( text_, location_,  NorthWestGravity, 0.0 );
382 }
383 // Annotate using specified text, bounding area, and placement gravity
384 void Magick::Image::annotate ( const std::string &text_,
385                                const Geometry &boundingArea_,
386                                const GravityType gravity_ )
387 {
388   annotate ( text_, boundingArea_, gravity_, 0.0 );
389 }
390 // Annotate with text using specified text, bounding area, placement
391 // gravity, and rotation.
392 void Magick::Image::annotate ( const std::string &text_,
393                                const Geometry &boundingArea_,
394                                const GravityType gravity_,
395                                const double degrees_ )
396 {
397   modifyImage();
398
399   DrawInfo *drawInfo
400     = options()->drawInfo();
401   
402   drawInfo->text = const_cast<char *>(text_.c_str());
403
404   char boundingArea[MaxTextExtent];
405
406   drawInfo->geometry = 0;
407   if ( boundingArea_.isValid() ){
408     if ( boundingArea_.width() == 0 || boundingArea_.height() == 0 )
409       {
410         FormatLocaleString( boundingArea, MaxTextExtent, "%+.20g%+.20g",
411           (double) boundingArea_.xOff(), (double) boundingArea_.yOff() );
412       }
413     else
414       {
415         (void) CopyMagickString( boundingArea, string(boundingArea_).c_str(),
416           MaxTextExtent);
417       }
418     drawInfo->geometry = boundingArea;
419   }
420
421   drawInfo->gravity = gravity_;
422
423   AffineMatrix oaffine = drawInfo->affine;
424   if ( degrees_ != 0.0)
425     {
426         AffineMatrix affine;
427         affine.sx=1.0;
428         affine.rx=0.0;
429         affine.ry=0.0;
430         affine.sy=1.0;
431         affine.tx=0.0;
432         affine.ty=0.0;
433
434         AffineMatrix current = drawInfo->affine;
435         affine.sx=cos(DegreesToRadians(fmod(degrees_,360.0)));
436         affine.rx=sin(DegreesToRadians(fmod(degrees_,360.0)));
437         affine.ry=(-sin(DegreesToRadians(fmod(degrees_,360.0))));
438         affine.sy=cos(DegreesToRadians(fmod(degrees_,360.0)));
439
440         drawInfo->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
441         drawInfo->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
442         drawInfo->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
443         drawInfo->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
444         drawInfo->affine.tx=current.sx*affine.tx+current.ry*affine.ty
445           +current.tx;
446     }
447
448   ExceptionInfo exceptionInfo;
449   GetExceptionInfo( &exceptionInfo );
450   AnnotateImage( image(), drawInfo, &exceptionInfo );
451
452   // Restore original values
453   drawInfo->affine = oaffine;
454   drawInfo->text = 0;
455   drawInfo->geometry = 0;
456
457   throwException( exceptionInfo );
458   (void) DestroyExceptionInfo( &exceptionInfo );
459 }
460 // Annotate with text (bounding area is entire image) and placement gravity.
461 void Magick::Image::annotate ( const std::string &text_,
462                                const GravityType gravity_ )
463 {
464   modifyImage();
465
466   DrawInfo *drawInfo
467     = options()->drawInfo();
468
469   drawInfo->text = const_cast<char *>(text_.c_str());
470
471   drawInfo->gravity = gravity_;
472
473   ExceptionInfo exceptionInfo;
474   GetExceptionInfo( &exceptionInfo );
475   AnnotateImage( image(), drawInfo, &exceptionInfo );
476
477   drawInfo->gravity = NorthWestGravity;
478   drawInfo->text = 0;
479
480   throwException( exceptionInfo );
481   (void) DestroyExceptionInfo( &exceptionInfo );
482 }
483
484 // Blur image
485 void Magick::Image::blur( const double radius_, const double sigma_ )
486 {
487   ExceptionInfo exceptionInfo;
488   GetExceptionInfo( &exceptionInfo );
489   MagickCore::Image* newImage =
490     BlurImage( image(), radius_, sigma_, image()->bias, &exceptionInfo);
491   replaceImage( newImage );
492   throwException( exceptionInfo );
493   (void) DestroyExceptionInfo( &exceptionInfo );
494 }
495
496 void Magick::Image::blurChannel( const ChannelType channel_,
497                                  const double radius_, const double sigma_ )
498 {
499   ExceptionInfo exceptionInfo;
500   GetExceptionInfo( &exceptionInfo );
501   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
502   MagickCore::Image* newImage =
503     BlurImage( image(), radius_, sigma_, image()->bias, &exceptionInfo);
504   (void) SetPixelChannelMapMask( image(), channel_mask );
505   replaceImage( newImage );
506   throwException( exceptionInfo );
507   (void) DestroyExceptionInfo( &exceptionInfo );
508 }
509
510 // Add border to image
511 // Only uses width & height
512 void Magick::Image::border( const Geometry &geometry_ )
513 {
514   RectangleInfo borderInfo = geometry_;
515   ExceptionInfo exceptionInfo;
516   GetExceptionInfo( &exceptionInfo );
517   MagickCore::Image* newImage =
518     BorderImage( image(), &borderInfo, image()->compose, &exceptionInfo);
519   replaceImage( newImage );
520   throwException( exceptionInfo );
521   (void) DestroyExceptionInfo( &exceptionInfo );
522 }
523
524 // Extract channel from image
525 void Magick::Image::channel ( const ChannelType channel_ )
526 {
527   modifyImage();
528   ExceptionInfo exceptionInfo;
529   GetExceptionInfo( &exceptionInfo );
530   MagickCore::Image* newImage =
531     SeparateImage( image(), channel_, &exceptionInfo);
532   replaceImage( newImage );
533   throwException( exceptionInfo );
534   (void) DestroyExceptionInfo( &exceptionInfo );
535 }
536
537 // Set or obtain modulus channel depth
538 void Magick::Image::channelDepth ( const size_t depth_ )
539 {
540   modifyImage();
541   ExceptionInfo exceptionInfo;
542   GetExceptionInfo( &exceptionInfo );
543   SetImageDepth( image(), depth_, &exceptionInfo);
544   throwException( exceptionInfo );
545   (void) DestroyExceptionInfo( &exceptionInfo );
546 }
547 size_t Magick::Image::channelDepth ( )
548 {
549   size_t channel_depth;
550
551   ExceptionInfo exceptionInfo;
552   GetExceptionInfo( &exceptionInfo );
553   channel_depth=GetImageDepth( constImage(), &exceptionInfo );
554   throwException( exceptionInfo );
555   (void) DestroyExceptionInfo( &exceptionInfo );
556   return channel_depth;
557 }
558
559
560 // Charcoal-effect image
561 void Magick::Image::charcoal( const double radius_, const double sigma_ )
562 {
563   ExceptionInfo exceptionInfo;
564   GetExceptionInfo( &exceptionInfo );
565   MagickCore::Image* newImage =
566     CharcoalImage( image(), radius_, sigma_, image()->bias, &exceptionInfo );
567   replaceImage( newImage );
568   throwException( exceptionInfo );
569   (void) DestroyExceptionInfo( &exceptionInfo );
570 }
571
572 // Chop image
573 void Magick::Image::chop( const Geometry &geometry_ )
574 {
575   RectangleInfo chopInfo = geometry_;
576   ExceptionInfo exceptionInfo;
577   GetExceptionInfo( &exceptionInfo );
578   MagickCore::Image* newImage =
579     ChopImage( image(), &chopInfo, &exceptionInfo);
580   replaceImage( newImage );
581   throwException( exceptionInfo );
582   (void) DestroyExceptionInfo( &exceptionInfo );
583 }
584
585 // contains one or more color corrections and applies the correction to the
586 // image.
587 void Magick::Image::cdl ( const std::string &cdl_ )
588 {
589   modifyImage();
590   ExceptionInfo exceptionInfo;
591   GetExceptionInfo( &exceptionInfo );
592   (void) ColorDecisionListImage( image(), cdl_.c_str(), &exceptionInfo );
593   throwException( exceptionInfo );
594   (void) DestroyExceptionInfo( &exceptionInfo );
595 }
596
597 // Colorize
598 void Magick::Image::colorize ( const unsigned int alphaRed_,
599                                const unsigned int alphaGreen_,
600                                const unsigned int alphaBlue_,
601                                const Color &penColor_ )
602 {
603   if ( !penColor_.isValid() )
604   {
605     throwExceptionExplicit( OptionError,
606                             "Pen color argument is invalid");
607   }
608
609   char blend[MaxTextExtent];
610   FormatLocaleString(blend,MaxTextExtent,"%u/%u/%u",alphaRed_,alphaGreen_,alphaBlue_);
611
612   ExceptionInfo exceptionInfo;
613   GetExceptionInfo( &exceptionInfo );
614   PixelInfo target;
615   GetPixelInfo(image(),&target);
616   PixelInfo pixel=static_cast<PixelInfo>(penColor_);
617   target.red=pixel.red;
618   target.green=pixel.green;
619   target.blue=pixel.blue;
620   target.alpha=pixel.alpha;
621   MagickCore::Image* newImage =
622     ColorizeImage ( image(), blend, &target, &exceptionInfo );
623   replaceImage( newImage );
624   throwException( exceptionInfo );
625   (void) DestroyExceptionInfo( &exceptionInfo );
626 }
627 void Magick::Image::colorize ( const unsigned int alpha_,
628                                const Color &penColor_ )
629 {
630   colorize( alpha_, alpha_, alpha_, penColor_ );
631 }
632
633 // Apply a color matrix to the image channels.  The user supplied
634 // matrix may be of order 1 to 6 (1x1 through 6x6).
635 void Magick::Image::colorMatrix (const size_t order_,
636          const double *color_matrix_)
637 {
638   KernelInfo
639     *kernel_info;
640
641   ExceptionInfo exceptionInfo;
642   GetExceptionInfo( &exceptionInfo );
643   kernel_info=AcquireKernelInfo((const char *) NULL);
644   kernel_info->width=order_;
645   kernel_info->height=order_;
646   kernel_info->values=(double *) color_matrix_;
647   MagickCore::Image* newImage =
648     ColorMatrixImage( image(), kernel_info, &exceptionInfo );
649   kernel_info->values=(double *) NULL;
650   kernel_info=DestroyKernelInfo(kernel_info);
651   replaceImage( newImage );
652   throwException( exceptionInfo );
653   (void) DestroyExceptionInfo( &exceptionInfo );
654 }
655
656 // Compare current image with another image
657 // Sets meanErrorPerPixel, normalizedMaxError, and normalizedMeanError
658 // in the current image. False is returned if the images are identical.
659 bool Magick::Image::compare ( const Image &reference_ )
660 {
661   ExceptionInfo exceptionInfo;
662   GetExceptionInfo( &exceptionInfo );
663   modifyImage();
664   Image ref = reference_;
665   ref.modifyImage();
666   bool status =
667     static_cast<bool>(IsImagesEqual(image(), ref.image(), &exceptionInfo));
668   throwException( exceptionInfo );
669   (void) DestroyExceptionInfo( &exceptionInfo );
670   return status;
671 }
672
673 // Composite two images
674 void Magick::Image::composite ( const Image &compositeImage_,
675                                 const ssize_t xOffset_,
676                                 const ssize_t yOffset_,
677                                 const CompositeOperator compose_ )
678 {
679   // Image supplied as compositeImage is composited with current image and
680   // results in updating current image.
681   modifyImage();
682
683   ExceptionInfo exceptionInfo;
684   GetExceptionInfo( &exceptionInfo );
685   CompositeImage( image(),
686                   compose_,
687                   compositeImage_.constImage(),
688                   xOffset_,
689                   yOffset_, &exceptionInfo );
690   throwException( exceptionInfo );
691   (void) DestroyExceptionInfo( &exceptionInfo );
692 }
693 void Magick::Image::composite ( const Image &compositeImage_,
694                                 const Geometry &offset_,
695                                 const CompositeOperator compose_ )
696 {
697   modifyImage();
698
699   ssize_t x = offset_.xOff();
700   ssize_t y = offset_.yOff();
701   size_t width = columns();
702   size_t height = rows();
703
704   ParseMetaGeometry (static_cast<std::string>(offset_).c_str(),
705                       &x, &y,
706                       &width, &height );
707
708   ExceptionInfo exceptionInfo;
709   GetExceptionInfo( &exceptionInfo );
710   CompositeImage( image(),
711                   compose_,
712                   compositeImage_.constImage(),
713                   x, y, &exceptionInfo );
714   throwException( exceptionInfo );
715   (void) DestroyExceptionInfo( &exceptionInfo );
716 }
717 void Magick::Image::composite ( const Image &compositeImage_,
718                                 const GravityType gravity_,
719                                 const CompositeOperator compose_ )
720 {
721   modifyImage();
722
723   RectangleInfo geometry;
724
725   SetGeometry(compositeImage_.constImage(), &geometry);
726   GravityAdjustGeometry(columns(), rows(), gravity_, &geometry);
727
728   ExceptionInfo exceptionInfo;
729   GetExceptionInfo( &exceptionInfo );
730   CompositeImage( image(),
731                   compose_,
732                   compositeImage_.constImage(),
733                   geometry.x, geometry.y, &exceptionInfo );
734   throwException( exceptionInfo );
735   (void) DestroyExceptionInfo( &exceptionInfo );
736 }
737
738 // Contrast image
739 void Magick::Image::contrast ( const size_t sharpen_ )
740 {
741   modifyImage();
742   ExceptionInfo exceptionInfo;
743   GetExceptionInfo( &exceptionInfo );
744   ContrastImage ( image(), (MagickBooleanType) sharpen_, &exceptionInfo );
745   throwException( exceptionInfo );
746   (void) DestroyExceptionInfo( &exceptionInfo );
747 }
748
749 // Convolve image.  Applies a general image convolution kernel to the image.
750 //  order_ represents the number of columns and rows in the filter kernel.
751 //  kernel_ is an array of doubles representing the convolution kernel.
752 void Magick::Image::convolve ( const size_t order_,
753                                const double *kernel_ )
754 {
755   KernelInfo
756     *kernel_info;
757
758   ExceptionInfo exceptionInfo;
759   GetExceptionInfo( &exceptionInfo );
760   kernel_info=AcquireKernelInfo((const char *) NULL);
761   kernel_info->width=order_;
762   kernel_info->height=order_;
763   kernel_info->values=(MagickRealType *) kernel_;
764   kernel_info->bias=image()->bias;
765   MagickCore::Image* newImage =
766     ConvolveImage ( image(), kernel_info, &exceptionInfo );
767   kernel_info->values=(MagickRealType *) NULL;
768   kernel_info=DestroyKernelInfo(kernel_info);
769   replaceImage( newImage );
770   throwException( exceptionInfo );
771   (void) DestroyExceptionInfo( &exceptionInfo );
772 }
773
774 // Crop image
775 void Magick::Image::crop ( const Geometry &geometry_ )
776 {
777   RectangleInfo cropInfo = geometry_;
778   ExceptionInfo exceptionInfo;
779   GetExceptionInfo( &exceptionInfo );
780   MagickCore::Image* newImage =
781     CropImage( image(),
782                &cropInfo,
783                &exceptionInfo);
784   replaceImage( newImage );
785   throwException( exceptionInfo );
786   (void) DestroyExceptionInfo( &exceptionInfo );
787 }
788
789 // Cycle Color Map
790 void Magick::Image::cycleColormap ( const ssize_t amount_ )
791 {
792   ExceptionInfo exceptionInfo;
793   GetExceptionInfo( &exceptionInfo );
794   modifyImage();
795   CycleColormapImage( image(), amount_, &exceptionInfo );
796   throwException( exceptionInfo );
797   (void) DestroyExceptionInfo( &exceptionInfo );
798 }
799
800 // Despeckle
801 void Magick::Image::despeckle ( void )
802 {
803   ExceptionInfo exceptionInfo;
804   GetExceptionInfo( &exceptionInfo );
805   MagickCore::Image* newImage =
806     DespeckleImage( image(), &exceptionInfo );
807   replaceImage( newImage );
808   throwException( exceptionInfo );
809   (void) DestroyExceptionInfo( &exceptionInfo );
810 }
811
812 // Display image
813 void Magick::Image::display( void )
814 {
815   ExceptionInfo exceptionInfo;
816   GetExceptionInfo( &exceptionInfo );
817   DisplayImages( imageInfo(), image(), &exceptionInfo );
818   throwException( exceptionInfo );
819   (void) DestroyExceptionInfo( &exceptionInfo );
820 }
821
822 // Distort image.  distorts an image using various distortion methods, by
823 // mapping color lookups of the source image to a new destination image
824 // usally of the same size as the source image, unless 'bestfit' is set to
825 // true.
826 void Magick::Image::distort ( const DistortImageMethod method_,
827                               const size_t number_arguments_,
828                               const double *arguments_,
829                               const bool bestfit_ )
830 {
831   ExceptionInfo exceptionInfo;
832   GetExceptionInfo( &exceptionInfo );
833   MagickCore::Image* newImage = DistortImage ( image(), method_,
834     number_arguments_, arguments_, bestfit_ == true ? MagickTrue : MagickFalse,
835     &exceptionInfo );
836   replaceImage( newImage );
837   throwException( exceptionInfo );
838   (void) DestroyExceptionInfo( &exceptionInfo );
839 }
840
841 // Draw on image using single drawable
842 void Magick::Image::draw ( const Magick::Drawable &drawable_ )
843 {
844   modifyImage();
845
846   DrawingWand *wand = DrawAllocateWand( options()->drawInfo(), image());
847
848   if(wand)
849     {
850       drawable_.operator()(wand);
851
852       DrawRender(wand);
853
854       wand=DestroyDrawingWand(wand);
855     }
856
857   throwImageException();
858 }
859
860 // Draw on image using a drawable list
861 void Magick::Image::draw ( const std::list<Magick::Drawable> &drawable_ )
862 {
863   modifyImage();
864
865   DrawingWand *wand = DrawAllocateWand( options()->drawInfo(), image());
866
867   if(wand)
868     {
869       for( std::list<Magick::Drawable>::const_iterator p = drawable_.begin();
870            p != drawable_.end(); p++ )
871         {
872           p->operator()(wand);
873         }
874
875       DrawRender(wand);
876
877       wand=DestroyDrawingWand(wand);
878     }
879
880   throwImageException();
881 }
882
883 // Hilight edges in image
884 void Magick::Image::edge ( const double radius_, const double sigma_ )
885 {
886   ExceptionInfo exceptionInfo;
887   GetExceptionInfo( &exceptionInfo );
888   MagickCore::Image* newImage =
889     EdgeImage( image(), radius_, sigma_, &exceptionInfo );
890   replaceImage( newImage );
891   throwException( exceptionInfo );
892   (void) DestroyExceptionInfo( &exceptionInfo );
893 }
894
895 // Emboss image (hilight edges)
896 void Magick::Image::emboss ( const double radius_, const double sigma_ )
897 {
898   ExceptionInfo exceptionInfo;
899   GetExceptionInfo( &exceptionInfo );
900   MagickCore::Image* newImage =
901     EmbossImage( image(), radius_, sigma_, &exceptionInfo );
902   replaceImage( newImage );
903   throwException( exceptionInfo );
904   (void) DestroyExceptionInfo( &exceptionInfo );
905 }
906
907 // Enhance image (minimize noise)
908 void Magick::Image::enhance ( void )
909 {
910   ExceptionInfo exceptionInfo;
911   GetExceptionInfo( &exceptionInfo );
912   MagickCore::Image* newImage =
913     EnhanceImage( image(), &exceptionInfo );
914   replaceImage( newImage );
915   throwException( exceptionInfo );
916   (void) DestroyExceptionInfo( &exceptionInfo );
917 }
918
919 // Equalize image (histogram equalization)
920 void Magick::Image::equalize ( void )
921 {
922   ExceptionInfo exceptionInfo;
923   GetExceptionInfo( &exceptionInfo );
924   modifyImage();
925   EqualizeImage( image(), &exceptionInfo );
926   throwException( exceptionInfo );
927   (void) DestroyExceptionInfo( &exceptionInfo );
928 }
929
930 // Erase image to current "background color"
931 void Magick::Image::erase ( void )
932 {
933   modifyImage();
934   ExceptionInfo exceptionInfo;
935   GetExceptionInfo( &exceptionInfo );
936   SetImageBackgroundColor( image(), &exceptionInfo );
937   throwException( exceptionInfo );
938   (void) DestroyExceptionInfo( &exceptionInfo );
939 }
940
941 // Extends image as defined by the geometry.
942 //
943 void Magick::Image::extent ( const Geometry &geometry_ )
944 {
945   RectangleInfo extentInfo = geometry_;
946   modifyImage();
947   ExceptionInfo exceptionInfo;
948   GetExceptionInfo( &exceptionInfo );
949   MagickCore::Image* newImage =
950     ExtentImage ( image(), &extentInfo, &exceptionInfo );
951   replaceImage( newImage );
952   throwException( exceptionInfo );
953   (void) DestroyExceptionInfo( &exceptionInfo );
954 }
955 void Magick::Image::extent ( const Geometry &geometry_, const Color &backgroundColor_ )
956 {
957   backgroundColor ( backgroundColor_ );
958   extent ( geometry_ );
959 }
960 void Magick::Image::extent ( const Geometry &geometry_, const GravityType gravity_ )
961 {
962   image()->gravity  = gravity_;
963   extent ( geometry_ );
964 }
965 void Magick::Image::extent ( const Geometry &geometry_, const Color &backgroundColor_, const GravityType gravity_ )
966 {
967   image()->gravity  = gravity_;
968   backgroundColor ( backgroundColor_ );
969   extent ( geometry_ );
970 }
971
972 // Flip image (reflect each scanline in the vertical direction)
973 void Magick::Image::flip ( void )
974 {
975   ExceptionInfo exceptionInfo;
976   GetExceptionInfo( &exceptionInfo );
977   MagickCore::Image* newImage =
978     FlipImage( image(), &exceptionInfo );
979   replaceImage( newImage );
980   throwException( exceptionInfo );
981   (void) DestroyExceptionInfo( &exceptionInfo );
982 }
983
984 // Flood-fill color across pixels that match the color of the
985 // target pixel and are neighbors of the target pixel.
986 // Uses current fuzz setting when determining color match.
987 void Magick::Image::floodFillColor( const ssize_t x_,
988                                     const ssize_t y_,
989                                     const Magick::Color &fillColor_ )
990 {
991   floodFillTexture( x_, y_, Image( Geometry( 1, 1), fillColor_ ) );
992 }
993 void Magick::Image::floodFillColor( const Geometry &point_,
994                                     const Magick::Color &fillColor_ )
995 {
996   floodFillTexture( point_, Image( Geometry( 1, 1), fillColor_) );
997 }
998
999 // Flood-fill color across pixels starting at target-pixel and
1000 // stopping at pixels matching specified border color.
1001 // Uses current fuzz setting when determining color match.
1002 void Magick::Image::floodFillColor( const ssize_t x_,
1003                                     const ssize_t y_,
1004                                     const Magick::Color &fillColor_,
1005                                     const Magick::Color &borderColor_ )
1006 {
1007   floodFillTexture( x_, y_, Image( Geometry( 1, 1), fillColor_),
1008                     borderColor_ );
1009 }
1010 void Magick::Image::floodFillColor( const Geometry &point_,
1011                                     const Magick::Color &fillColor_,
1012                                     const Magick::Color &borderColor_ )
1013 {
1014   floodFillTexture( point_, Image( Geometry( 1, 1), fillColor_),
1015                     borderColor_ );
1016 }
1017
1018 // Floodfill pixels matching color (within fuzz factor) of target
1019 // pixel(x,y) with replacement alpha value using method.
1020 void Magick::Image::floodFillAlpha( const ssize_t x_,
1021                                       const ssize_t y_,
1022                                       const unsigned int alpha_,
1023                                       const PaintMethod method_ )
1024 {
1025   modifyImage();
1026   PixelInfo target;
1027   GetPixelInfo(image(),&target);
1028   PixelInfo pixel=static_cast<PixelInfo>(pixelColor(x_,y_));
1029   target.red=pixel.red;
1030   target.green=pixel.green;
1031   target.blue=pixel.blue;
1032   target.alpha=alpha_;
1033   ExceptionInfo exceptionInfo;
1034   GetExceptionInfo( &exceptionInfo );
1035   FloodfillPaintImage ( image(),
1036                         options()->drawInfo(), // const DrawInfo *draw_info
1037                         &target,
1038                                         static_cast<ssize_t>(x_), static_cast<ssize_t>(y_),
1039                         method_  == FloodfillMethod ? MagickFalse : MagickTrue,
1040     &exceptionInfo);
1041   throwException( exceptionInfo );
1042   (void) DestroyExceptionInfo( &exceptionInfo );
1043 }
1044
1045 // Flood-fill texture across pixels that match the color of the
1046 // target pixel and are neighbors of the target pixel.
1047 // Uses current fuzz setting when determining color match.
1048 void Magick::Image::floodFillTexture( const ssize_t x_,
1049                                       const ssize_t y_,
1050                                       const Magick::Image &texture_ )
1051 {
1052   modifyImage();
1053
1054   // Set drawing pattern
1055   options()->fillPattern(texture_.constImage());
1056
1057   // Get pixel view
1058   Pixels pixels(*this);
1059   // Fill image
1060   Quantum *p = pixels.get(x_, y_, 1, 1 );
1061   PixelInfo target;
1062   GetPixelInfo(constImage(),&target);
1063   target.red=GetPixelRed(constImage(),p);
1064   target.green=GetPixelGreen(constImage(),p);
1065   target.blue=GetPixelBlue(constImage(),p);
1066   ExceptionInfo exceptionInfo;
1067   GetExceptionInfo( &exceptionInfo );
1068   if (p)
1069     FloodfillPaintImage ( image(), // Image *image
1070                           options()->drawInfo(), // const DrawInfo *draw_info
1071                           &target, // const MagickPacket target
1072                           static_cast<ssize_t>(x_), // const ssize_t x_offset
1073                           static_cast<ssize_t>(y_), // const ssize_t y_offset
1074                           MagickFalse, // const PaintMethod method
1075       &exceptionInfo );
1076   throwException( exceptionInfo );
1077   (void) DestroyExceptionInfo( &exceptionInfo );
1078
1079 }
1080 void Magick::Image::floodFillTexture( const Magick::Geometry &point_,
1081                                       const Magick::Image &texture_ )
1082 {
1083   floodFillTexture( point_.xOff(), point_.yOff(), texture_ );
1084 }
1085
1086 // Flood-fill texture across pixels starting at target-pixel and
1087 // stopping at pixels matching specified border color.
1088 // Uses current fuzz setting when determining color match.
1089 void Magick::Image::floodFillTexture( const ssize_t x_,
1090                                       const ssize_t y_,
1091                                       const Magick::Image &texture_,
1092                                       const Magick::Color &borderColor_ )
1093 {
1094   modifyImage();
1095
1096   // Set drawing fill pattern
1097   options()->fillPattern(texture_.constImage());
1098
1099   PixelInfo target;
1100   GetPixelInfo(constImage(),&target);
1101   target.red=static_cast<PixelInfo>(borderColor_).red;
1102   target.green=static_cast<PixelInfo>(borderColor_).green;
1103   target.blue=static_cast<PixelInfo>(borderColor_).blue;
1104   ExceptionInfo exceptionInfo;
1105   GetExceptionInfo( &exceptionInfo );
1106   FloodfillPaintImage ( image(),
1107                         options()->drawInfo(),
1108                         &target,
1109                         static_cast<ssize_t>(x_),
1110                         static_cast<ssize_t>(y_),
1111                         MagickTrue, &exceptionInfo);
1112
1113   throwException( exceptionInfo );
1114   (void) DestroyExceptionInfo( &exceptionInfo );
1115 }
1116 void  Magick::Image::floodFillTexture( const Magick::Geometry &point_,
1117                                        const Magick::Image &texture_,
1118                                        const Magick::Color &borderColor_ )
1119 {
1120   floodFillTexture( point_.xOff(), point_.yOff(), texture_, borderColor_ );
1121 }
1122
1123 // Flop image (reflect each scanline in the horizontal direction)
1124 void Magick::Image::flop ( void )
1125 {
1126   ExceptionInfo exceptionInfo;
1127   GetExceptionInfo( &exceptionInfo );
1128   MagickCore::Image* newImage =
1129     FlopImage( image(), &exceptionInfo );
1130   replaceImage( newImage );
1131   throwException( exceptionInfo );
1132   (void) DestroyExceptionInfo( &exceptionInfo );
1133 }
1134
1135 // Frame image
1136 void Magick::Image::frame ( const Geometry &geometry_ )
1137 {
1138   FrameInfo info;
1139
1140   info.x           = static_cast<ssize_t>(geometry_.width());
1141   info.y           = static_cast<ssize_t>(geometry_.height());
1142   info.width       = columns() + ( static_cast<size_t>(info.x) << 1 );
1143   info.height      = rows() + ( static_cast<size_t>(info.y) << 1 );
1144   info.outer_bevel = geometry_.xOff();
1145   info.inner_bevel = geometry_.yOff();
1146
1147   ExceptionInfo exceptionInfo;
1148   GetExceptionInfo( &exceptionInfo );
1149   MagickCore::Image* newImage =
1150     FrameImage( image(), &info, image()->compose, &exceptionInfo );
1151   replaceImage( newImage );
1152   throwException( exceptionInfo );
1153   (void) DestroyExceptionInfo( &exceptionInfo );
1154 }
1155 void Magick::Image::frame ( const size_t width_,
1156                             const size_t height_,
1157                             const ssize_t outerBevel_, const ssize_t innerBevel_ )
1158 {
1159   FrameInfo info;
1160   info.x           = static_cast<ssize_t>(width_);
1161   info.y           = static_cast<ssize_t>(height_);
1162   info.width       = columns() + ( static_cast<size_t>(info.x) << 1 );
1163   info.height      = rows() + ( static_cast<size_t>(info.y) << 1 );
1164   info.outer_bevel = static_cast<ssize_t>(outerBevel_);
1165   info.inner_bevel = static_cast<ssize_t>(innerBevel_);
1166
1167   ExceptionInfo exceptionInfo;
1168   GetExceptionInfo( &exceptionInfo );
1169   MagickCore::Image* newImage =
1170     FrameImage( image(), &info, image()->compose, &exceptionInfo );
1171   replaceImage( newImage );
1172   throwException( exceptionInfo );
1173   (void) DestroyExceptionInfo( &exceptionInfo );
1174 }
1175
1176 // Fx image.  Applies a mathematical expression to the image.
1177 void Magick::Image::fx ( const std::string expression )
1178 {
1179   ExceptionInfo exceptionInfo;
1180   GetExceptionInfo( &exceptionInfo );
1181   MagickCore::Image* newImage =
1182     FxImage ( image(), expression.c_str(), &exceptionInfo );
1183   replaceImage( newImage );
1184   throwException( exceptionInfo );
1185   (void) DestroyExceptionInfo( &exceptionInfo );
1186 }
1187 void Magick::Image::fx ( const std::string expression,
1188                          const Magick::ChannelType channel )
1189 {
1190   ExceptionInfo exceptionInfo;
1191   GetExceptionInfo( &exceptionInfo );
1192   ChannelType channel_mask = SetPixelChannelMask( image(), channel );
1193   MagickCore::Image* newImage =
1194     FxImage ( image(), expression.c_str(), &exceptionInfo );
1195   (void) SetPixelChannelMapMask( image(), channel_mask );
1196   replaceImage( newImage );
1197   throwException( exceptionInfo );
1198   (void) DestroyExceptionInfo( &exceptionInfo );
1199 }
1200
1201 // Gamma correct image
1202 void Magick::Image::gamma ( const double gamma_ )
1203 {
1204   ExceptionInfo exceptionInfo;
1205   GetExceptionInfo( &exceptionInfo );
1206   modifyImage();
1207   GammaImage ( image(), gamma_, &exceptionInfo );
1208   throwException( exceptionInfo );
1209   (void) DestroyExceptionInfo( &exceptionInfo );
1210 }
1211
1212 void Magick::Image::gamma ( const double gammaRed_,
1213                             const double gammaGreen_,
1214                             const double gammaBlue_ )
1215 {
1216   char gamma[MaxTextExtent + 1];
1217   FormatLocaleString( gamma, MaxTextExtent, "%3.6f/%3.6f/%3.6f/",
1218                 gammaRed_, gammaGreen_, gammaBlue_);
1219
1220   ExceptionInfo exceptionInfo;
1221   GetExceptionInfo( &exceptionInfo );
1222   modifyImage();
1223   GammaImage ( image(), atof(gamma), &exceptionInfo );
1224   throwException( exceptionInfo );
1225   (void) DestroyExceptionInfo( &exceptionInfo );
1226 }
1227
1228 // Gaussian blur image
1229 // The number of neighbor pixels to be included in the convolution
1230 // mask is specified by 'width_'. The standard deviation of the
1231 // gaussian bell curve is specified by 'sigma_'.
1232 void Magick::Image::gaussianBlur ( const double width_, const double sigma_ )
1233 {
1234   ExceptionInfo exceptionInfo;
1235   GetExceptionInfo( &exceptionInfo );
1236   MagickCore::Image* newImage =
1237     GaussianBlurImage( image(), width_, sigma_, &exceptionInfo );
1238   replaceImage( newImage );
1239   throwException( exceptionInfo );
1240   (void) DestroyExceptionInfo( &exceptionInfo );
1241 }
1242
1243 void Magick::Image::gaussianBlurChannel ( const ChannelType channel_,
1244                                           const double width_,
1245                                           const double sigma_ )
1246 {
1247   ExceptionInfo exceptionInfo;
1248   GetExceptionInfo( &exceptionInfo );
1249   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
1250   MagickCore::Image* newImage =
1251     GaussianBlurImage( image(), width_, sigma_, &exceptionInfo );
1252   (void) SetPixelChannelMapMask( image(), channel_mask );
1253   replaceImage( newImage );
1254   throwException( exceptionInfo );
1255   (void) DestroyExceptionInfo( &exceptionInfo );
1256 }
1257
1258 // Apply a color lookup table (Hald CLUT) to the image.
1259 void  Magick::Image::haldClut ( const Image &clutImage_ )
1260 {
1261   ExceptionInfo exceptionInfo;
1262   GetExceptionInfo( &exceptionInfo );
1263   modifyImage();
1264   (void) HaldClutImage( image(), clutImage_.constImage(), &exceptionInfo );
1265   throwException( exceptionInfo );
1266   (void) DestroyExceptionInfo( &exceptionInfo );
1267 }
1268
1269 // Implode image
1270 void Magick::Image::implode ( const double factor_ )
1271 {
1272   ExceptionInfo exceptionInfo;
1273   GetExceptionInfo( &exceptionInfo );
1274   MagickCore::Image* newImage =
1275     ImplodeImage( image(), factor_, image()->interpolate, &exceptionInfo );
1276   replaceImage( newImage );
1277   throwException( exceptionInfo );
1278   (void) DestroyExceptionInfo( &exceptionInfo );
1279 }
1280
1281 // implements the inverse discrete Fourier transform (IFT) of the image either
1282 // as a magnitude / phase or real / imaginary image pair.
1283 void Magick::Image::inverseFourierTransform ( const Image &phase_ )
1284 {
1285   ExceptionInfo exceptionInfo;
1286   GetExceptionInfo( &exceptionInfo );
1287   MagickCore::Image* newImage = InverseFourierTransformImage( image(),
1288                  phase_.constImage(), MagickTrue, &exceptionInfo);
1289   replaceImage( newImage );
1290   throwException( exceptionInfo );
1291   (void) DestroyExceptionInfo( &exceptionInfo );
1292 }
1293 void Magick::Image::inverseFourierTransform ( const Image &phase_,
1294    const bool magnitude_ )
1295 {
1296   ExceptionInfo exceptionInfo;
1297   GetExceptionInfo( &exceptionInfo );
1298   MagickCore::Image* newImage = InverseFourierTransformImage( image(),
1299                  phase_.constImage(), magnitude_ == true ? MagickTrue : MagickFalse,
1300      &exceptionInfo);
1301   replaceImage( newImage );
1302   throwException( exceptionInfo );
1303   (void) DestroyExceptionInfo( &exceptionInfo );
1304 }
1305
1306 // Level image. Adjust the levels of the image by scaling the colors
1307 // falling between specified white and black points to the full
1308 // available quantum range. The parameters provided represent the
1309 // black, mid (gamma), and white points.  The black point specifies
1310 // the darkest color in the image. Colors darker than the black point
1311 // are set to zero. Mid point (gamma) specifies a gamma correction to
1312 // apply to the image. White point specifies the lightest color in the
1313 // image.  Colors brighter than the white point are set to the maximum
1314 // quantum value. The black and white point have the valid range 0 to
1315 // QuantumRange while gamma has a useful range of 0 to ten.
1316 void Magick::Image::level ( const double black_point,
1317                             const double white_point,
1318                             const double gamma )
1319 {
1320   ExceptionInfo exceptionInfo;
1321   GetExceptionInfo( &exceptionInfo );
1322   modifyImage();
1323   (void) LevelImage( image(), black_point, white_point, gamma, &exceptionInfo );
1324   throwException( exceptionInfo );
1325   (void) DestroyExceptionInfo( &exceptionInfo );
1326 }
1327
1328 // Magnify image by integral size
1329 void Magick::Image::magnify ( void )
1330 {
1331   ExceptionInfo exceptionInfo;
1332   GetExceptionInfo( &exceptionInfo );
1333   MagickCore::Image* newImage =
1334     MagnifyImage( image(), &exceptionInfo );
1335   replaceImage( newImage );
1336   throwException( exceptionInfo );
1337   (void) DestroyExceptionInfo( &exceptionInfo );
1338 }
1339
1340 // Remap image colors with closest color from reference image
1341 void Magick::Image::map ( const Image &mapImage_ , const bool dither_ )
1342 {
1343   ExceptionInfo exceptionInfo;
1344   GetExceptionInfo( &exceptionInfo );
1345   modifyImage();
1346   options()->quantizeDither( dither_ );
1347   RemapImage ( options()->quantizeInfo(), image(),
1348              mapImage_.constImage(), &exceptionInfo);
1349   throwException( exceptionInfo );
1350   (void) DestroyExceptionInfo( &exceptionInfo );
1351 }
1352 // Floodfill designated area with replacement alpha value
1353 void Magick::Image::matteFloodfill ( const Color &target_ ,
1354                                      const unsigned int alpha_,
1355                                      const ssize_t x_, const ssize_t y_,
1356                                      const Magick::PaintMethod method_ )
1357 {
1358   modifyImage();
1359   PixelInfo target;
1360   GetPixelInfo(constImage(),&target);
1361   target.red=static_cast<PixelInfo>(target_).red;
1362   target.green=static_cast<PixelInfo>(target_).green;
1363   target.blue=static_cast<PixelInfo>(target_).blue;
1364   target.alpha=alpha_;
1365   ChannelType channel_mask = SetPixelChannelMask( image(), AlphaChannel );
1366   ExceptionInfo exceptionInfo;
1367   GetExceptionInfo( &exceptionInfo );
1368   FloodfillPaintImage ( image(), options()->drawInfo(), &target, x_, y_,
1369     method_ == FloodfillMethod ? MagickFalse : MagickTrue, &exceptionInfo);
1370   (void) SetPixelChannelMapMask( image(), channel_mask );
1371   throwException( exceptionInfo );
1372   (void) DestroyExceptionInfo( &exceptionInfo );
1373 }
1374
1375 // Filter image by replacing each pixel component with the median
1376 // color in a circular neighborhood
1377 void Magick::Image::medianFilter ( const double radius_ )
1378 {
1379   ExceptionInfo exceptionInfo;
1380   GetExceptionInfo( &exceptionInfo );
1381   MagickCore::Image* newImage =
1382     StatisticImage ( image(), MedianStatistic, (size_t) radius_, (size_t)
1383     radius_,&exceptionInfo );
1384   replaceImage( newImage );
1385   throwException( exceptionInfo );
1386   (void) DestroyExceptionInfo( &exceptionInfo );
1387 }
1388
1389 // Reduce image by integral size
1390 void Magick::Image::minify ( void )
1391 {
1392   ExceptionInfo exceptionInfo;
1393   GetExceptionInfo( &exceptionInfo );
1394   MagickCore::Image* newImage =
1395     MinifyImage( image(), &exceptionInfo );
1396   replaceImage( newImage );
1397   throwException( exceptionInfo );
1398   (void) DestroyExceptionInfo( &exceptionInfo );
1399 }
1400
1401 // Modulate percent hue, saturation, and brightness of an image
1402 void Magick::Image::modulate ( const double brightness_,
1403                                const double saturation_,
1404                                const double hue_ )
1405 {
1406   char modulate[MaxTextExtent + 1];
1407   FormatLocaleString( modulate, MaxTextExtent, "%3.6f,%3.6f,%3.6f",
1408                 brightness_, saturation_, hue_);
1409
1410   ExceptionInfo exceptionInfo;
1411   GetExceptionInfo( &exceptionInfo );
1412   modifyImage();
1413   ModulateImage( image(), modulate, &exceptionInfo );
1414   throwException( exceptionInfo );
1415   (void) DestroyExceptionInfo( &exceptionInfo );
1416 }
1417
1418 // Motion blur image with specified blur factor
1419 // The radius_ parameter specifies the radius of the Gaussian, in
1420 // pixels, not counting the center pixel.  The sigma_ parameter
1421 // specifies the standard deviation of the Laplacian, in pixels.
1422 // The angle_ parameter specifies the angle the object appears
1423 // to be comming from (zero degrees is from the right).
1424 void            Magick::Image::motionBlur ( const double radius_,
1425                                             const double sigma_,
1426                                             const double angle_ )
1427 {
1428   ExceptionInfo exceptionInfo;
1429   GetExceptionInfo( &exceptionInfo );
1430   MagickCore::Image* newImage =
1431     MotionBlurImage( image(), radius_, sigma_, angle_, 0.0, &exceptionInfo);
1432   replaceImage( newImage );
1433   throwException( exceptionInfo );
1434   (void) DestroyExceptionInfo( &exceptionInfo );
1435 }
1436     
1437 // Negate image.  Set grayscale_ to true to effect grayscale values
1438 // only
1439 void Magick::Image::negate ( const bool grayscale_ )
1440 {
1441   ExceptionInfo exceptionInfo;
1442   GetExceptionInfo( &exceptionInfo );
1443   modifyImage();
1444   NegateImage ( image(), grayscale_ == true ? MagickTrue : MagickFalse, 
1445     &exceptionInfo );
1446   throwException( exceptionInfo );
1447   (void) DestroyExceptionInfo( &exceptionInfo );
1448 }
1449
1450 // Normalize image
1451 void Magick::Image::normalize ( void )
1452 {
1453   modifyImage();
1454   ExceptionInfo exceptionInfo;
1455   GetExceptionInfo( &exceptionInfo );
1456   NormalizeImage ( image(), &exceptionInfo );
1457   throwException( exceptionInfo );
1458   (void) DestroyExceptionInfo( &exceptionInfo );
1459 }
1460
1461 // Oilpaint image
1462 void Magick::Image::oilPaint ( const double radius_, const double sigma_ )
1463 {
1464   ExceptionInfo exceptionInfo;
1465   GetExceptionInfo( &exceptionInfo );
1466   MagickCore::Image* newImage =
1467     OilPaintImage( image(), radius_, sigma_, &exceptionInfo );
1468   replaceImage( newImage );
1469   throwException( exceptionInfo );
1470   (void) DestroyExceptionInfo( &exceptionInfo );
1471 }
1472
1473 // Set or attenuate the alpha channel. If the image pixels are
1474 // opaque then they are set to the specified alpha value, otherwise
1475 // they are blended with the supplied alpha value.  The value of
1476 // alpha_ ranges from 0 (completely opaque) to QuantumRange. The defines
1477 // OpaqueAlpha and TransparentAlpha are available to specify
1478 // completely opaque or completely transparent, respectively.
1479 void Magick::Image::alpha ( const unsigned int alpha_ )
1480 {
1481   modifyImage();
1482   ExceptionInfo exceptionInfo;
1483   GetExceptionInfo( &exceptionInfo );
1484   SetImageAlpha( image(), alpha_, &exceptionInfo );
1485   throwException( exceptionInfo );
1486   (void) DestroyExceptionInfo( &exceptionInfo );
1487 }
1488
1489 // Change the color of an opaque pixel to the pen color.
1490 void Magick::Image::opaque ( const Color &opaqueColor_,
1491                              const Color &penColor_ )
1492 {
1493   if ( !opaqueColor_.isValid() )
1494   {
1495     throwExceptionExplicit( OptionError,
1496                             "Opaque color argument is invalid" );
1497   }
1498   if ( !penColor_.isValid() )
1499   {
1500     throwExceptionExplicit( OptionError,
1501                             "Pen color argument is invalid" );
1502   }
1503
1504   modifyImage();
1505   std::string opaqueColor = opaqueColor_;
1506   std::string penColor = penColor_;
1507
1508   PixelInfo opaque;
1509   PixelInfo pen;
1510   ExceptionInfo exceptionInfo;
1511   GetExceptionInfo( &exceptionInfo );
1512   (void) QueryColorCompliance(std::string(opaqueColor_).c_str(),
1513     AllCompliance, &opaque, &exceptionInfo);
1514   (void) QueryColorCompliance(std::string(penColor_).c_str(),
1515     AllCompliance, &pen, &exceptionInfo);
1516   OpaquePaintImage ( image(), &opaque, &pen, MagickFalse, &exceptionInfo );
1517   throwException( exceptionInfo );
1518   (void) DestroyExceptionInfo( &exceptionInfo );
1519 }
1520
1521 // Ping is similar to read except only enough of the image is read to
1522 // determine the image columns, rows, and filesize.  Access the
1523 // columns(), rows(), and fileSize() attributes after invoking ping.
1524 // The image data is not valid after calling ping.
1525 void Magick::Image::ping ( const std::string &imageSpec_ )
1526 {
1527   options()->fileName( imageSpec_ );
1528   ExceptionInfo exceptionInfo;
1529   GetExceptionInfo( &exceptionInfo );
1530   MagickCore::Image* image =
1531     PingImage( imageInfo(), &exceptionInfo );
1532   replaceImage( image );
1533   throwException( exceptionInfo );
1534   (void) DestroyExceptionInfo( &exceptionInfo );
1535 }
1536
1537 // Ping is similar to read except only enough of the image is read
1538 // to determine the image columns, rows, and filesize.  Access the
1539 // columns(), rows(), and fileSize() attributes after invoking
1540 // ping.  The image data is not valid after calling ping.
1541 void Magick::Image::ping ( const Blob& blob_ )
1542 {
1543   ExceptionInfo exceptionInfo;
1544   GetExceptionInfo( &exceptionInfo );
1545   MagickCore::Image* image =
1546     PingBlob( imageInfo(), blob_.data(), blob_.length(), &exceptionInfo );
1547   replaceImage( image );
1548   throwException( exceptionInfo );
1549   (void) DestroyExceptionInfo( &exceptionInfo );
1550 }
1551
1552 // Execute a named process module using an argc/argv syntax similar to
1553 // that accepted by a C 'main' routine. An exception is thrown if the
1554 // requested process module doesn't exist, fails to load, or fails during
1555 // execution.
1556 void Magick::Image::process( std::string name_, const ssize_t argc, const char **argv )
1557 {
1558   modifyImage();
1559
1560   ExceptionInfo exceptionInfo;
1561   GetExceptionInfo( &exceptionInfo );
1562   size_t status = 
1563     InvokeDynamicImageFilter( name_.c_str(), &image(), argc, argv,
1564       &exceptionInfo );
1565   throwException( exceptionInfo );
1566   (void) DestroyExceptionInfo( &exceptionInfo );
1567 }
1568
1569 // Quantize colors in image using current quantization settings
1570 // Set measureError_ to true in order to measure quantization error
1571 void Magick::Image::quantize ( const bool measureError_  )
1572 {
1573   modifyImage();
1574  
1575   if (measureError_)
1576     options()->quantizeInfo()->measure_error=MagickTrue;
1577   else
1578     options()->quantizeInfo()->measure_error=MagickFalse;
1579
1580   ExceptionInfo exceptionInfo;
1581   GetExceptionInfo( &exceptionInfo );
1582   QuantizeImage( options()->quantizeInfo(), image(), &exceptionInfo );
1583
1584   throwException( exceptionInfo );
1585   (void) DestroyExceptionInfo( &exceptionInfo );
1586 }
1587
1588 // Apply an arithmetic or bitwise operator to the image pixel quantums.
1589 void Magick::Image::quantumOperator ( const ChannelType channel_,
1590                                       const MagickEvaluateOperator operator_,
1591                                       double rvalue_)
1592 {
1593   ExceptionInfo exceptionInfo;
1594   GetExceptionInfo( &exceptionInfo );
1595   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
1596   EvaluateImage( image(), operator_, rvalue_, &exceptionInfo);
1597   (void) SetPixelChannelMapMask( image(), channel_mask );
1598   throwException( exceptionInfo );
1599   (void) DestroyExceptionInfo( &exceptionInfo );
1600 }
1601
1602 void Magick::Image::quantumOperator ( const ssize_t x_,const ssize_t y_,
1603                                       const size_t columns_,
1604                                       const size_t rows_,
1605                                       const ChannelType channel_,
1606                                       const MagickEvaluateOperator operator_,
1607                                       const double rvalue_)
1608 {
1609   ExceptionInfo exceptionInfo;
1610   GetExceptionInfo( &exceptionInfo );
1611   RectangleInfo geometry;
1612   geometry.width = columns_;
1613   geometry.height = rows_;
1614   geometry.x = x_;
1615   geometry.y = y_;
1616   MagickCore::Image *crop_image = CropImage( image(), &geometry,
1617     &exceptionInfo );
1618   ChannelType channel_mask = SetPixelChannelMask( image(), channel_);
1619   EvaluateImage( crop_image, operator_, rvalue_, &exceptionInfo );
1620   (void) SetPixelChannelMapMask( image(), channel_mask );
1621   (void) CompositeImage( image(), image()->matte != MagickFalse ?
1622     OverCompositeOp : CopyCompositeOp, crop_image, geometry.x, geometry.y,
1623     &exceptionInfo );
1624   crop_image = DestroyImageList(crop_image);
1625   throwException( exceptionInfo );
1626   (void) DestroyExceptionInfo( &exceptionInfo );
1627 }
1628
1629 // Raise image (lighten or darken the edges of an image to give a 3-D
1630 // raised or lowered effect)
1631 void Magick::Image::raise ( const Geometry &geometry_ ,
1632                             const bool raisedFlag_ )
1633 {
1634   ExceptionInfo exceptionInfo;
1635   GetExceptionInfo( &exceptionInfo );
1636   RectangleInfo raiseInfo = geometry_;
1637   modifyImage();
1638   RaiseImage ( image(), &raiseInfo, raisedFlag_ == true ? MagickTrue : MagickFalse, &exceptionInfo );
1639   throwException( exceptionInfo );
1640   (void) DestroyExceptionInfo( &exceptionInfo );
1641 }
1642
1643
1644 // Random threshold image.
1645 //
1646 // Changes the value of individual pixels based on the intensity
1647 // of each pixel compared to a random threshold.  The result is a
1648 // low-contrast, two color image.  The thresholds_ argument is a
1649 // geometry containing LOWxHIGH thresholds.  If the string
1650 // contains 2x2, 3x3, or 4x4, then an ordered dither of order 2,
1651 // 3, or 4 will be performed instead.  If a channel_ argument is
1652 // specified then only the specified channel is altered.  This is
1653 // a very fast alternative to 'quantize' based dithering.
1654 void Magick::Image::randomThreshold( const Geometry &thresholds_ )
1655 {
1656   randomThresholdChannel(thresholds_,DefaultChannels);
1657 }
1658 void Magick::Image::randomThresholdChannel( const Geometry &thresholds_,
1659                                             const ChannelType channel_ )
1660 {
1661   ExceptionInfo exceptionInfo;
1662   GetExceptionInfo( &exceptionInfo );
1663   modifyImage();
1664   ChannelType channel_mask = SetPixelChannelMask( image(), channel_);
1665   (void) RandomThresholdImage( image(),
1666                                       static_cast<std::string>(thresholds_).c_str(),
1667                                       &exceptionInfo );
1668   (void) SetPixelChannelMapMask( image(), channel_mask );
1669   throwImageException();
1670   (void) DestroyExceptionInfo( &exceptionInfo );
1671 }
1672     
1673 // Read image into current object
1674 void Magick::Image::read ( const std::string &imageSpec_ )
1675 {
1676   options()->fileName( imageSpec_ );
1677
1678   ExceptionInfo exceptionInfo;
1679   GetExceptionInfo( &exceptionInfo );
1680   MagickCore::Image* image =
1681     ReadImage( imageInfo(), &exceptionInfo );
1682
1683   // Ensure that multiple image frames were not read.
1684   if ( image && image->next )
1685     {
1686       // Destroy any extra image frames
1687       MagickCore::Image* next = image->next;
1688       image->next = 0;
1689       next->previous = 0;
1690       DestroyImageList( next );
1691  
1692     }
1693   replaceImage( image );
1694   throwException( exceptionInfo );
1695   (void) DestroyExceptionInfo( &exceptionInfo );
1696 }
1697
1698 // Read image of specified size into current object
1699 void Magick::Image::read ( const Geometry &size_,
1700                            const std::string &imageSpec_ )
1701 {
1702   size( size_ );
1703   read( imageSpec_ );
1704 }
1705
1706 // Read image from in-memory BLOB
1707 void Magick::Image::read ( const Blob &blob_ )
1708 {
1709   ExceptionInfo exceptionInfo;
1710   GetExceptionInfo( &exceptionInfo );
1711   MagickCore::Image* image =
1712     BlobToImage( imageInfo(),
1713                  static_cast<const void *>(blob_.data()),
1714                  blob_.length(), &exceptionInfo );
1715   replaceImage( image );
1716   throwException( exceptionInfo );
1717   (void) DestroyExceptionInfo( &exceptionInfo );
1718 }
1719
1720 // Read image of specified size from in-memory BLOB
1721 void  Magick::Image::read ( const Blob &blob_,
1722                             const Geometry &size_ )
1723 {
1724   // Set image size
1725   size( size_ );
1726   // Read from Blob
1727   read( blob_ );
1728 }
1729
1730 // Read image of specified size and depth from in-memory BLOB
1731 void Magick::Image::read ( const Blob &blob_,
1732                            const Geometry &size_,
1733                            const size_t depth_ )
1734 {
1735   // Set image size
1736   size( size_ );
1737   // Set image depth
1738   depth( depth_ );
1739   // Read from Blob
1740   read( blob_ );
1741 }
1742
1743 // Read image of specified size, depth, and format from in-memory BLOB
1744 void Magick::Image::read ( const Blob &blob_,
1745                            const Geometry &size_,
1746                            const size_t depth_,
1747                            const std::string &magick_ )
1748 {
1749   // Set image size
1750   size( size_ );
1751   // Set image depth
1752   depth( depth_ );
1753   // Set image magick
1754   magick( magick_ );
1755   // Set explicit image format
1756   fileName( magick_ + ':');
1757   // Read from Blob
1758   read( blob_ );
1759 }
1760
1761 // Read image of specified size, and format from in-memory BLOB
1762 void Magick::Image::read ( const Blob &blob_,
1763                            const Geometry &size_,
1764                            const std::string &magick_ )
1765 {
1766   // Set image size
1767   size( size_ );
1768   // Set image magick
1769   magick( magick_ );
1770   // Set explicit image format
1771   fileName( magick_ + ':');
1772   // Read from Blob
1773   read( blob_ );
1774 }
1775
1776 // Read image based on raw pixels in memory (ConstituteImage)
1777 void Magick::Image::read ( const size_t width_,
1778                            const size_t height_,
1779                            const std::string &map_,
1780                            const StorageType type_,
1781                            const void *pixels_ )
1782 {
1783   ExceptionInfo exceptionInfo;
1784   GetExceptionInfo( &exceptionInfo );
1785   MagickCore::Image* image =
1786     ConstituteImage( width_, height_, map_.c_str(), type_, pixels_,
1787                      &exceptionInfo );
1788   replaceImage( image );
1789   throwException( exceptionInfo );
1790   (void) DestroyExceptionInfo( &exceptionInfo );
1791 }
1792
1793 // Reduce noise in image
1794 void Magick::Image::reduceNoise ( const double order_ )
1795 {
1796   ExceptionInfo exceptionInfo;
1797   GetExceptionInfo( &exceptionInfo );
1798   MagickCore::Image* newImage =
1799     StatisticImage( image(), NonpeakStatistic, (size_t) order_, (size_t) order_,
1800     &exceptionInfo );
1801   replaceImage( newImage );
1802   throwException( exceptionInfo );
1803   (void) DestroyExceptionInfo( &exceptionInfo );
1804 }
1805
1806 // Resize image
1807 void Magick::Image::resize( const Geometry &geometry_ )
1808 {
1809   // Calculate new size.  This code should be supported using binary arguments
1810   // in the ImageMagick library.
1811   ssize_t x = 0;
1812   ssize_t y = 0;
1813   size_t width = columns();
1814   size_t height = rows();
1815
1816   ParseMetaGeometry (static_cast<std::string>(geometry_).c_str(),
1817                      &x, &y,
1818                      &width, &height );
1819
1820   ExceptionInfo exceptionInfo;
1821   GetExceptionInfo( &exceptionInfo );
1822   MagickCore::Image* newImage =
1823     ResizeImage( image(),
1824                width,
1825                height,
1826                image()->filter,
1827                1.0,
1828                &exceptionInfo);
1829   replaceImage( newImage );
1830   throwException( exceptionInfo );
1831   (void) DestroyExceptionInfo( &exceptionInfo );
1832 }
1833
1834 // Roll image
1835 void Magick::Image::roll ( const Geometry &roll_ )
1836 {
1837   ssize_t xOff = roll_.xOff();
1838   if ( roll_.xNegative() )
1839     xOff = 0 - xOff;
1840   ssize_t yOff = roll_.yOff();
1841   if ( roll_.yNegative() )
1842     yOff = 0 - yOff;
1843
1844   ExceptionInfo exceptionInfo;
1845   GetExceptionInfo( &exceptionInfo );
1846   MagickCore::Image* newImage =
1847     RollImage( image(), xOff, yOff, &exceptionInfo );
1848   replaceImage( newImage );
1849   throwException( exceptionInfo );
1850   (void) DestroyExceptionInfo( &exceptionInfo );
1851 }
1852 void Magick::Image::roll ( const size_t columns_,
1853                            const size_t rows_ )
1854 {
1855   ExceptionInfo exceptionInfo;
1856   GetExceptionInfo( &exceptionInfo );
1857   MagickCore::Image* newImage =
1858     RollImage( image(),
1859                static_cast<ssize_t>(columns_),
1860                static_cast<ssize_t>(rows_), &exceptionInfo );
1861   replaceImage( newImage );
1862   throwException( exceptionInfo );
1863   (void) DestroyExceptionInfo( &exceptionInfo );
1864 }
1865
1866 // Rotate image
1867 void Magick::Image::rotate ( const double degrees_ )
1868 {
1869   ExceptionInfo exceptionInfo;
1870   GetExceptionInfo( &exceptionInfo );
1871   MagickCore::Image* newImage =
1872     RotateImage( image(), degrees_, &exceptionInfo);
1873   replaceImage( newImage );
1874   throwException( exceptionInfo );
1875   (void) DestroyExceptionInfo( &exceptionInfo );
1876 }
1877
1878 // Sample image
1879 void Magick::Image::sample ( const Geometry &geometry_ )
1880 {
1881   ssize_t x = 0;
1882   ssize_t y = 0;
1883   size_t width = columns();
1884   size_t height = rows();
1885
1886   ParseMetaGeometry (static_cast<std::string>(geometry_).c_str(),
1887                       &x, &y,
1888                       &width, &height );
1889
1890   ExceptionInfo exceptionInfo;
1891   GetExceptionInfo( &exceptionInfo );
1892   MagickCore::Image* newImage =
1893     SampleImage( image(), width, height, &exceptionInfo );
1894   replaceImage( newImage );
1895   throwException( exceptionInfo );
1896   (void) DestroyExceptionInfo( &exceptionInfo );
1897 }
1898
1899 // Scale image
1900 void Magick::Image::scale ( const Geometry &geometry_ )
1901 {
1902   ssize_t x = 0;
1903   ssize_t y = 0;
1904   size_t width = columns();
1905   size_t height = rows();
1906
1907   ParseMetaGeometry (static_cast<std::string>(geometry_).c_str(),
1908                       &x, &y,
1909                       &width, &height );
1910
1911   ExceptionInfo exceptionInfo;
1912   GetExceptionInfo( &exceptionInfo );
1913   MagickCore::Image* newImage =
1914     ScaleImage( image(), width, height, &exceptionInfo );
1915   replaceImage( newImage );
1916   throwException( exceptionInfo );
1917   (void) DestroyExceptionInfo( &exceptionInfo );
1918 }
1919
1920 // Segment (coalesce similar image components) by analyzing the
1921 // histograms of the color components and identifying units that are
1922 // homogeneous with the fuzzy c-means technique.
1923 void Magick::Image::segment ( const double clusterThreshold_, 
1924                               const double smoothingThreshold_ )
1925 {
1926   ExceptionInfo exceptionInfo;
1927   GetExceptionInfo( &exceptionInfo );
1928   modifyImage();
1929   SegmentImage ( image(),
1930                  options()->quantizeColorSpace(),
1931                  (MagickBooleanType) options()->verbose(),
1932                  clusterThreshold_,
1933                  smoothingThreshold_, &exceptionInfo );
1934   SyncImage( image(), &exceptionInfo );
1935   throwException( exceptionInfo );
1936   (void) DestroyExceptionInfo( &exceptionInfo );
1937 }
1938
1939 // Shade image using distant light source
1940 void Magick::Image::shade ( const double azimuth_,
1941                             const double elevation_,
1942                             const bool   colorShading_ )
1943 {
1944   ExceptionInfo exceptionInfo;
1945   GetExceptionInfo( &exceptionInfo );
1946   MagickCore::Image* newImage =
1947     ShadeImage( image(),
1948                 colorShading_ == true ? MagickTrue : MagickFalse,
1949                 azimuth_,
1950                 elevation_,
1951                 &exceptionInfo);
1952   replaceImage( newImage );
1953   throwException( exceptionInfo );
1954   (void) DestroyExceptionInfo( &exceptionInfo );
1955 }
1956
1957 // Simulate an image shadow
1958 void Magick::Image::shadow( const double percent_opacity_, const double sigma_,
1959   const ssize_t x_, const ssize_t y_ )
1960 {
1961   ExceptionInfo exceptionInfo;
1962   GetExceptionInfo( &exceptionInfo );
1963   MagickCore::Image* newImage = ShadowImage( image(), percent_opacity_, sigma_,
1964     image()->bias, x_, y_, &exceptionInfo );
1965   replaceImage( newImage );
1966   throwException( exceptionInfo );
1967   (void) DestroyExceptionInfo( &exceptionInfo );
1968 }
1969
1970 // Sharpen pixels in image
1971 void Magick::Image::sharpen ( const double radius_, const double sigma_ )
1972 {
1973   ExceptionInfo exceptionInfo;
1974   GetExceptionInfo( &exceptionInfo );
1975   MagickCore::Image* newImage =
1976     SharpenImage( image(),
1977                   radius_,
1978                   sigma_,
1979                   image()->bias,
1980                   &exceptionInfo );
1981   replaceImage( newImage );
1982   throwException( exceptionInfo );
1983   (void) DestroyExceptionInfo( &exceptionInfo );
1984 }
1985
1986 void Magick::Image::sharpenChannel ( const ChannelType channel_,
1987                                      const double radius_, const double sigma_ )
1988 {
1989   ExceptionInfo exceptionInfo;
1990   GetExceptionInfo( &exceptionInfo );
1991   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
1992   MagickCore::Image* newImage =
1993     SharpenImage( image(),
1994                          radius_,
1995                          sigma_,
1996                   image()->bias,
1997                          &exceptionInfo );
1998   (void) SetPixelChannelMapMask( image(), channel_mask );
1999   replaceImage( newImage );
2000   throwException( exceptionInfo );
2001   (void) DestroyExceptionInfo( &exceptionInfo );
2002 }
2003
2004 // Shave pixels from image edges.
2005 void Magick::Image::shave ( const Geometry &geometry_ )
2006 {
2007   RectangleInfo shaveInfo = geometry_;
2008   ExceptionInfo exceptionInfo;
2009   GetExceptionInfo( &exceptionInfo );
2010   MagickCore::Image* newImage =
2011     ShaveImage( image(),
2012                &shaveInfo,
2013                &exceptionInfo);
2014   replaceImage( newImage );
2015   throwException( exceptionInfo );
2016   (void) DestroyExceptionInfo( &exceptionInfo );
2017 }
2018
2019 // Shear image
2020 void Magick::Image::shear ( const double xShearAngle_,
2021                             const double yShearAngle_ )
2022 {
2023   ExceptionInfo exceptionInfo;
2024   GetExceptionInfo( &exceptionInfo );
2025   MagickCore::Image* newImage =
2026     ShearImage( image(),
2027                 xShearAngle_,
2028                 yShearAngle_,
2029                 &exceptionInfo );
2030   replaceImage( newImage );
2031   throwException( exceptionInfo );
2032   (void) DestroyExceptionInfo( &exceptionInfo );
2033 }
2034
2035 // Contrast image
2036 void Magick::Image::sigmoidalContrast ( const size_t sharpen_, const double contrast, const double midpoint )
2037 {
2038   ExceptionInfo exceptionInfo;
2039   GetExceptionInfo( &exceptionInfo );
2040   modifyImage();
2041   (void) SigmoidalContrastImage( image(), (MagickBooleanType) sharpen_, contrast, midpoint, &exceptionInfo );
2042   throwException( exceptionInfo );
2043   (void) DestroyExceptionInfo( &exceptionInfo );
2044 }
2045
2046 // Solarize image (similar to effect seen when exposing a photographic
2047 // film to light during the development process)
2048 void Magick::Image::solarize ( const double factor_ )
2049 {
2050   ExceptionInfo exceptionInfo;
2051   GetExceptionInfo( &exceptionInfo );
2052   modifyImage();
2053   SolarizeImage ( image(), factor_, &exceptionInfo );
2054   throwException( exceptionInfo );
2055   (void) DestroyExceptionInfo( &exceptionInfo );
2056 }
2057
2058 // Sparse color image, given a set of coordinates, interpolates the colors
2059 // found at those coordinates, across the whole image, using various methods.
2060 //
2061 void Magick::Image::sparseColor ( const ChannelType channel,
2062                                   const SparseColorMethod method,
2063                                   const size_t number_arguments,
2064                                   const double *arguments )
2065 {
2066   ExceptionInfo exceptionInfo;
2067   GetExceptionInfo( &exceptionInfo );
2068
2069   ChannelType channel_mask = SetPixelChannelMask( image(), channel );
2070   MagickCore::Image* newImage = SparseColorImage ( image(), method,
2071     number_arguments, arguments, &exceptionInfo );
2072   (void) SetPixelChannelMapMask( image(), channel_mask );
2073   replaceImage( newImage );
2074   throwException( exceptionInfo );
2075   (void) DestroyExceptionInfo( &exceptionInfo );
2076 }
2077
2078 // Spread pixels randomly within image by specified ammount
2079 void Magick::Image::spread ( const size_t amount_ )
2080 {
2081   ExceptionInfo exceptionInfo;
2082   GetExceptionInfo( &exceptionInfo );
2083   MagickCore::Image* newImage =
2084     SpreadImage( image(),
2085                  amount_,
2086                  image()->interpolate,
2087                  &exceptionInfo );
2088   replaceImage( newImage );
2089   throwException( exceptionInfo );
2090   (void) DestroyExceptionInfo( &exceptionInfo );
2091 }
2092
2093 // Add a digital watermark to the image (based on second image)
2094 void Magick::Image::stegano ( const Image &watermark_ )
2095 {
2096   ExceptionInfo exceptionInfo;
2097   GetExceptionInfo( &exceptionInfo );
2098   MagickCore::Image* newImage =
2099     SteganoImage( image(),
2100                   watermark_.constImage(),
2101                   &exceptionInfo);
2102   replaceImage( newImage );
2103   throwException( exceptionInfo );
2104   (void) DestroyExceptionInfo( &exceptionInfo );
2105 }
2106
2107 // Stereo image (left image is current image)
2108 void Magick::Image::stereo ( const Image &rightImage_ )
2109 {
2110   ExceptionInfo exceptionInfo;
2111   GetExceptionInfo( &exceptionInfo );
2112   MagickCore::Image* newImage =
2113     StereoImage( image(),
2114                  rightImage_.constImage(),
2115                  &exceptionInfo);
2116   replaceImage( newImage );
2117   throwException( exceptionInfo );
2118   (void) DestroyExceptionInfo( &exceptionInfo );
2119 }
2120
2121 // Swirl image
2122 void Magick::Image::swirl ( const double degrees_ )
2123 {
2124   ExceptionInfo exceptionInfo;
2125   GetExceptionInfo( &exceptionInfo );
2126   MagickCore::Image* newImage =
2127     SwirlImage( image(), degrees_, image()->interpolate,
2128                 &exceptionInfo);
2129   replaceImage( newImage );
2130   throwException( exceptionInfo );
2131   (void) DestroyExceptionInfo( &exceptionInfo );
2132 }
2133
2134 // Texture image
2135 void Magick::Image::texture ( const Image &texture_ )
2136 {
2137   modifyImage();
2138   ExceptionInfo exceptionInfo;
2139   GetExceptionInfo( &exceptionInfo );
2140   TextureImage( image(), texture_.constImage(), &exceptionInfo );
2141   throwException( exceptionInfo );
2142   (void) DestroyExceptionInfo( &exceptionInfo );
2143 }
2144
2145 // Threshold image
2146 void Magick::Image::threshold ( const double threshold_ )
2147 {
2148   modifyImage();
2149   ExceptionInfo exceptionInfo;
2150   GetExceptionInfo( &exceptionInfo );
2151   BilevelImage( image(), threshold_, &exceptionInfo );
2152   throwException( exceptionInfo );
2153   (void) DestroyExceptionInfo( &exceptionInfo );
2154 }
2155
2156 // Transform image based on image geometry only
2157 void Magick::Image::transform ( const Geometry &imageGeometry_ )
2158 {
2159   modifyImage();
2160   ExceptionInfo exceptionInfo;
2161   GetExceptionInfo( &exceptionInfo );
2162   TransformImage ( &(image()), 0,
2163                    std::string(imageGeometry_).c_str(), &exceptionInfo );
2164   throwException( exceptionInfo );
2165   (void) DestroyExceptionInfo( &exceptionInfo );
2166 }
2167 // Transform image based on image and crop geometries
2168 void Magick::Image::transform ( const Geometry &imageGeometry_,
2169                                 const Geometry &cropGeometry_ )
2170 {
2171   modifyImage();
2172   ExceptionInfo exceptionInfo;
2173   GetExceptionInfo( &exceptionInfo );
2174   TransformImage ( &(image()), std::string(cropGeometry_).c_str(),
2175                    std::string(imageGeometry_).c_str(), &exceptionInfo );
2176   throwException( exceptionInfo );
2177   (void) DestroyExceptionInfo( &exceptionInfo );
2178 }
2179
2180 // Add matte image to image, setting pixels matching color to transparent
2181 void Magick::Image::transparent ( const Color &color_ )
2182 {
2183   if ( !color_.isValid() )
2184   {
2185     throwExceptionExplicit( OptionError,
2186                             "Color argument is invalid" );
2187   }
2188
2189   std::string color = color_;
2190
2191   PixelInfo target;
2192   ExceptionInfo exceptionInfo;
2193   GetExceptionInfo( &exceptionInfo );
2194   (void) QueryColorCompliance(std::string(color_).c_str(),AllCompliance,
2195     &target,&exceptionInfo);
2196   modifyImage();
2197   TransparentPaintImage ( image(), &target, TransparentAlpha, MagickFalse,
2198     &exceptionInfo );
2199   throwException( exceptionInfo );
2200   (void) DestroyExceptionInfo( &exceptionInfo );
2201 }
2202
2203 // Add matte image to image, setting pixels matching color to transparent
2204 void Magick::Image::transparentChroma(const Color &colorLow_,
2205   const Color &colorHigh_)
2206 {
2207   if ( !colorLow_.isValid() || !colorHigh_.isValid() )
2208   {
2209     throwExceptionExplicit( OptionError,
2210                             "Color argument is invalid" );
2211   }
2212
2213   std::string colorLow = colorLow_;
2214   std::string colorHigh = colorHigh_;
2215
2216   PixelInfo targetLow;
2217   PixelInfo targetHigh;
2218   ExceptionInfo exceptionInfo;
2219   GetExceptionInfo( &exceptionInfo );
2220   (void) QueryColorCompliance(std::string(colorLow_).c_str(),
2221     AllCompliance,&targetLow,&exceptionInfo);
2222   (void) QueryColorCompliance(std::string(colorHigh_).c_str(),
2223     AllCompliance,&targetHigh,&exceptionInfo);
2224   modifyImage();
2225   TransparentPaintImageChroma ( image(), &targetLow, &targetHigh,
2226     TransparentAlpha, MagickFalse, &exceptionInfo );
2227   throwException( exceptionInfo );
2228   (void) DestroyExceptionInfo( &exceptionInfo );
2229 }
2230
2231
2232 // Trim edges that are the background color from the image
2233 void Magick::Image::trim ( void )
2234 {
2235   ExceptionInfo exceptionInfo;
2236   GetExceptionInfo( &exceptionInfo );
2237   MagickCore::Image* newImage =
2238     TrimImage( image(), &exceptionInfo);
2239   replaceImage( newImage );
2240   throwException( exceptionInfo );
2241   (void) DestroyExceptionInfo( &exceptionInfo );
2242 }
2243
2244 // Replace image with a sharpened version of the original image
2245 // using the unsharp mask algorithm.
2246 //  radius_
2247 //    the radius of the Gaussian, in pixels, not counting the
2248 //    center pixel.
2249 //  sigma_
2250 //    the standard deviation of the Gaussian, in pixels.
2251 //  amount_
2252 //    the percentage of the difference between the original and
2253 //    the blur image that is added back into the original.
2254 // threshold_
2255 //   the threshold in pixels needed to apply the diffence amount.
2256 void Magick::Image::unsharpmask ( const double radius_,
2257                                   const double sigma_,
2258                                   const double amount_,
2259                                   const double threshold_ )
2260 {
2261   ExceptionInfo exceptionInfo;
2262   GetExceptionInfo( &exceptionInfo );
2263   MagickCore::Image* newImage =
2264     UnsharpMaskImage( image(),
2265                       radius_,
2266                       sigma_,
2267                       amount_,
2268                       threshold_,
2269                       &exceptionInfo );
2270   replaceImage( newImage );
2271   throwException( exceptionInfo );
2272   (void) DestroyExceptionInfo( &exceptionInfo );
2273 }
2274
2275 void Magick::Image::unsharpmaskChannel ( const ChannelType channel_,
2276                                          const double radius_,
2277                                          const double sigma_,
2278                                          const double amount_,
2279                                          const double threshold_ )
2280 {
2281   ExceptionInfo exceptionInfo;
2282   GetExceptionInfo( &exceptionInfo );
2283   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
2284   MagickCore::Image* newImage =
2285     UnsharpMaskImage( image(),
2286                              radius_,
2287                              sigma_,
2288                              amount_,
2289                              threshold_,
2290                              &exceptionInfo );
2291   (void) SetPixelChannelMapMask( image(), channel_mask );
2292   replaceImage( newImage );
2293   throwException( exceptionInfo );
2294   (void) DestroyExceptionInfo( &exceptionInfo );
2295 }
2296
2297 // Map image pixels to a sine wave
2298 void Magick::Image::wave ( const double amplitude_, const double wavelength_ )
2299 {
2300   ExceptionInfo exceptionInfo;
2301   GetExceptionInfo( &exceptionInfo );
2302   MagickCore::Image* newImage =
2303     WaveImage( image(),
2304                amplitude_,
2305                wavelength_,
2306                image()->interpolate,
2307                &exceptionInfo);
2308   replaceImage( newImage );
2309   throwException( exceptionInfo );
2310   (void) DestroyExceptionInfo( &exceptionInfo );
2311 }
2312
2313 // Write image to file
2314 void Magick::Image::write( const std::string &imageSpec_ )
2315 {
2316   ExceptionInfo exceptionInfo;
2317   GetExceptionInfo( &exceptionInfo );
2318   modifyImage();
2319   fileName( imageSpec_ );
2320   WriteImage( imageInfo(), image(), &exceptionInfo );
2321   throwException( exceptionInfo );
2322   (void) DestroyExceptionInfo( &exceptionInfo );
2323 }
2324
2325 // Write image to in-memory BLOB
2326 void Magick::Image::write ( Blob *blob_ )
2327 {
2328   modifyImage();
2329   size_t length = 2048; // Efficient size for small images
2330   ExceptionInfo exceptionInfo;
2331   GetExceptionInfo( &exceptionInfo );
2332   void* data = ImageToBlob( imageInfo(),
2333                             image(),
2334                             &length,
2335                             &exceptionInfo);
2336   throwException( exceptionInfo );
2337   blob_->updateNoCopy( data, length, Blob::MallocAllocator );
2338   throwImageException();
2339   (void) DestroyExceptionInfo( &exceptionInfo );
2340 }
2341 void Magick::Image::write ( Blob *blob_,
2342                             const std::string &magick_ )
2343 {
2344   modifyImage();
2345   magick(magick_);
2346   size_t length = 2048; // Efficient size for small images
2347   ExceptionInfo exceptionInfo;
2348   GetExceptionInfo( &exceptionInfo );
2349   void* data = ImageToBlob( imageInfo(),
2350                             image(),
2351                             &length,
2352                             &exceptionInfo);
2353   throwException( exceptionInfo );
2354   blob_->updateNoCopy( data, length, Blob::MallocAllocator );
2355   throwImageException();
2356   (void) DestroyExceptionInfo( &exceptionInfo );
2357 }
2358 void Magick::Image::write ( Blob *blob_,
2359                             const std::string &magick_,
2360                             const size_t depth_ )
2361 {
2362   modifyImage();
2363   magick(magick_);
2364   depth(depth_);
2365   size_t length = 2048; // Efficient size for small images
2366   ExceptionInfo exceptionInfo;
2367   GetExceptionInfo( &exceptionInfo );
2368   void* data = ImageToBlob( imageInfo(),
2369                             image(),
2370                             &length,
2371                             &exceptionInfo);
2372   throwException( exceptionInfo );
2373   blob_->updateNoCopy( data, length, Blob::MallocAllocator );
2374   throwImageException();
2375   (void) DestroyExceptionInfo( &exceptionInfo );
2376 }
2377
2378 // Write image to an array of pixels with storage type specified
2379 // by user (ExportImagePixels), e.g.
2380 // image.write( 0, 0, 640, 1, "RGB", 0, pixels );
2381 void Magick::Image::write ( const ssize_t x_,
2382                             const ssize_t y_,
2383                             const size_t columns_,
2384                             const size_t rows_,
2385                             const std::string &map_,
2386                             const StorageType type_,
2387                             void *pixels_ )
2388 {
2389   ExceptionInfo exceptionInfo;
2390   GetExceptionInfo( &exceptionInfo );
2391   ExportImagePixels( image(), x_, y_, columns_, rows_, map_.c_str(), type_,
2392                  pixels_,
2393     &exceptionInfo);
2394   throwException( exceptionInfo );
2395   (void) DestroyExceptionInfo( &exceptionInfo );
2396 }
2397
2398 // Zoom image
2399 void Magick::Image::zoom( const Geometry &geometry_ )
2400 {
2401   // Calculate new size.  This code should be supported using binary arguments
2402   // in the ImageMagick library.
2403   ssize_t x = 0;
2404   ssize_t y = 0;
2405   size_t width = columns();
2406   size_t height = rows();
2407
2408   ParseMetaGeometry (static_cast<std::string>(geometry_).c_str(),
2409                      &x, &y,
2410                      &width, &height );
2411
2412   ExceptionInfo exceptionInfo;
2413   GetExceptionInfo( &exceptionInfo );
2414   MagickCore::Image* newImage =
2415     ResizeImage( image(),
2416                width,
2417                height,
2418                image()->filter,
2419                image()->blur,
2420                &exceptionInfo);
2421   replaceImage( newImage );
2422   throwException( exceptionInfo );
2423   (void) DestroyExceptionInfo( &exceptionInfo );
2424 }
2425
2426 /*
2427  * Methods for setting image attributes
2428  *
2429  */
2430
2431 // Join images into a single multi-image file
2432 void Magick::Image::adjoin ( const bool flag_ )
2433 {
2434   modifyImage();
2435   options()->adjoin( flag_ );
2436 }
2437 bool Magick::Image::adjoin ( void ) const
2438 {
2439   return constOptions()->adjoin();
2440 }
2441
2442 // Remove pixel aliasing
2443 void Magick::Image::antiAlias( const bool flag_ )
2444 {
2445   modifyImage();
2446   options()->antiAlias( static_cast<size_t>(flag_) );
2447 }
2448 bool Magick::Image::antiAlias( void )
2449 {
2450   return static_cast<bool>( options()->antiAlias( ) );
2451 }
2452
2453 // Animation inter-frame delay
2454 void Magick::Image::animationDelay ( const size_t delay_ )
2455 {
2456   modifyImage();
2457   image()->delay = delay_;
2458 }
2459 size_t Magick::Image::animationDelay ( void ) const
2460 {
2461   return constImage()->delay;
2462 }
2463
2464 // Number of iterations to play animation
2465 void Magick::Image::animationIterations ( const size_t iterations_ )
2466 {
2467   modifyImage();
2468   image()->iterations = iterations_;
2469 }
2470 size_t Magick::Image::animationIterations ( void ) const
2471 {
2472   return constImage()->iterations;
2473 }
2474
2475 // Access/Update a named image attribute
2476 void Magick::Image::attribute ( const std::string name_,
2477                                 const std::string value_ )
2478 {
2479   modifyImage();
2480   ExceptionInfo exceptionInfo;
2481   GetExceptionInfo( &exceptionInfo );
2482   SetImageProperty( image(), name_.c_str(), value_.c_str(), &exceptionInfo );
2483   throwException( exceptionInfo );
2484   (void) DestroyExceptionInfo( &exceptionInfo );
2485 }
2486 std::string Magick::Image::attribute ( const std::string name_ )
2487 {
2488   ExceptionInfo exceptionInfo;
2489   GetExceptionInfo( &exceptionInfo );
2490   const char *value = GetImageProperty( constImage(), name_.c_str(),
2491     &exceptionInfo );
2492   throwException( exceptionInfo );
2493   (void) DestroyExceptionInfo( &exceptionInfo );
2494
2495   if ( value )
2496     return std::string( value );
2497
2498   return std::string(); // Intentionally no exception
2499 }
2500
2501 // Background color
2502 void Magick::Image::backgroundColor ( const Color &backgroundColor_ )
2503 {
2504   modifyImage();
2505
2506   if ( backgroundColor_.isValid() )
2507     {
2508       image()->background_color = backgroundColor_;
2509     }
2510   else
2511     {
2512       image()->background_color = Color();
2513     }
2514
2515   options()->backgroundColor( backgroundColor_ );
2516 }
2517 Magick::Color Magick::Image::backgroundColor ( void ) const
2518 {
2519   return constOptions()->backgroundColor( );
2520 }
2521
2522 // Background fill texture
2523 void Magick::Image::backgroundTexture ( const std::string &backgroundTexture_ )
2524 {
2525   modifyImage();
2526   options()->backgroundTexture( backgroundTexture_ );
2527 }
2528 std::string Magick::Image::backgroundTexture ( void ) const
2529 {
2530   return constOptions()->backgroundTexture( );
2531 }
2532
2533 // Original image columns
2534 size_t Magick::Image::baseColumns ( void ) const
2535 {
2536   return constImage()->magick_columns;
2537 }
2538
2539 // Original image name
2540 std::string Magick::Image::baseFilename ( void ) const
2541 {
2542   return std::string(constImage()->magick_filename);
2543 }
2544
2545 // Original image rows
2546 size_t Magick::Image::baseRows ( void ) const
2547 {
2548   return constImage()->magick_rows;
2549 }
2550
2551 // Border color
2552 void Magick::Image::borderColor ( const Color &borderColor_ )
2553 {
2554   modifyImage();
2555
2556   if ( borderColor_.isValid() )
2557     {
2558       image()->border_color = borderColor_;
2559     }
2560   else
2561     {
2562       image()->border_color = Color();
2563     }
2564
2565   options()->borderColor( borderColor_ );
2566 }
2567 Magick::Color Magick::Image::borderColor ( void ) const
2568 {
2569   return constOptions()->borderColor( );
2570 }
2571
2572 // Return smallest bounding box enclosing non-border pixels. The
2573 // current fuzz value is used when discriminating between pixels.
2574 // This is the crop bounding box used by crop(Geometry(0,0));
2575 Magick::Geometry Magick::Image::boundingBox ( void ) const
2576 {
2577   ExceptionInfo exceptionInfo;
2578   GetExceptionInfo( &exceptionInfo );
2579   RectangleInfo bbox = GetImageBoundingBox( constImage(), &exceptionInfo);
2580   throwException( exceptionInfo );
2581   (void) DestroyExceptionInfo( &exceptionInfo );
2582   return Geometry( bbox );
2583 }
2584
2585 // Text bounding-box base color
2586 void Magick::Image::boxColor ( const Color &boxColor_ )
2587 {
2588   modifyImage();
2589   options()->boxColor( boxColor_ );
2590 }
2591 Magick::Color Magick::Image::boxColor ( void ) const
2592 {
2593   return constOptions()->boxColor( );
2594 }
2595
2596 // Pixel cache threshold.  Once this threshold is exceeded, all
2597 // subsequent pixels cache operations are to/from disk.
2598 // This setting is shared by all Image objects.
2599 /* static */
2600 void Magick::Image::cacheThreshold ( const size_t threshold_ )
2601 {
2602   SetMagickResourceLimit( MemoryResource, threshold_ );
2603 }
2604
2605 void Magick::Image::chromaBluePrimary ( const double x_, const double y_ )
2606 {
2607   modifyImage();
2608   image()->chromaticity.blue_primary.x = x_;
2609   image()->chromaticity.blue_primary.y = y_;
2610 }
2611 void Magick::Image::chromaBluePrimary ( double *x_, double *y_ ) const
2612 {
2613   *x_ = constImage()->chromaticity.blue_primary.x;
2614   *y_ = constImage()->chromaticity.blue_primary.y;
2615 }
2616
2617 void Magick::Image::chromaGreenPrimary ( const double x_, const double y_ )
2618 {
2619   modifyImage();
2620   image()->chromaticity.green_primary.x = x_;
2621   image()->chromaticity.green_primary.y = y_;
2622 }
2623 void Magick::Image::chromaGreenPrimary ( double *x_, double *y_ ) const
2624 {
2625   *x_ = constImage()->chromaticity.green_primary.x;
2626   *y_ = constImage()->chromaticity.green_primary.y;
2627 }
2628
2629 void Magick::Image::chromaRedPrimary ( const double x_, const double y_ )
2630 {
2631   modifyImage();
2632   image()->chromaticity.red_primary.x = x_;
2633   image()->chromaticity.red_primary.y = y_;
2634 }
2635 void Magick::Image::chromaRedPrimary ( double *x_, double *y_ ) const
2636 {
2637   *x_ = constImage()->chromaticity.red_primary.x;
2638   *y_ = constImage()->chromaticity.red_primary.y;
2639 }
2640
2641 void Magick::Image::chromaWhitePoint ( const double x_, const double y_ )
2642 {
2643   modifyImage();
2644   image()->chromaticity.white_point.x = x_;
2645   image()->chromaticity.white_point.y = y_;
2646 }
2647 void Magick::Image::chromaWhitePoint ( double *x_, double *y_ ) const
2648 {
2649   *x_ = constImage()->chromaticity.white_point.x;
2650   *y_ = constImage()->chromaticity.white_point.y;
2651 }
2652
2653 // Set image storage class
2654 void Magick::Image::classType ( const ClassType class_ )
2655 {
2656   if ( classType() == PseudoClass && class_ == DirectClass )
2657     {
2658       // Use SyncImage to synchronize the DirectClass pixels with the
2659       // color map and then set to DirectClass type.
2660       modifyImage();
2661       ExceptionInfo exceptionInfo;
2662       GetExceptionInfo( &exceptionInfo );
2663       SyncImage( image(), &exceptionInfo );
2664       throwException( exceptionInfo );
2665       (void) DestroyExceptionInfo( &exceptionInfo );
2666       image()->colormap = (PixelInfo *)
2667         RelinquishMagickMemory( image()->colormap );
2668       image()->storage_class = static_cast<MagickCore::ClassType>(DirectClass);
2669       return;
2670     }
2671
2672   if ( classType() == DirectClass && class_ == PseudoClass )
2673     {
2674       // Quantize to create PseudoClass color map
2675       modifyImage();
2676       quantizeColors(MaxColormapSize);
2677       quantize();
2678       image()->storage_class = static_cast<MagickCore::ClassType>(PseudoClass);
2679     }
2680 }
2681
2682 // Associate a clip mask with the image. The clip mask must be the
2683 // same dimensions as the image. Pass an invalid image to unset an
2684 // existing clip mask.
2685 void Magick::Image::clipMask ( const Magick::Image & clipMask_ )
2686 {
2687   modifyImage();
2688
2689   ExceptionInfo exceptionInfo;
2690   GetExceptionInfo( &exceptionInfo );
2691   if( clipMask_.isValid() )
2692     {
2693       // Set clip mask
2694       SetImageMask( image(), clipMask_.constImage(), &exceptionInfo );
2695     }
2696   else
2697     {
2698       // Unset existing clip mask
2699       SetImageMask( image(), 0, &exceptionInfo );
2700     }
2701    throwException( exceptionInfo );
2702    (void) DestroyExceptionInfo( &exceptionInfo );
2703 }
2704 Magick::Image Magick::Image::clipMask ( void  ) const
2705 {
2706    ExceptionInfo exceptionInfo;
2707    GetExceptionInfo( &exceptionInfo );
2708    MagickCore::Image* image = GetImageMask( constImage(), &exceptionInfo );
2709    throwException( exceptionInfo );
2710    (void) DestroyExceptionInfo( &exceptionInfo );
2711    return Magick::Image( image );
2712 }
2713
2714 void Magick::Image::colorFuzz ( const double fuzz_ )
2715 {
2716   modifyImage();
2717   image()->fuzz = fuzz_;
2718   options()->colorFuzz( fuzz_ );
2719 }
2720 double Magick::Image::colorFuzz ( void ) const
2721 {
2722   return constOptions()->colorFuzz( );
2723 }
2724
2725 // Set color in colormap at index
2726 void Magick::Image::colorMap ( const size_t index_,
2727                                const Color &color_ )
2728 {
2729   MagickCore::Image* imageptr = image();
2730
2731   if (index_ > (MaxColormapSize-1) )
2732     throwExceptionExplicit( OptionError,
2733                             "Colormap index must be less than MaxColormapSize" );
2734   
2735   if ( !color_.isValid() )
2736     throwExceptionExplicit( OptionError,
2737                             "Color argument is invalid");
2738   modifyImage();
2739
2740   // Ensure that colormap size is large enough
2741   if ( colorMapSize() < (index_+1) )
2742     colorMapSize( index_ + 1 );
2743
2744   // Set color at index in colormap
2745   (imageptr->colormap)[index_] = color_;
2746 }
2747 // Return color in colormap at index
2748 Magick::Color Magick::Image::colorMap ( const size_t index_ ) const
2749 {
2750   const MagickCore::Image* imageptr = constImage();
2751
2752   if ( !imageptr->colormap )
2753     throwExceptionExplicit( OptionError,
2754                             "Image does not contain a colormap");
2755
2756   if ( index_ > imageptr->colors-1 )
2757     throwExceptionExplicit( OptionError,
2758                             "Index out of range");
2759
2760   return Magick::Color( (imageptr->colormap)[index_] );
2761 }
2762
2763 // Colormap size (number of colormap entries)
2764 void Magick::Image::colorMapSize ( const size_t entries_ )
2765 {
2766   if (entries_ >MaxColormapSize )
2767     throwExceptionExplicit( OptionError,
2768                             "Colormap entries must not exceed MaxColormapSize" );
2769
2770   modifyImage();
2771
2772   MagickCore::Image* imageptr = image();
2773
2774   if( !imageptr->colormap )
2775     {
2776       // Allocate colormap
2777       imageptr->colormap =
2778         static_cast<PixelInfo*>(AcquireMagickMemory(entries_*sizeof(PixelInfo)));
2779       imageptr->colors = 0;
2780     }
2781   else if ( entries_ > imageptr->colors )
2782     {
2783       // Re-allocate colormap
2784       imageptr->colormap=(PixelInfo *)
2785         ResizeMagickMemory(imageptr->colormap,(entries_)*sizeof(PixelInfo));
2786     }
2787
2788   // Initialize any new colormap entries as all black
2789   Color black(0,0,0);
2790   for( size_t i=imageptr->colors; i<(entries_-1); i++ )
2791     (imageptr->colormap)[i] = black;
2792
2793   imageptr->colors = entries_;
2794 }
2795 size_t Magick::Image::colorMapSize ( void )
2796 {
2797   const MagickCore::Image* imageptr = constImage();
2798
2799   if ( !imageptr->colormap )
2800     throwExceptionExplicit( OptionError,
2801                             "Image does not contain a colormap");
2802
2803   return imageptr->colors;
2804 }
2805
2806 // Image colorspace
2807 void Magick::Image::colorSpace( const ColorspaceType colorSpace_ )
2808 {
2809   // Nothing to do?
2810   if ( image()->colorspace == colorSpace_ )
2811     return;
2812
2813   modifyImage();
2814
2815   ExceptionInfo exceptionInfo;
2816   GetExceptionInfo( &exceptionInfo );
2817   if ( colorSpace_ != RGBColorspace &&
2818        colorSpace_ != sRGBColorspace &&
2819        colorSpace_ != TransparentColorspace &&
2820        colorSpace_ != GRAYColorspace )
2821     {
2822       if (image()->colorspace != RGBColorspace &&
2823           image()->colorspace != sRGBColorspace &&
2824           image()->colorspace != TransparentColorspace &&
2825           image()->colorspace != GRAYColorspace)
2826         {
2827           /* Transform to RGB colorspace as intermediate step */
2828           TransformRGBImage( image(), image()->colorspace, &exceptionInfo );
2829           throwImageException();
2830         }
2831       /* Transform to final non-RGB colorspace */
2832       RGBTransformImage( image(), colorSpace_, &exceptionInfo );
2833       throwException( exceptionInfo );
2834       (void) DestroyExceptionInfo( &exceptionInfo );
2835       return;
2836     }
2837
2838   if ( colorSpace_ == RGBColorspace ||
2839        colorSpace_ == sRGBColorspace ||
2840        colorSpace_ == TransparentColorspace ||
2841        colorSpace_ == GRAYColorspace )
2842     {
2843       /* Transform to a RGB-type colorspace */
2844       TransformRGBImage( image(), image()->colorspace, &exceptionInfo );
2845       throwException( exceptionInfo );
2846       (void) DestroyExceptionInfo( &exceptionInfo );
2847       return;
2848     }
2849   throwException( exceptionInfo );
2850   (void) DestroyExceptionInfo( &exceptionInfo );
2851 }
2852 Magick::ColorspaceType Magick::Image::colorSpace ( void ) const
2853 {
2854   return constImage()->colorspace;
2855 }
2856
2857 // Set image colorspace type.
2858 void Magick::Image::colorspaceType( const ColorspaceType colorSpace_ )
2859 {
2860   modifyImage();
2861   options()->colorspaceType( colorSpace_ );
2862 }
2863 Magick::ColorspaceType Magick::Image::colorspaceType ( void ) const
2864 {
2865   return constOptions()->colorspaceType();
2866 }
2867
2868
2869 // Comment string
2870 void Magick::Image::comment ( const std::string &comment_ )
2871 {
2872   modifyImage();
2873   ExceptionInfo exceptionInfo;
2874   GetExceptionInfo( &exceptionInfo );
2875   SetImageProperty( image(), "Comment", NULL, &exceptionInfo );
2876   if ( comment_.length() > 0 )
2877     SetImageProperty( image(), "Comment", comment_.c_str(), &exceptionInfo );
2878   throwException( exceptionInfo );
2879   (void) DestroyExceptionInfo( &exceptionInfo );
2880 }
2881 std::string Magick::Image::comment ( void ) const
2882 {
2883   ExceptionInfo exceptionInfo;
2884   GetExceptionInfo( &exceptionInfo );
2885   const char *value = GetImageProperty( constImage(), "Comment",
2886     &exceptionInfo );
2887   throwException( exceptionInfo );
2888   (void) DestroyExceptionInfo( &exceptionInfo );
2889
2890   if ( value )
2891     return std::string( value );
2892
2893   return std::string(); // Intentionally no exception
2894 }
2895
2896 // Composition operator to be used when composition is implicitly used
2897 // (such as for image flattening).
2898 void Magick::Image::compose (const CompositeOperator compose_)
2899 {
2900   image()->compose=compose_;
2901 }
2902
2903 Magick::CompositeOperator Magick::Image::compose ( void ) const
2904 {
2905   return constImage()->compose;
2906 }
2907
2908 // Compression algorithm
2909 void Magick::Image::compressType ( const CompressionType compressType_ )
2910 {
2911   modifyImage();
2912   image()->compression = compressType_;
2913   options()->compressType( compressType_ );
2914 }
2915 Magick::CompressionType Magick::Image::compressType ( void ) const
2916 {
2917   return constImage()->compression;
2918 }
2919
2920 // Enable printing of debug messages from ImageMagick
2921 void Magick::Image::debug ( const bool flag_ )
2922 {
2923   modifyImage();
2924   options()->debug( flag_ );
2925 }
2926 bool Magick::Image::debug ( void ) const
2927 {
2928   return constOptions()->debug();
2929 }
2930
2931 // Tagged image format define (set/access coder-specific option) The
2932 // magick_ option specifies the coder the define applies to.  The key_
2933 // option provides the key specific to that coder.  The value_ option
2934 // provides the value to set (if any). See the defineSet() method if the
2935 // key must be removed entirely.
2936 void Magick::Image::defineValue ( const std::string &magick_,
2937                                   const std::string &key_,
2938                                   const std::string &value_ )
2939 {
2940   modifyImage();
2941   std::string format = magick_ + ":" + key_;
2942   std::string option = value_;
2943   (void) SetImageOption ( imageInfo(), format.c_str(), option.c_str() );
2944 }
2945 std::string Magick::Image::defineValue ( const std::string &magick_,
2946                                          const std::string &key_ ) const
2947 {
2948   std::string definition = magick_ + ":" + key_;
2949   const char *option =
2950     GetImageOption ( constImageInfo(), definition.c_str() );
2951   if (option)
2952     return std::string( option );
2953   return std::string( );
2954 }
2955
2956 // Tagged image format define. Similar to the defineValue() method
2957 // except that passing the flag_ value 'true' creates a value-less
2958 // define with that format and key. Passing the flag_ value 'false'
2959 // removes any existing matching definition. The method returns 'true'
2960 // if a matching key exists, and 'false' if no matching key exists.
2961 void Magick::Image::defineSet ( const std::string &magick_,
2962                                 const std::string &key_,
2963                                 bool flag_ )
2964 {
2965   modifyImage();
2966   std::string definition = magick_ + ":" + key_;
2967   if (flag_)
2968     {
2969       (void) SetImageOption ( imageInfo(), definition.c_str(),  "" );
2970     }
2971   else
2972     {
2973       DeleteImageOption( imageInfo(), definition.c_str() );
2974     }
2975 }
2976 bool Magick::Image::defineSet ( const std::string &magick_,
2977                                 const std::string &key_ ) const
2978 {
2979   std::string key = magick_ + ":" + key_;
2980   const char *option =
2981     GetImageOption ( constImageInfo(), key.c_str() );
2982   if (option)
2983     return true;
2984   return false;
2985 }
2986
2987 // Pixel resolution
2988 void Magick::Image::density ( const Geometry &density_ )
2989 {
2990   modifyImage();
2991   options()->density( density_ );
2992   if ( density_.isValid() )
2993     {
2994       image()->resolution.x = density_.width();
2995       if ( density_.height() != 0 )
2996         {
2997           image()->resolution.y = density_.height();
2998         }
2999       else
3000         {
3001           image()->resolution.y = density_.width();
3002         }
3003     }
3004   else
3005     {
3006       // Reset to default
3007       image()->resolution.x = 0;
3008       image()->resolution.y = 0;
3009     }
3010 }
3011 Magick::Geometry Magick::Image::density ( void ) const
3012 {
3013   if (isValid())
3014     {
3015       ssize_t x_resolution=72;
3016       ssize_t y_resolution=72;
3017
3018       if (constImage()->resolution.x > 0.0)
3019         x_resolution=static_cast<ssize_t>(constImage()->resolution.x + 0.5);
3020
3021       if (constImage()->resolution.y > 0.0)
3022         y_resolution=static_cast<ssize_t>(constImage()->resolution.y + 0.5);
3023
3024       return Geometry(x_resolution,y_resolution);
3025     }
3026
3027   return constOptions()->density( );
3028 }
3029
3030 // Image depth (bits allocated to red/green/blue components)
3031 void Magick::Image::depth ( const size_t depth_ )
3032 {
3033   size_t depth = depth_;
3034
3035   if (depth > MAGICKCORE_QUANTUM_DEPTH)
3036     depth=MAGICKCORE_QUANTUM_DEPTH;
3037
3038   modifyImage();
3039   image()->depth=depth;
3040   options()->depth( depth );
3041 }
3042 size_t Magick::Image::depth ( void ) const
3043 {
3044   return constImage()->depth;
3045 }
3046
3047 std::string Magick::Image::directory ( void ) const
3048 {
3049   if ( constImage()->directory )
3050     return std::string( constImage()->directory );
3051
3052   throwExceptionExplicit( CorruptImageWarning,
3053                           "Image does not contain a directory");
3054
3055   return std::string();
3056 }
3057
3058 // Endianness (little like Intel or big like SPARC) for image
3059 // formats which support endian-specific options.
3060 void Magick::Image::endian ( const Magick::EndianType endian_ )
3061 {
3062   modifyImage();
3063   options()->endian( endian_ );
3064   image()->endian = endian_;
3065 }
3066 Magick::EndianType Magick::Image::endian ( void ) const
3067 {
3068   return constImage()->endian;
3069 }
3070
3071 // EXIF profile (BLOB)
3072 void Magick::Image::exifProfile( const Magick::Blob &exifProfile_ )
3073 {
3074   modifyImage();
3075   if ( exifProfile_.data() != 0 )
3076     {
3077       StringInfo * exif_profile = AcquireStringInfo( exifProfile_.length() );
3078       SetStringInfoDatum(exif_profile ,(unsigned char *) exifProfile_.data());
3079       ExceptionInfo exceptionInfo;
3080       GetExceptionInfo( &exceptionInfo );
3081       (void) SetImageProfile( image(), "exif", exif_profile, &exceptionInfo);
3082       exif_profile =DestroyStringInfo( exif_profile );
3083       throwException( exceptionInfo );
3084       (void) DestroyExceptionInfo( &exceptionInfo );
3085     }
3086 }
3087 Magick::Blob Magick::Image::exifProfile( void ) const
3088 {
3089   const StringInfo * exif_profile = GetImageProfile( constImage(), "exif" );
3090   if ( exif_profile == (StringInfo *) NULL)
3091     return Blob( 0, 0 );
3092   return Blob(GetStringInfoDatum(exif_profile),GetStringInfoLength(exif_profile));
3093
3094
3095 // Image file name
3096 void Magick::Image::fileName ( const std::string &fileName_ )
3097 {
3098   modifyImage();
3099
3100   fileName_.copy( image()->filename,
3101                   sizeof(image()->filename) - 1 );
3102   image()->filename[ fileName_.length() ] = 0; // Null terminate
3103   
3104   options()->fileName( fileName_ );
3105   
3106 }
3107 std::string Magick::Image::fileName ( void ) const
3108 {
3109   return constOptions()->fileName( );
3110 }
3111
3112 // Image file size
3113 off_t Magick::Image::fileSize ( void ) const
3114 {
3115   return (off_t) GetBlobSize( constImage() );
3116 }
3117
3118 // Color to use when drawing inside an object
3119 void Magick::Image::fillColor ( const Magick::Color &fillColor_ )
3120 {
3121   modifyImage();
3122   options()->fillColor(fillColor_);
3123 }
3124 Magick::Color Magick::Image::fillColor ( void ) const
3125 {
3126   return constOptions()->fillColor();
3127 }
3128
3129 // Rule to use when filling drawn objects
3130 void Magick::Image::fillRule ( const Magick::FillRule &fillRule_ )
3131 {
3132   modifyImage();
3133   options()->fillRule(fillRule_);
3134 }
3135 Magick::FillRule Magick::Image::fillRule ( void ) const
3136 {
3137   return constOptions()->fillRule();
3138 }
3139
3140 // Pattern to use while filling drawn objects.
3141 void Magick::Image::fillPattern ( const Image &fillPattern_ )
3142 {
3143   modifyImage();
3144   if(fillPattern_.isValid())
3145     options()->fillPattern( fillPattern_.constImage() );
3146   else
3147     options()->fillPattern( static_cast<MagickCore::Image*>(NULL) );
3148 }
3149 Magick::Image  Magick::Image::fillPattern ( void  ) const
3150 {
3151   // FIXME: This is inordinately innefficient
3152   Image texture;
3153   
3154   const MagickCore::Image* tmpTexture = constOptions()->fillPattern( );
3155
3156   if ( tmpTexture )
3157     {
3158       ExceptionInfo exceptionInfo;
3159       GetExceptionInfo( &exceptionInfo );
3160       MagickCore::Image* image =
3161         CloneImage( tmpTexture,
3162                     0, // columns
3163                     0, // rows
3164                     MagickTrue, // orphan
3165                     &exceptionInfo);
3166       texture.replaceImage( image );
3167       throwException( exceptionInfo );
3168       (void) DestroyExceptionInfo( &exceptionInfo );
3169     }
3170   return texture;
3171 }
3172
3173 // Filter used by zoom
3174 void Magick::Image::filterType ( const Magick::FilterTypes filterType_ )
3175 {
3176   modifyImage();
3177   image()->filter = filterType_;
3178 }
3179 Magick::FilterTypes Magick::Image::filterType ( void ) const
3180 {
3181   return constImage()->filter;
3182 }
3183
3184 // Font name
3185 void Magick::Image::font ( const std::string &font_ )
3186 {
3187   modifyImage();
3188   options()->font( font_ );
3189 }
3190 std::string Magick::Image::font ( void ) const
3191 {
3192   return constOptions()->font( );
3193 }
3194
3195 // Font point size
3196 void Magick::Image::fontPointsize ( const double pointSize_ )
3197 {
3198   modifyImage();
3199   options()->fontPointsize( pointSize_ );
3200 }
3201 double Magick::Image::fontPointsize ( void ) const
3202 {
3203   return constOptions()->fontPointsize( );
3204 }
3205
3206 // Font type metrics
3207 void Magick::Image::fontTypeMetrics( const std::string &text_,
3208                                      TypeMetric *metrics )
3209 {
3210   DrawInfo *drawInfo = options()->drawInfo();
3211   drawInfo->text = const_cast<char *>(text_.c_str());
3212   ExceptionInfo exceptionInfo;
3213   GetExceptionInfo( &exceptionInfo );
3214   GetTypeMetrics( image(), drawInfo, &(metrics->_typeMetric), &exceptionInfo );
3215   drawInfo->text = 0;
3216   throwException( exceptionInfo );
3217   (void) DestroyExceptionInfo( &exceptionInfo );
3218 }
3219
3220 // Image format string
3221 std::string Magick::Image::format ( void ) const
3222 {
3223   ExceptionInfo exceptionInfo;
3224   GetExceptionInfo( &exceptionInfo );
3225   const MagickInfo * magick_info
3226     = GetMagickInfo( constImage()->magick, &exceptionInfo);
3227   throwException( exceptionInfo );
3228   (void) DestroyExceptionInfo( &exceptionInfo );
3229
3230   if (( magick_info != 0 ) && 
3231       ( *magick_info->description != '\0' ))
3232     return std::string(magick_info->description);
3233
3234   throwExceptionExplicit( CorruptImageWarning,
3235                           "Unrecognized image magick type" );
3236   return std::string();
3237 }
3238
3239 // Gamma adjustment
3240 double Magick::Image::gamma ( void ) const
3241 {
3242   return constImage()->gamma;
3243 }
3244
3245 Magick::Geometry Magick::Image::geometry ( void ) const
3246 {
3247   if ( constImage()->geometry )
3248   {
3249     return Geometry(constImage()->geometry);
3250   }
3251
3252   throwExceptionExplicit( OptionWarning,
3253                           "Image does not contain a geometry");
3254
3255   return Geometry();
3256 }
3257
3258 void Magick::Image::gifDisposeMethod ( const size_t disposeMethod_ )
3259 {
3260   modifyImage();
3261   image()->dispose = (DisposeType) disposeMethod_;
3262 }
3263 size_t Magick::Image::gifDisposeMethod ( void ) const
3264 {
3265   // FIXME: It would be better to return an enumeration
3266   return constImage()->dispose;
3267 }
3268
3269 // ICC ICM color profile (BLOB)
3270 void Magick::Image::iccColorProfile( const Magick::Blob &colorProfile_ )
3271 {
3272   profile("icm",colorProfile_);
3273 }
3274 Magick::Blob Magick::Image::iccColorProfile( void ) const
3275 {
3276   const StringInfo * color_profile = GetImageProfile( constImage(), "icc" );
3277   if ( color_profile == (StringInfo *) NULL)
3278     return Blob( 0, 0 );
3279   return Blob( GetStringInfoDatum(color_profile), GetStringInfoLength(color_profile) );
3280 }
3281
3282 void Magick::Image::interlaceType ( const Magick::InterlaceType interlace_ )
3283 {
3284   modifyImage();
3285   image()->interlace = interlace_;
3286   options()->interlaceType ( interlace_ );
3287 }
3288 Magick::InterlaceType Magick::Image::interlaceType ( void ) const
3289 {
3290   return constImage()->interlace;
3291 }
3292
3293 // IPTC profile (BLOB)
3294 void Magick::Image::iptcProfile( const Magick::Blob &iptcProfile_ )
3295 {
3296   modifyImage();
3297   if (  iptcProfile_.data() != 0 )
3298     {
3299       StringInfo * iptc_profile = AcquireStringInfo( iptcProfile_.length() );
3300       SetStringInfoDatum(iptc_profile ,(unsigned char *) iptcProfile_.data());
3301       ExceptionInfo exceptionInfo;
3302       GetExceptionInfo( &exceptionInfo );
3303       (void) SetImageProfile( image(), "iptc", iptc_profile, &exceptionInfo);
3304       iptc_profile =DestroyStringInfo( iptc_profile );
3305       throwException( exceptionInfo );
3306       (void) DestroyExceptionInfo( &exceptionInfo );
3307     }
3308 }
3309 Magick::Blob Magick::Image::iptcProfile( void ) const
3310 {
3311   const StringInfo * iptc_profile = GetImageProfile( constImage(), "iptc" );
3312   if ( iptc_profile == (StringInfo *) NULL)
3313     return Blob( 0, 0 );
3314   return Blob( GetStringInfoDatum(iptc_profile), GetStringInfoLength(iptc_profile));
3315 }
3316
3317 // Does object contain valid image?
3318 void Magick::Image::isValid ( const bool isValid_ )
3319 {
3320   if ( !isValid_ )
3321     {
3322       delete _imgRef;
3323       _imgRef = new ImageRef;
3324     }
3325   else if ( !isValid() )
3326     {
3327       // Construct with single-pixel black image to make
3328       // image valid.  This is an obvious hack.
3329       size( Geometry(1,1) );
3330       read( "xc:#000000" );
3331     }
3332 }
3333
3334 bool Magick::Image::isValid ( void ) const
3335 {
3336   if ( rows() && columns() )
3337     return true;
3338
3339   return false;
3340 }
3341
3342 // Label image
3343 void Magick::Image::label ( const std::string &label_ )
3344 {
3345   modifyImage();
3346   ExceptionInfo exceptionInfo;
3347   GetExceptionInfo( &exceptionInfo );
3348   SetImageProperty ( image(), "Label", NULL, &exceptionInfo );
3349   if ( label_.length() > 0 )
3350     SetImageProperty ( image(), "Label", label_.c_str(), &exceptionInfo );
3351   throwException( exceptionInfo );
3352   (void) DestroyExceptionInfo( &exceptionInfo );
3353 }
3354 std::string Magick::Image::label ( void ) const
3355 {
3356   ExceptionInfo exceptionInfo;
3357   GetExceptionInfo( &exceptionInfo );
3358   const char *value = GetImageProperty( constImage(), "Label", &exceptionInfo );
3359   throwException( exceptionInfo );
3360   (void) DestroyExceptionInfo( &exceptionInfo );
3361
3362   if ( value )
3363     return std::string( value );
3364
3365   return std::string();
3366 }
3367
3368 void Magick::Image::magick ( const std::string &magick_ )
3369 {
3370   modifyImage();
3371
3372   magick_.copy( image()->magick,
3373                 sizeof(image()->magick) - 1 );
3374   image()->magick[ magick_.length() ] = 0;
3375   
3376   options()->magick( magick_ );
3377 }
3378 std::string Magick::Image::magick ( void ) const
3379 {
3380   if ( *(constImage()->magick) != '\0' )
3381     return std::string(constImage()->magick);
3382
3383   return constOptions()->magick( );
3384 }
3385
3386 void Magick::Image::matte ( const bool matteFlag_ )
3387 {
3388   modifyImage();
3389
3390   // If matte channel is requested, but image doesn't already have a
3391   // matte channel, then create an opaque matte channel.  Likewise, if
3392   // the image already has a matte channel but a matte channel is not
3393   // desired, then set the matte channel to opaque.
3394   ExceptionInfo exceptionInfo;
3395   GetExceptionInfo( &exceptionInfo );
3396   if ((matteFlag_ && !constImage()->matte) ||
3397       (constImage()->matte && !matteFlag_))
3398     SetImageAlpha(image(),OpaqueAlpha,&exceptionInfo);
3399   throwException( exceptionInfo );
3400   (void) DestroyExceptionInfo( &exceptionInfo );
3401
3402   image()->matte = (MagickBooleanType) matteFlag_;
3403 }
3404 bool Magick::Image::matte ( void ) const
3405 {
3406   if ( constImage()->matte )
3407     return true;
3408   else
3409     return false;
3410 }
3411
3412 void Magick::Image::matteColor ( const Color &matteColor_ )
3413 {
3414   modifyImage();
3415   
3416   if ( matteColor_.isValid() )
3417     {
3418       image()->matte_color = matteColor_;
3419       options()->matteColor( matteColor_ );
3420     }
3421   else
3422     {
3423       // Set to default matte color
3424       Color tmpColor( "#BDBDBD" );
3425       image()->matte_color = tmpColor;
3426       options()->matteColor( tmpColor );
3427     }
3428 }
3429 Magick::Color Magick::Image::matteColor ( void ) const
3430 {
3431   return Color( ClampToQuantum( constImage()->matte_color.red ),
3432                 ClampToQuantum( constImage()->matte_color.green ),
3433                 ClampToQuantum( constImage()->matte_color.blue ) );
3434 }
3435
3436 double Magick::Image::meanErrorPerPixel ( void ) const
3437 {
3438   return(constImage()->error.mean_error_per_pixel);
3439 }
3440
3441 // Image modulus depth (minimum number of bits required to support
3442 // red/green/blue components without loss of accuracy)
3443 void Magick::Image::modulusDepth ( const size_t depth_ )
3444 {
3445   modifyImage();
3446   ExceptionInfo exceptionInfo;
3447   GetExceptionInfo( &exceptionInfo );
3448   SetImageDepth( image(), depth_, &exceptionInfo );
3449   throwException( exceptionInfo );
3450   (void) DestroyExceptionInfo( &exceptionInfo );
3451   options()->depth( depth_ );
3452 }
3453 size_t Magick::Image::modulusDepth ( void ) const
3454 {
3455   ExceptionInfo exceptionInfo;
3456   GetExceptionInfo( &exceptionInfo );
3457   size_t depth=GetImageDepth( constImage(), &exceptionInfo );
3458   throwException( exceptionInfo );
3459   (void) DestroyExceptionInfo( &exceptionInfo );
3460   return depth;
3461 }
3462
3463 void Magick::Image::monochrome ( const bool monochromeFlag_ )
3464 {
3465   modifyImage();
3466   options()->monochrome( monochromeFlag_ );
3467 }
3468 bool Magick::Image::monochrome ( void ) const
3469 {
3470   return constOptions()->monochrome( );
3471 }
3472
3473 Magick::Geometry Magick::Image::montageGeometry ( void ) const
3474 {
3475   if ( constImage()->montage )
3476     return Magick::Geometry(constImage()->montage);
3477
3478   throwExceptionExplicit( CorruptImageWarning,
3479                           "Image does not contain a montage" );
3480
3481   return Magick::Geometry();
3482 }
3483
3484 double Magick::Image::normalizedMaxError ( void ) const
3485 {
3486   return(constImage()->error.normalized_maximum_error);
3487 }
3488
3489 double Magick::Image::normalizedMeanError ( void ) const
3490 {
3491   return constImage()->error.normalized_mean_error;
3492 }
3493
3494 // Image orientation
3495 void Magick::Image::orientation ( const Magick::OrientationType orientation_ )
3496 {
3497   modifyImage();
3498   image()->orientation = orientation_;
3499 }
3500 Magick::OrientationType Magick::Image::orientation ( void ) const
3501 {
3502   return constImage()->orientation;
3503 }
3504
3505 void Magick::Image::penColor ( const Color &penColor_ )
3506 {
3507   modifyImage();
3508   options()->fillColor(penColor_);
3509   options()->strokeColor(penColor_);
3510 }
3511 Magick::Color Magick::Image::penColor ( void  ) const
3512 {
3513   return constOptions()->fillColor();
3514 }
3515
3516 void Magick::Image::penTexture ( const Image &penTexture_ )
3517 {
3518   modifyImage();
3519   if(penTexture_.isValid())
3520     options()->fillPattern( penTexture_.constImage() );
3521   else
3522     options()->fillPattern( static_cast<MagickCore::Image*>(NULL) );
3523 }
3524
3525 Magick::Image  Magick::Image::penTexture ( void  ) const
3526 {
3527   // FIXME: This is inordinately innefficient
3528   Image texture;
3529   
3530   const MagickCore::Image* tmpTexture = constOptions()->fillPattern( );
3531
3532   if ( tmpTexture )
3533     {
3534       ExceptionInfo exceptionInfo;
3535       GetExceptionInfo( &exceptionInfo );
3536       MagickCore::Image* image =
3537         CloneImage( tmpTexture,
3538                     0, // columns
3539                     0, // rows
3540                     MagickTrue, // orphan
3541                     &exceptionInfo);
3542       texture.replaceImage( image );
3543       throwException( exceptionInfo );
3544   (void) DestroyExceptionInfo( &exceptionInfo );
3545     }
3546   return texture;
3547 }
3548
3549 // Set the color of a pixel.
3550 void Magick::Image::pixelColor ( const ssize_t x_, const ssize_t y_,
3551                                  const Color &color_ )
3552 {
3553   // Test arguments to ensure they are within the image.
3554   if ( y_ > (ssize_t) rows() || x_ > (ssize_t) columns() )
3555     throwExceptionExplicit( OptionError,
3556             "Access outside of image boundary" );
3557       
3558   modifyImage();
3559
3560   // Set image to DirectClass
3561   classType( DirectClass );
3562
3563   // Get pixel view
3564   Pixels pixels(*this);
3565     // Set pixel value
3566   Quantum *pixel = pixels.get(x_, y_, 1, 1 );
3567   PixelInfo packet = color_;
3568   MagickCore::SetPixelInfoPixel(constImage(),&packet,pixel);
3569   // Tell ImageMagick that pixels have been updated
3570   pixels.sync();
3571
3572   return;
3573 }
3574
3575 // Get the color of a pixel
3576 Magick::Color Magick::Image::pixelColor ( const ssize_t x_,
3577                                           const ssize_t y_ ) const
3578 {
3579   ClassType storage_class;
3580   storage_class = classType();
3581   // DirectClass
3582   const Quantum* pixel = getConstPixels( x_, y_, 1, 1 );
3583   if ( pixel )
3584     {
3585       PixelInfo packet;
3586       MagickCore::GetPixelInfoPixel(constImage(),pixel,&packet);
3587       return Color( packet );
3588     }
3589
3590   return Color(); // invalid
3591 }
3592
3593 // Preferred size and location of an image canvas.
3594 void Magick::Image::page ( const Magick::Geometry &pageSize_ )
3595 {
3596   modifyImage();
3597   options()->page( pageSize_ );
3598   image()->page = pageSize_;
3599 }
3600 Magick::Geometry Magick::Image::page ( void ) const
3601 {
3602   return Geometry( constImage()->page.width,
3603                    constImage()->page.height,
3604                    AbsoluteValue(constImage()->page.x),
3605                    AbsoluteValue(constImage()->page.y),
3606                    constImage()->page.x < 0 ? true : false,
3607                    constImage()->page.y < 0 ? true : false);
3608 }
3609
3610 // Add a named profile to an image or remove a named profile by
3611 // passing an empty Blob (use default Blob constructor).
3612 // Valid names are:
3613 // "*", "8BIM", "ICM", "IPTC", or a generic profile name.
3614 void Magick::Image::profile( const std::string name_,
3615                              const Magick::Blob &profile_ )
3616 {
3617   modifyImage();
3618   ExceptionInfo exceptionInfo;
3619   GetExceptionInfo( &exceptionInfo );
3620   ssize_t result = ProfileImage( image(), name_.c_str(),
3621                              (unsigned char *)profile_.data(),
3622                              profile_.length(), &exceptionInfo);
3623   throwException( exceptionInfo );
3624   (void) DestroyExceptionInfo( &exceptionInfo );
3625
3626 }
3627
3628 // Retrieve a named profile from the image.
3629 // Valid names are:
3630 // "8BIM", "8BIMTEXT", "APP1", "APP1JPEG", "ICC", "ICM", & "IPTC" or
3631 // an existing generic profile name.
3632 Magick::Blob Magick::Image::profile( const std::string name_ ) const
3633 {
3634   const MagickCore::Image* image = constImage();
3635                                                                                 
3636   const StringInfo * profile = GetImageProfile( image, name_.c_str() );
3637                                                                                 
3638   if ( profile != (StringInfo *) NULL)
3639       return Blob( (void*) GetStringInfoDatum(profile), GetStringInfoLength(profile));
3640                                                                                 
3641   Blob blob;
3642   Image temp_image = *this;
3643   temp_image.write( &blob, name_ );
3644   return blob;
3645 }
3646
3647 void Magick::Image::quality ( const size_t quality_ )
3648 {
3649   modifyImage();
3650   image()->quality = quality_;
3651   options()->quality( quality_ );
3652 }
3653 size_t Magick::Image::quality ( void ) const
3654 {
3655   return constImage()->quality;
3656 }
3657
3658 void Magick::Image::quantizeColors ( const size_t colors_ )
3659 {
3660   modifyImage();
3661   options()->quantizeColors( colors_ );
3662 }
3663 size_t Magick::Image::quantizeColors ( void ) const
3664 {
3665   return constOptions()->quantizeColors( );
3666 }
3667
3668 void Magick::Image::quantizeColorSpace
3669   ( const Magick::ColorspaceType colorSpace_ )
3670 {
3671   modifyImage();
3672   options()->quantizeColorSpace( colorSpace_ );
3673 }
3674 Magick::ColorspaceType Magick::Image::quantizeColorSpace ( void ) const
3675 {
3676   return constOptions()->quantizeColorSpace( );
3677 }
3678
3679 void Magick::Image::quantizeDither ( const bool ditherFlag_ )
3680 {
3681   modifyImage();
3682   options()->quantizeDither( ditherFlag_ );
3683 }
3684 bool Magick::Image::quantizeDither ( void ) const
3685 {
3686   return constOptions()->quantizeDither( );
3687 }
3688
3689 void Magick::Image::quantizeTreeDepth ( const size_t treeDepth_ )
3690 {
3691   modifyImage();
3692   options()->quantizeTreeDepth( treeDepth_ );
3693 }
3694 size_t Magick::Image::quantizeTreeDepth ( void ) const
3695 {
3696   return constOptions()->quantizeTreeDepth( );
3697 }
3698
3699 void Magick::Image::renderingIntent
3700   ( const Magick::RenderingIntent renderingIntent_ )
3701 {
3702   modifyImage();
3703   image()->rendering_intent = renderingIntent_;
3704 }
3705 Magick::RenderingIntent Magick::Image::renderingIntent ( void ) const
3706 {
3707   return static_cast<Magick::RenderingIntent>(constImage()->rendering_intent);
3708 }
3709
3710 void Magick::Image::resolutionUnits
3711   ( const Magick::ResolutionType resolutionUnits_ )
3712 {
3713   modifyImage();
3714   image()->units = resolutionUnits_;
3715   options()->resolutionUnits( resolutionUnits_ );
3716 }
3717 Magick::ResolutionType Magick::Image::resolutionUnits ( void ) const
3718 {
3719   return constOptions()->resolutionUnits( );
3720 }
3721
3722 void Magick::Image::scene ( const size_t scene_ )
3723 {
3724   modifyImage();
3725   image()->scene = scene_;
3726 }
3727 size_t Magick::Image::scene ( void ) const
3728 {
3729   return constImage()->scene;
3730 }
3731
3732 std::string Magick::Image::signature ( const bool force_ ) const
3733 {
3734   Lock( &_imgRef->_mutexLock );
3735
3736   // Re-calculate image signature if necessary
3737   ExceptionInfo exceptionInfo;
3738   GetExceptionInfo( &exceptionInfo );
3739   if ( force_ ||
3740        !GetImageProperty(constImage(), "Signature", &exceptionInfo) ||
3741        constImage()->taint )
3742     {
3743       SignatureImage( const_cast<MagickCore::Image *>(constImage()), &exceptionInfo );
3744     }
3745
3746   const char *property = GetImageProperty(constImage(), "Signature",
3747     &exceptionInfo);
3748   throwException( exceptionInfo );
3749   (void) DestroyExceptionInfo( &exceptionInfo );
3750
3751   return std::string( property );
3752 }
3753
3754 void Magick::Image::size ( const Geometry &geometry_ )
3755 {
3756   modifyImage();
3757   options()->size( geometry_ );
3758   image()->rows = geometry_.height();
3759   image()->columns = geometry_.width();
3760 }
3761 Magick::Geometry Magick::Image::size ( void ) const
3762 {
3763   return Magick::Geometry( constImage()->columns, constImage()->rows );
3764 }
3765
3766 // Splice image
3767 void Magick::Image::splice( const Geometry &geometry_ )
3768 {
3769   RectangleInfo spliceInfo = geometry_;
3770   ExceptionInfo exceptionInfo;
3771   GetExceptionInfo( &exceptionInfo );
3772   MagickCore::Image* newImage =
3773     SpliceImage( image(), &spliceInfo, &exceptionInfo);
3774   replaceImage( newImage );
3775   throwException( exceptionInfo );
3776   (void) DestroyExceptionInfo( &exceptionInfo );
3777 }
3778
3779 // Obtain image statistics. Statistics are normalized to the range of
3780 // 0.0 to 1.0 and are output to the specified ImageStatistics
3781 // structure.
3782 void Magick::Image::statistics ( ImageStatistics *statistics ) 
3783 {
3784   double
3785     maximum,
3786     minimum;
3787
3788   ExceptionInfo exceptionInfo;
3789   GetExceptionInfo( &exceptionInfo );
3790
3791   ChannelType channel_mask = SetPixelChannelMask( image(), RedChannel);
3792   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3793   statistics->red.minimum=minimum;
3794   statistics->red.maximum=maximum;
3795   (void) GetImageMean( image(),&statistics->red.mean,
3796     &statistics->red.standard_deviation,&exceptionInfo);
3797   (void) GetImageKurtosis( image(),&statistics->red.kurtosis,
3798     &statistics->red.skewness,&exceptionInfo);
3799   (void) SetPixelChannelMapMask( image(), channel_mask );
3800
3801   channel_mask = SetPixelChannelMask( image(), GreenChannel);
3802   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3803   statistics->green.minimum=minimum;
3804   statistics->green.maximum=maximum;
3805   (void) GetImageMean( image(),&statistics->green.mean,
3806     &statistics->green.standard_deviation,&exceptionInfo);
3807   (void) GetImageKurtosis( image(),&statistics->green.kurtosis,
3808     &statistics->green.skewness,&exceptionInfo);
3809   (void) SetPixelChannelMapMask( image(), channel_mask );
3810
3811   channel_mask = SetPixelChannelMask( image(), GreenChannel);
3812   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3813   statistics->blue.minimum=minimum;
3814   statistics->blue.maximum=maximum;
3815   (void) GetImageMean( image(),&statistics->blue.mean,
3816     &statistics->blue.standard_deviation,&exceptionInfo);
3817   (void) GetImageKurtosis( image(),&statistics->blue.kurtosis,
3818     &statistics->blue.skewness,&exceptionInfo);
3819   (void) SetPixelChannelMapMask( image(), channel_mask );
3820
3821   channel_mask = SetPixelChannelMask( image(), AlphaChannel);
3822   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3823   statistics->alpha.minimum=minimum;
3824   statistics->alpha.maximum=maximum;
3825   (void) GetImageMean( image(),&statistics->alpha.mean,
3826     &statistics->alpha.standard_deviation,&exceptionInfo);
3827   (void) GetImageKurtosis( image(),&statistics->alpha.kurtosis,
3828     &statistics->alpha.skewness,&exceptionInfo);
3829   (void) SetPixelChannelMapMask( image(), channel_mask );
3830
3831   throwException( exceptionInfo );
3832   (void) DestroyExceptionInfo( &exceptionInfo );
3833 }
3834
3835 // Strip strips an image of all profiles and comments.
3836 void Magick::Image::strip ( void )
3837 {
3838   modifyImage();
3839   ExceptionInfo exceptionInfo;
3840   GetExceptionInfo( &exceptionInfo );
3841   StripImage( image(), &exceptionInfo );
3842   throwException( exceptionInfo );
3843   (void) DestroyExceptionInfo( &exceptionInfo );
3844 }
3845
3846 // enabled/disable stroke anti-aliasing
3847 void Magick::Image::strokeAntiAlias ( const bool flag_ )
3848 {
3849   modifyImage();
3850   options()->strokeAntiAlias(flag_);
3851 }
3852 bool Magick::Image::strokeAntiAlias ( void ) const
3853 {
3854   return constOptions()->strokeAntiAlias();
3855 }
3856
3857 // Color to use when drawing object outlines
3858 void Magick::Image::strokeColor ( const Magick::Color &strokeColor_ )
3859 {
3860   modifyImage();
3861   options()->strokeColor(strokeColor_);
3862 }
3863 Magick::Color Magick::Image::strokeColor ( void ) const
3864 {
3865   return constOptions()->strokeColor();
3866 }
3867
3868 // dash pattern for drawing vector objects (default one)
3869 void Magick::Image::strokeDashArray ( const double* strokeDashArray_ )
3870 {
3871   modifyImage();
3872   options()->strokeDashArray( strokeDashArray_ );
3873 }
3874
3875 const double* Magick::Image::strokeDashArray ( void ) const
3876 {
3877   return constOptions()->strokeDashArray( );
3878 }
3879
3880 // dash offset for drawing vector objects (default one)
3881 void Magick::Image::strokeDashOffset ( const double strokeDashOffset_ )
3882 {
3883   modifyImage();
3884   options()->strokeDashOffset( strokeDashOffset_ );
3885 }
3886
3887 double Magick::Image::strokeDashOffset ( void ) const
3888 {
3889   return constOptions()->strokeDashOffset( );
3890 }
3891
3892 // Specify the shape to be used at the end of open subpaths when they
3893 // are stroked. Values of LineCap are UndefinedCap, ButtCap, RoundCap,
3894 // and SquareCap.
3895 void Magick::Image::strokeLineCap ( const Magick::LineCap lineCap_ )
3896 {
3897   modifyImage();
3898   options()->strokeLineCap( lineCap_ );
3899 }
3900 Magick::LineCap Magick::Image::strokeLineCap ( void ) const
3901 {
3902   return constOptions()->strokeLineCap( );
3903 }
3904
3905 // Specify the shape to be used at the corners of paths (or other
3906 // vector shapes) when they are stroked. Values of LineJoin are
3907 // UndefinedJoin, MiterJoin, RoundJoin, and BevelJoin.
3908 void Magick::Image::strokeLineJoin ( const Magick::LineJoin lineJoin_ )
3909 {
3910   modifyImage();
3911   options()->strokeLineJoin( lineJoin_ );
3912 }
3913 Magick::LineJoin Magick::Image::strokeLineJoin ( void ) const
3914 {
3915   return constOptions()->strokeLineJoin( );
3916 }
3917
3918 // Specify miter limit. When two line segments meet at a sharp angle
3919 // and miter joins have been specified for 'lineJoin', it is possible
3920 // for the miter to extend far beyond the thickness of the line
3921 // stroking the path. The miterLimit' imposes a limit on the ratio of
3922 // the miter length to the 'lineWidth'. The default value of this
3923 // parameter is 4.
3924 void Magick::Image::strokeMiterLimit ( const size_t strokeMiterLimit_ )
3925 {
3926   modifyImage();
3927   options()->strokeMiterLimit( strokeMiterLimit_ );
3928 }
3929 size_t Magick::Image::strokeMiterLimit ( void ) const
3930 {
3931   return constOptions()->strokeMiterLimit( );
3932 }
3933
3934 // Pattern to use while stroking drawn objects.
3935 void Magick::Image::strokePattern ( const Image &strokePattern_ )
3936 {
3937   modifyImage();
3938   if(strokePattern_.isValid())
3939     options()->strokePattern( strokePattern_.constImage() );
3940   else
3941     options()->strokePattern( static_cast<MagickCore::Image*>(NULL) );
3942 }
3943 Magick::Image  Magick::Image::strokePattern ( void  ) const
3944 {
3945   // FIXME: This is inordinately innefficient
3946   Image texture;
3947   
3948   const MagickCore::Image* tmpTexture = constOptions()->strokePattern( );
3949
3950   if ( tmpTexture )
3951     {
3952       ExceptionInfo exceptionInfo;
3953       GetExceptionInfo( &exceptionInfo );
3954       MagickCore::Image* image =
3955         CloneImage( tmpTexture,
3956                     0, // columns
3957                     0, // rows
3958                     MagickTrue, // orphan
3959                     &exceptionInfo);
3960       throwException( exceptionInfo );
3961       (void) DestroyExceptionInfo( &exceptionInfo );
3962       texture.replaceImage( image );
3963     }
3964   return texture;
3965 }
3966
3967 // Stroke width for drawing lines, circles, ellipses, etc.
3968 void Magick::Image::strokeWidth ( const double strokeWidth_ )
3969 {
3970   modifyImage();
3971   options()->strokeWidth( strokeWidth_ );
3972 }
3973 double Magick::Image::strokeWidth ( void ) const
3974 {
3975   return constOptions()->strokeWidth( );
3976 }
3977
3978 void Magick::Image::subImage ( const size_t subImage_ )
3979 {
3980   modifyImage();
3981   options()->subImage( subImage_ );
3982 }
3983 size_t Magick::Image::subImage ( void ) const
3984 {
3985   return constOptions()->subImage( );
3986 }
3987
3988 void Magick::Image::subRange ( const size_t subRange_ )
3989 {
3990   modifyImage();
3991   options()->subRange( subRange_ );
3992 }
3993 size_t Magick::Image::subRange ( void ) const
3994 {
3995   return constOptions()->subRange( );
3996 }
3997
3998 // Annotation text encoding (e.g. "UTF-16")
3999 void Magick::Image::textEncoding ( const std::string &encoding_ )
4000 {
4001   modifyImage();
4002   options()->textEncoding( encoding_ );
4003 }
4004 std::string Magick::Image::textEncoding ( void ) const
4005 {
4006   return constOptions()->textEncoding( );
4007 }
4008
4009 size_t Magick::Image::totalColors ( void )
4010 {
4011   ExceptionInfo exceptionInfo;
4012   GetExceptionInfo( &exceptionInfo );
4013   size_t colors = GetNumberColors( image(), 0, &exceptionInfo);
4014   throwException( exceptionInfo );
4015   (void) DestroyExceptionInfo( &exceptionInfo );
4016   return colors;
4017 }
4018
4019 // Origin of coordinate system to use when annotating with text or drawing
4020 void Magick::Image::transformOrigin ( const double x_, const double y_ )
4021 {
4022   modifyImage();
4023   options()->transformOrigin( x_, y_ );
4024 }
4025
4026 // Rotation to use when annotating with text or drawing
4027 void Magick::Image::transformRotation ( const double angle_ )
4028 {
4029   modifyImage();
4030   options()->transformRotation( angle_ );
4031 }
4032
4033 // Reset transformation parameters to default
4034 void Magick::Image::transformReset ( void )
4035 {
4036   modifyImage();
4037   options()->transformReset();
4038 }
4039
4040 // Scale to use when annotating with text or drawing
4041 void Magick::Image::transformScale ( const double sx_, const double sy_ )
4042 {
4043   modifyImage();
4044   options()->transformScale( sx_, sy_ );
4045 }
4046
4047 // Skew to use in X axis when annotating with text or drawing
4048 void Magick::Image::transformSkewX ( const double skewx_ )
4049 {
4050   modifyImage();
4051   options()->transformSkewX( skewx_ );
4052 }
4053
4054 // Skew to use in Y axis when annotating with text or drawing
4055 void Magick::Image::transformSkewY ( const double skewy_ )
4056 {
4057   modifyImage();
4058   options()->transformSkewY( skewy_ );
4059 }
4060
4061 // Image representation type
4062 Magick::ImageType Magick::Image::type ( void ) const
4063 {
4064
4065   ExceptionInfo exceptionInfo;
4066   GetExceptionInfo( &exceptionInfo );
4067   ImageType image_type = constOptions()->type();
4068   if ( image_type == UndefinedType )
4069     image_type= GetImageType( constImage(), &exceptionInfo);
4070   throwException( exceptionInfo );
4071   (void) DestroyExceptionInfo( &exceptionInfo );
4072   return image_type;
4073 }
4074 void Magick::Image::type ( const Magick::ImageType type_)
4075 {
4076   ExceptionInfo exceptionInfo;
4077   GetExceptionInfo( &exceptionInfo );
4078   modifyImage();
4079   options()->type( type_ );
4080   SetImageType( image(), type_, &exceptionInfo );
4081   throwException( exceptionInfo );
4082   (void) DestroyExceptionInfo( &exceptionInfo );
4083 }
4084
4085 void Magick::Image::verbose ( const bool verboseFlag_ )
4086 {
4087   modifyImage();
4088   options()->verbose( verboseFlag_ );
4089 }
4090 bool Magick::Image::verbose ( void ) const
4091 {
4092   return constOptions()->verbose( );
4093 }
4094
4095 void Magick::Image::view ( const std::string &view_ )
4096 {
4097   modifyImage();
4098   options()->view( view_ );
4099 }
4100 std::string Magick::Image::view ( void ) const
4101 {
4102   return constOptions()->view( );
4103 }
4104
4105 // Virtual pixel method
4106 void Magick::Image::virtualPixelMethod ( const VirtualPixelMethod virtual_pixel_method_ )
4107 {
4108   modifyImage();
4109   ExceptionInfo exceptionInfo;
4110   GetExceptionInfo( &exceptionInfo );
4111   SetImageVirtualPixelMethod( image(), virtual_pixel_method_, &exceptionInfo );
4112   throwException( exceptionInfo );
4113   (void) DestroyExceptionInfo( &exceptionInfo );
4114 }
4115 Magick::VirtualPixelMethod Magick::Image::virtualPixelMethod ( void ) const
4116 {
4117   return GetImageVirtualPixelMethod( constImage() );
4118 }
4119
4120 void Magick::Image::x11Display ( const std::string &display_ )
4121 {
4122   modifyImage();
4123   options()->x11Display( display_ );
4124 }
4125 std::string Magick::Image::x11Display ( void ) const
4126 {
4127   return constOptions()->x11Display( );
4128 }
4129
4130 double Magick::Image::xResolution ( void ) const
4131 {
4132   return constImage()->resolution.x;
4133 }
4134 double Magick::Image::yResolution ( void ) const
4135 {
4136   return constImage()->resolution.y;
4137 }
4138
4139 // Copy Constructor
4140 Magick::Image::Image( const Image & image_ )
4141   : _imgRef(image_._imgRef)
4142 {
4143   Lock( &_imgRef->_mutexLock );
4144
4145   // Increase reference count
4146   ++_imgRef->_refCount;
4147 }
4148
4149 // Assignment operator
4150 Magick::Image& Magick::Image::operator=( const Magick::Image &image_ )
4151 {
4152   if( this != &image_ )
4153     {
4154       {
4155         Lock( &image_._imgRef->_mutexLock );
4156         ++image_._imgRef->_refCount;
4157       }
4158
4159       bool doDelete = false;
4160       {
4161         Lock( &_imgRef->_mutexLock );
4162         if ( --_imgRef->_refCount == 0 )
4163           doDelete = true;
4164       }
4165
4166       if ( doDelete )
4167         {
4168           // Delete old image reference with associated image and options.
4169           delete _imgRef;
4170           _imgRef = 0;
4171         }
4172       // Use new image reference
4173       _imgRef = image_._imgRef;
4174     }
4175
4176   return *this;
4177 }
4178
4179 //////////////////////////////////////////////////////////////////////    
4180 //
4181 // Low-level Pixel Access Routines
4182 //
4183 // Also see the Pixels class, which provides support for multiple
4184 // cache views. The low-level pixel access routines in the Image
4185 // class are provided in order to support backward compatability.
4186 //
4187 //////////////////////////////////////////////////////////////////////
4188
4189 // Transfers read-only pixels from the image to the pixel cache as
4190 // defined by the specified region
4191 const Magick::Quantum* Magick::Image::getConstPixels
4192   ( const ssize_t x_, const ssize_t y_,
4193     const size_t columns_,
4194     const size_t rows_ ) const
4195 {
4196   ExceptionInfo exceptionInfo;
4197   GetExceptionInfo( &exceptionInfo );
4198   const Quantum* p = (*GetVirtualPixels)( constImage(),
4199                                                 x_, y_,
4200                                                 columns_, rows_,
4201                                                 &exceptionInfo );
4202   throwException( exceptionInfo );
4203   (void) DestroyExceptionInfo( &exceptionInfo );
4204   return p;
4205 }
4206
4207 // Obtain read-only pixel associated pixels channels
4208 const void* Magick::Image::getConstMetacontent ( void ) const
4209 {
4210   const void* result = GetVirtualMetacontent( constImage() );
4211
4212   if( !result )
4213     throwImageException();
4214
4215   return result;
4216 }
4217
4218 // Obtain image pixel associated pixels channels
4219 void* Magick::Image::getMetacontent ( void )
4220 {
4221   void* result = GetAuthenticMetacontent( image() );
4222
4223   if( !result )
4224     throwImageException();
4225
4226   return ( result );
4227 }
4228
4229 // Transfers pixels from the image to the pixel cache as defined
4230 // by the specified region. Modified pixels may be subsequently
4231 // transferred back to the image via syncPixels.
4232 Magick::Quantum* Magick::Image::getPixels ( const ssize_t x_, const ssize_t y_,
4233                                                 const size_t columns_,
4234                                                 const size_t rows_ )
4235 {
4236   modifyImage();
4237   ExceptionInfo exceptionInfo;
4238   GetExceptionInfo( &exceptionInfo );
4239   Quantum* result = (*GetAuthenticPixels)( image(),
4240                                            x_, y_,
4241                                            columns_, rows_, &exceptionInfo );
4242   throwException( exceptionInfo );
4243   (void) DestroyExceptionInfo( &exceptionInfo );
4244
4245   return result;
4246 }
4247
4248 // Allocates a pixel cache region to store image pixels as defined
4249 // by the region rectangle.  This area is subsequently transferred
4250 // from the pixel cache to the image via syncPixels.
4251 Magick::Quantum* Magick::Image::setPixels ( const ssize_t x_, const ssize_t y_,
4252                                                 const size_t columns_,
4253                                                 const size_t rows_ )
4254 {
4255   modifyImage();
4256   ExceptionInfo exceptionInfo;
4257   GetExceptionInfo( &exceptionInfo );
4258   Quantum* result = (*QueueAuthenticPixels)( image(),
4259                                            x_, y_,
4260                                            columns_, rows_, &exceptionInfo );
4261   throwException( exceptionInfo );
4262   (void) DestroyExceptionInfo( &exceptionInfo );
4263
4264   return result;
4265 }
4266
4267 // Transfers the image cache pixels to the image.
4268 void Magick::Image::syncPixels ( void )
4269 {
4270   ExceptionInfo exceptionInfo;
4271   GetExceptionInfo( &exceptionInfo );
4272   (*SyncAuthenticPixels)( image(), &exceptionInfo );
4273   throwException( exceptionInfo );
4274   (void) DestroyExceptionInfo( &exceptionInfo );
4275 }
4276
4277 // Transfers one or more pixel components from a buffer or file
4278 // into the image pixel cache of an image.
4279 // Used to support image decoders.
4280 void Magick::Image::readPixels ( const Magick::QuantumType quantum_,
4281                                  const unsigned char *source_ )
4282 {
4283   QuantumInfo
4284     *quantum_info;
4285
4286   quantum_info=AcquireQuantumInfo(imageInfo(),image());
4287   ExceptionInfo exceptionInfo;
4288   GetExceptionInfo( &exceptionInfo );
4289   ImportQuantumPixels(image(),(MagickCore::CacheView *) NULL,quantum_info,
4290     quantum_,source_, &exceptionInfo);
4291   throwException( exceptionInfo );
4292   (void) DestroyExceptionInfo( &exceptionInfo );
4293   quantum_info=DestroyQuantumInfo(quantum_info);
4294 }
4295
4296 // Transfers one or more pixel components from the image pixel
4297 // cache to a buffer or file.
4298 // Used to support image encoders.
4299 void Magick::Image::writePixels ( const Magick::QuantumType quantum_,
4300                                   unsigned char *destination_ )
4301 {
4302   QuantumInfo
4303     *quantum_info;
4304
4305   quantum_info=AcquireQuantumInfo(imageInfo(),image());
4306   ExceptionInfo exceptionInfo;
4307   GetExceptionInfo( &exceptionInfo );
4308   ExportQuantumPixels(image(),(MagickCore::CacheView *) NULL,quantum_info,
4309     quantum_,destination_, &exceptionInfo);
4310   quantum_info=DestroyQuantumInfo(quantum_info);
4311   throwException( exceptionInfo );
4312   (void) DestroyExceptionInfo( &exceptionInfo );
4313 }
4314
4315 /////////////////////////////////////////////////////////////////////
4316 //
4317 // No end-user methods beyond this point
4318 //
4319 /////////////////////////////////////////////////////////////////////
4320
4321
4322 //
4323 // Construct using existing image and default options
4324 //
4325 Magick::Image::Image ( MagickCore::Image* image_ )
4326   : _imgRef(new ImageRef( image_))
4327 {
4328 }
4329
4330 // Get Magick::Options*
4331 Magick::Options* Magick::Image::options( void )
4332 {
4333   return _imgRef->options();
4334 }
4335 const Magick::Options* Magick::Image::constOptions( void ) const
4336 {
4337   return _imgRef->options();
4338 }
4339
4340 // Get MagickCore::Image*
4341 MagickCore::Image*& Magick::Image::image( void )
4342 {
4343   return _imgRef->image();
4344 }
4345 const MagickCore::Image* Magick::Image::constImage( void ) const
4346 {
4347   return _imgRef->image();
4348 }
4349
4350 // Get ImageInfo *
4351 MagickCore::ImageInfo* Magick::Image::imageInfo( void )
4352 {
4353   return _imgRef->options()->imageInfo();
4354 }
4355 const MagickCore::ImageInfo * Magick::Image::constImageInfo( void ) const
4356 {
4357   return _imgRef->options()->imageInfo();
4358 }
4359
4360 // Get QuantizeInfo *
4361 MagickCore::QuantizeInfo* Magick::Image::quantizeInfo( void )
4362 {
4363   return _imgRef->options()->quantizeInfo();
4364 }
4365 const MagickCore::QuantizeInfo * Magick::Image::constQuantizeInfo( void ) const
4366 {
4367   return _imgRef->options()->quantizeInfo();
4368 }
4369
4370 //
4371 // Replace current image
4372 //
4373 MagickCore::Image * Magick::Image::replaceImage
4374   ( MagickCore::Image* replacement_ )
4375 {
4376   MagickCore::Image* image;
4377   
4378   if( replacement_ )
4379     image = replacement_;
4380   else
4381     {
4382       ExceptionInfo exceptionInfo;
4383       GetExceptionInfo( &exceptionInfo );
4384       image = AcquireImage(constImageInfo(), &exceptionInfo);
4385       throwException( exceptionInfo );
4386       (void) DestroyExceptionInfo( &exceptionInfo );
4387     }
4388
4389   {
4390     Lock( &_imgRef->_mutexLock );
4391
4392     if ( _imgRef->_refCount == 1 )
4393       {
4394         // We own the image, just replace it, and de-register
4395         _imgRef->id( -1 );
4396         _imgRef->image(image);
4397       }
4398     else
4399       {
4400         // We don't own the image, dereference and replace with copy
4401         --_imgRef->_refCount;
4402         _imgRef = new ImageRef( image, constOptions() );
4403       }
4404   }
4405
4406   return _imgRef->_image;
4407 }
4408
4409 //
4410 // Prepare to modify image or image options
4411 // Replace current image and options with copy if reference count > 1
4412 //
4413 void Magick::Image::modifyImage( void )
4414 {
4415   {
4416     Lock( &_imgRef->_mutexLock );
4417     if ( _imgRef->_refCount == 1 )
4418       {
4419         // De-register image and return
4420         _imgRef->id( -1 );
4421         return;
4422       }
4423   }
4424
4425   ExceptionInfo exceptionInfo;
4426   GetExceptionInfo( &exceptionInfo );
4427   replaceImage( CloneImage( image(),
4428                             0, // columns
4429                             0, // rows
4430                             MagickTrue, // orphan
4431                             &exceptionInfo) );
4432   throwException( exceptionInfo );
4433   (void) DestroyExceptionInfo( &exceptionInfo );
4434   return;
4435 }
4436
4437 //
4438 // Test for an ImageMagick reported error and throw exception if one
4439 // has been reported.  Secretly resets image->exception back to default
4440 // state even though this method is const.
4441 //
4442 void Magick::Image::throwImageException( void ) const
4443 {
4444   // Throw C++ exception while resetting Image exception to default state
4445 }
4446
4447 // Register image with image registry or obtain registration id
4448 ssize_t Magick::Image::registerId( void )
4449 {
4450   Lock( &_imgRef->_mutexLock );
4451   if( _imgRef->id() < 0 )
4452     {
4453       char id[MaxTextExtent];
4454       ExceptionInfo exceptionInfo;
4455       GetExceptionInfo( &exceptionInfo );
4456       _imgRef->id(_imgRef->id()+1);
4457       sprintf(id,"%.20g\n",(double) _imgRef->id());
4458       SetImageRegistry(ImageRegistryType, id, image(), &exceptionInfo);
4459       throwException( exceptionInfo );
4460   (void) DestroyExceptionInfo( &exceptionInfo );
4461     }
4462   return _imgRef->id();
4463 }
4464
4465 // Unregister image from image registry
4466 void Magick::Image::unregisterId( void )
4467 {
4468   modifyImage();
4469   _imgRef->id( -1 );
4470 }
4471
4472 //
4473 // Create a local wrapper around MagickCoreTerminus
4474 //
4475 namespace Magick
4476 {
4477   extern "C" {
4478     void MagickPlusPlusDestroyMagick(void);
4479   }
4480 }
4481
4482 void Magick::MagickPlusPlusDestroyMagick(void)
4483 {
4484   if (magick_initialized)
4485     {
4486       magick_initialized=false;
4487       MagickCore::MagickCoreTerminus();
4488     }
4489 }
4490
4491 // C library initialization routine
4492 void MagickPPExport Magick::InitializeMagick(const char *path_)
4493 {
4494   MagickCore::MagickCoreGenesis(path_,MagickFalse);
4495   if (!magick_initialized)
4496     magick_initialized=true;
4497 }
4498
4499 //
4500 // Cleanup class to ensure that ImageMagick singletons are destroyed
4501 // so as to avoid any resemblence to a memory leak (which seems to
4502 // confuse users)
4503 //
4504 namespace Magick
4505 {
4506
4507   class MagickCleanUp
4508   {
4509   public:
4510     MagickCleanUp( void );
4511     ~MagickCleanUp( void );
4512   };
4513
4514   // The destructor for this object is invoked when the destructors for
4515   // static objects in this translation unit are invoked.
4516   static MagickCleanUp magickCleanUpGuard;
4517 }
4518
4519 Magick::MagickCleanUp::MagickCleanUp ( void )
4520 {
4521   // Don't even think about invoking InitializeMagick here!
4522 }
4523
4524 Magick::MagickCleanUp::~MagickCleanUp ( void )
4525 {
4526   MagickPlusPlusDestroyMagick();
4527 }