]> 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=(MagickRealType *) color_matrix_;
647   MagickCore::Image* newImage =
648     ColorMatrixImage( image(), kernel_info, &exceptionInfo );
649   kernel_info->values=(MagickRealType *) 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 // Sharpen pixels in image
1958 void Magick::Image::sharpen ( const double radius_, const double sigma_ )
1959 {
1960   ExceptionInfo exceptionInfo;
1961   GetExceptionInfo( &exceptionInfo );
1962   MagickCore::Image* newImage =
1963     SharpenImage( image(),
1964                   radius_,
1965                   sigma_,
1966                   image()->bias,
1967                   &exceptionInfo );
1968   replaceImage( newImage );
1969   throwException( exceptionInfo );
1970   (void) DestroyExceptionInfo( &exceptionInfo );
1971 }
1972
1973 void Magick::Image::sharpenChannel ( const ChannelType channel_,
1974                                      const double radius_, const double sigma_ )
1975 {
1976   ExceptionInfo exceptionInfo;
1977   GetExceptionInfo( &exceptionInfo );
1978   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
1979   MagickCore::Image* newImage =
1980     SharpenImage( image(),
1981                          radius_,
1982                          sigma_,
1983                   image()->bias,
1984                          &exceptionInfo );
1985   (void) SetPixelChannelMapMask( image(), channel_mask );
1986   replaceImage( newImage );
1987   throwException( exceptionInfo );
1988   (void) DestroyExceptionInfo( &exceptionInfo );
1989 }
1990
1991 // Shave pixels from image edges.
1992 void Magick::Image::shave ( const Geometry &geometry_ )
1993 {
1994   RectangleInfo shaveInfo = geometry_;
1995   ExceptionInfo exceptionInfo;
1996   GetExceptionInfo( &exceptionInfo );
1997   MagickCore::Image* newImage =
1998     ShaveImage( image(),
1999                &shaveInfo,
2000                &exceptionInfo);
2001   replaceImage( newImage );
2002   throwException( exceptionInfo );
2003   (void) DestroyExceptionInfo( &exceptionInfo );
2004 }
2005
2006 // Shear image
2007 void Magick::Image::shear ( const double xShearAngle_,
2008                             const double yShearAngle_ )
2009 {
2010   ExceptionInfo exceptionInfo;
2011   GetExceptionInfo( &exceptionInfo );
2012   MagickCore::Image* newImage =
2013     ShearImage( image(),
2014                 xShearAngle_,
2015                 yShearAngle_,
2016                 &exceptionInfo );
2017   replaceImage( newImage );
2018   throwException( exceptionInfo );
2019   (void) DestroyExceptionInfo( &exceptionInfo );
2020 }
2021
2022 // Contrast image
2023 void Magick::Image::sigmoidalContrast ( const size_t sharpen_, const double contrast, const double midpoint )
2024 {
2025   ExceptionInfo exceptionInfo;
2026   GetExceptionInfo( &exceptionInfo );
2027   modifyImage();
2028   (void) SigmoidalContrastImage( image(), (MagickBooleanType) sharpen_, contrast, midpoint, &exceptionInfo );
2029   throwException( exceptionInfo );
2030   (void) DestroyExceptionInfo( &exceptionInfo );
2031 }
2032
2033 // Solarize image (similar to effect seen when exposing a photographic
2034 // film to light during the development process)
2035 void Magick::Image::solarize ( const double factor_ )
2036 {
2037   ExceptionInfo exceptionInfo;
2038   GetExceptionInfo( &exceptionInfo );
2039   modifyImage();
2040   SolarizeImage ( image(), factor_, &exceptionInfo );
2041   throwException( exceptionInfo );
2042   (void) DestroyExceptionInfo( &exceptionInfo );
2043 }
2044
2045 // Sparse color image, given a set of coordinates, interpolates the colors
2046 // found at those coordinates, across the whole image, using various methods.
2047 //
2048 void Magick::Image::sparseColor ( const ChannelType channel,
2049                                   const SparseColorMethod method,
2050                                   const size_t number_arguments,
2051                                   const double *arguments )
2052 {
2053   ExceptionInfo exceptionInfo;
2054   GetExceptionInfo( &exceptionInfo );
2055
2056   ChannelType channel_mask = SetPixelChannelMask( image(), channel );
2057   MagickCore::Image* newImage = SparseColorImage ( image(), method,
2058     number_arguments, arguments, &exceptionInfo );
2059   (void) SetPixelChannelMapMask( image(), channel_mask );
2060   replaceImage( newImage );
2061   throwException( exceptionInfo );
2062   (void) DestroyExceptionInfo( &exceptionInfo );
2063 }
2064
2065 // Spread pixels randomly within image by specified ammount
2066 void Magick::Image::spread ( const size_t amount_ )
2067 {
2068   ExceptionInfo exceptionInfo;
2069   GetExceptionInfo( &exceptionInfo );
2070   MagickCore::Image* newImage =
2071     SpreadImage( image(),
2072                  amount_,
2073                  image()->interpolate,
2074                  &exceptionInfo );
2075   replaceImage( newImage );
2076   throwException( exceptionInfo );
2077   (void) DestroyExceptionInfo( &exceptionInfo );
2078 }
2079
2080 // Add a digital watermark to the image (based on second image)
2081 void Magick::Image::stegano ( const Image &watermark_ )
2082 {
2083   ExceptionInfo exceptionInfo;
2084   GetExceptionInfo( &exceptionInfo );
2085   MagickCore::Image* newImage =
2086     SteganoImage( image(),
2087                   watermark_.constImage(),
2088                   &exceptionInfo);
2089   replaceImage( newImage );
2090   throwException( exceptionInfo );
2091   (void) DestroyExceptionInfo( &exceptionInfo );
2092 }
2093
2094 // Stereo image (left image is current image)
2095 void Magick::Image::stereo ( const Image &rightImage_ )
2096 {
2097   ExceptionInfo exceptionInfo;
2098   GetExceptionInfo( &exceptionInfo );
2099   MagickCore::Image* newImage =
2100     StereoImage( image(),
2101                  rightImage_.constImage(),
2102                  &exceptionInfo);
2103   replaceImage( newImage );
2104   throwException( exceptionInfo );
2105   (void) DestroyExceptionInfo( &exceptionInfo );
2106 }
2107
2108 // Swirl image
2109 void Magick::Image::swirl ( const double degrees_ )
2110 {
2111   ExceptionInfo exceptionInfo;
2112   GetExceptionInfo( &exceptionInfo );
2113   MagickCore::Image* newImage =
2114     SwirlImage( image(), degrees_, image()->interpolate,
2115                 &exceptionInfo);
2116   replaceImage( newImage );
2117   throwException( exceptionInfo );
2118   (void) DestroyExceptionInfo( &exceptionInfo );
2119 }
2120
2121 // Texture image
2122 void Magick::Image::texture ( const Image &texture_ )
2123 {
2124   modifyImage();
2125   ExceptionInfo exceptionInfo;
2126   GetExceptionInfo( &exceptionInfo );
2127   TextureImage( image(), texture_.constImage(), &exceptionInfo );
2128   throwException( exceptionInfo );
2129   (void) DestroyExceptionInfo( &exceptionInfo );
2130 }
2131
2132 // Threshold image
2133 void Magick::Image::threshold ( const double threshold_ )
2134 {
2135   modifyImage();
2136   ExceptionInfo exceptionInfo;
2137   GetExceptionInfo( &exceptionInfo );
2138   BilevelImage( image(), threshold_, &exceptionInfo );
2139   throwException( exceptionInfo );
2140   (void) DestroyExceptionInfo( &exceptionInfo );
2141 }
2142
2143 // Transform image based on image geometry only
2144 void Magick::Image::transform ( const Geometry &imageGeometry_ )
2145 {
2146   modifyImage();
2147   ExceptionInfo exceptionInfo;
2148   GetExceptionInfo( &exceptionInfo );
2149   TransformImage ( &(image()), 0,
2150                    std::string(imageGeometry_).c_str(), &exceptionInfo );
2151   throwException( exceptionInfo );
2152   (void) DestroyExceptionInfo( &exceptionInfo );
2153 }
2154 // Transform image based on image and crop geometries
2155 void Magick::Image::transform ( const Geometry &imageGeometry_,
2156                                 const Geometry &cropGeometry_ )
2157 {
2158   modifyImage();
2159   ExceptionInfo exceptionInfo;
2160   GetExceptionInfo( &exceptionInfo );
2161   TransformImage ( &(image()), std::string(cropGeometry_).c_str(),
2162                    std::string(imageGeometry_).c_str(), &exceptionInfo );
2163   throwException( exceptionInfo );
2164   (void) DestroyExceptionInfo( &exceptionInfo );
2165 }
2166
2167 // Add matte image to image, setting pixels matching color to transparent
2168 void Magick::Image::transparent ( const Color &color_ )
2169 {
2170   if ( !color_.isValid() )
2171   {
2172     throwExceptionExplicit( OptionError,
2173                             "Color argument is invalid" );
2174   }
2175
2176   std::string color = color_;
2177
2178   PixelInfo target;
2179   ExceptionInfo exceptionInfo;
2180   GetExceptionInfo( &exceptionInfo );
2181   (void) QueryColorCompliance(std::string(color_).c_str(),AllCompliance,
2182     &target,&exceptionInfo);
2183   modifyImage();
2184   TransparentPaintImage ( image(), &target, TransparentAlpha, MagickFalse,
2185     &exceptionInfo );
2186   throwException( exceptionInfo );
2187   (void) DestroyExceptionInfo( &exceptionInfo );
2188 }
2189
2190 // Add matte image to image, setting pixels matching color to transparent
2191 void Magick::Image::transparentChroma(const Color &colorLow_,
2192   const Color &colorHigh_)
2193 {
2194   if ( !colorLow_.isValid() || !colorHigh_.isValid() )
2195   {
2196     throwExceptionExplicit( OptionError,
2197                             "Color argument is invalid" );
2198   }
2199
2200   std::string colorLow = colorLow_;
2201   std::string colorHigh = colorHigh_;
2202
2203   PixelInfo targetLow;
2204   PixelInfo targetHigh;
2205   ExceptionInfo exceptionInfo;
2206   GetExceptionInfo( &exceptionInfo );
2207   (void) QueryColorCompliance(std::string(colorLow_).c_str(),
2208     AllCompliance,&targetLow,&exceptionInfo);
2209   (void) QueryColorCompliance(std::string(colorHigh_).c_str(),
2210     AllCompliance,&targetHigh,&exceptionInfo);
2211   modifyImage();
2212   TransparentPaintImageChroma ( image(), &targetLow, &targetHigh,
2213     TransparentAlpha, MagickFalse, &exceptionInfo );
2214   throwException( exceptionInfo );
2215   (void) DestroyExceptionInfo( &exceptionInfo );
2216 }
2217
2218
2219 // Trim edges that are the background color from the image
2220 void Magick::Image::trim ( void )
2221 {
2222   ExceptionInfo exceptionInfo;
2223   GetExceptionInfo( &exceptionInfo );
2224   MagickCore::Image* newImage =
2225     TrimImage( image(), &exceptionInfo);
2226   replaceImage( newImage );
2227   throwException( exceptionInfo );
2228   (void) DestroyExceptionInfo( &exceptionInfo );
2229 }
2230
2231 // Replace image with a sharpened version of the original image
2232 // using the unsharp mask algorithm.
2233 //  radius_
2234 //    the radius of the Gaussian, in pixels, not counting the
2235 //    center pixel.
2236 //  sigma_
2237 //    the standard deviation of the Gaussian, in pixels.
2238 //  amount_
2239 //    the percentage of the difference between the original and
2240 //    the blur image that is added back into the original.
2241 // threshold_
2242 //   the threshold in pixels needed to apply the diffence amount.
2243 void Magick::Image::unsharpmask ( const double radius_,
2244                                   const double sigma_,
2245                                   const double amount_,
2246                                   const double threshold_ )
2247 {
2248   ExceptionInfo exceptionInfo;
2249   GetExceptionInfo( &exceptionInfo );
2250   MagickCore::Image* newImage =
2251     UnsharpMaskImage( image(),
2252                       radius_,
2253                       sigma_,
2254                       amount_,
2255                       threshold_,
2256                       &exceptionInfo );
2257   replaceImage( newImage );
2258   throwException( exceptionInfo );
2259   (void) DestroyExceptionInfo( &exceptionInfo );
2260 }
2261
2262 void Magick::Image::unsharpmaskChannel ( const ChannelType channel_,
2263                                          const double radius_,
2264                                          const double sigma_,
2265                                          const double amount_,
2266                                          const double threshold_ )
2267 {
2268   ExceptionInfo exceptionInfo;
2269   GetExceptionInfo( &exceptionInfo );
2270   ChannelType channel_mask = SetPixelChannelMask( image(), channel_ );
2271   MagickCore::Image* newImage =
2272     UnsharpMaskImage( image(),
2273                              radius_,
2274                              sigma_,
2275                              amount_,
2276                              threshold_,
2277                              &exceptionInfo );
2278   (void) SetPixelChannelMapMask( image(), channel_mask );
2279   replaceImage( newImage );
2280   throwException( exceptionInfo );
2281   (void) DestroyExceptionInfo( &exceptionInfo );
2282 }
2283
2284 // Map image pixels to a sine wave
2285 void Magick::Image::wave ( const double amplitude_, const double wavelength_ )
2286 {
2287   ExceptionInfo exceptionInfo;
2288   GetExceptionInfo( &exceptionInfo );
2289   MagickCore::Image* newImage =
2290     WaveImage( image(),
2291                amplitude_,
2292                wavelength_,
2293                image()->interpolate,
2294                &exceptionInfo);
2295   replaceImage( newImage );
2296   throwException( exceptionInfo );
2297   (void) DestroyExceptionInfo( &exceptionInfo );
2298 }
2299
2300 // Write image to file
2301 void Magick::Image::write( const std::string &imageSpec_ )
2302 {
2303   ExceptionInfo exceptionInfo;
2304   GetExceptionInfo( &exceptionInfo );
2305   modifyImage();
2306   fileName( imageSpec_ );
2307   WriteImage( imageInfo(), image(), &exceptionInfo );
2308   throwException( exceptionInfo );
2309   (void) DestroyExceptionInfo( &exceptionInfo );
2310 }
2311
2312 // Write image to in-memory BLOB
2313 void Magick::Image::write ( Blob *blob_ )
2314 {
2315   modifyImage();
2316   size_t length = 2048; // Efficient size for small images
2317   ExceptionInfo exceptionInfo;
2318   GetExceptionInfo( &exceptionInfo );
2319   void* data = ImageToBlob( imageInfo(),
2320                             image(),
2321                             &length,
2322                             &exceptionInfo);
2323   throwException( exceptionInfo );
2324   blob_->updateNoCopy( data, length, Blob::MallocAllocator );
2325   throwImageException();
2326   (void) DestroyExceptionInfo( &exceptionInfo );
2327 }
2328 void Magick::Image::write ( Blob *blob_,
2329                             const std::string &magick_ )
2330 {
2331   modifyImage();
2332   magick(magick_);
2333   size_t length = 2048; // Efficient size for small images
2334   ExceptionInfo exceptionInfo;
2335   GetExceptionInfo( &exceptionInfo );
2336   void* data = ImageToBlob( imageInfo(),
2337                             image(),
2338                             &length,
2339                             &exceptionInfo);
2340   throwException( exceptionInfo );
2341   blob_->updateNoCopy( data, length, Blob::MallocAllocator );
2342   throwImageException();
2343   (void) DestroyExceptionInfo( &exceptionInfo );
2344 }
2345 void Magick::Image::write ( Blob *blob_,
2346                             const std::string &magick_,
2347                             const size_t depth_ )
2348 {
2349   modifyImage();
2350   magick(magick_);
2351   depth(depth_);
2352   size_t length = 2048; // Efficient size for small images
2353   ExceptionInfo exceptionInfo;
2354   GetExceptionInfo( &exceptionInfo );
2355   void* data = ImageToBlob( imageInfo(),
2356                             image(),
2357                             &length,
2358                             &exceptionInfo);
2359   throwException( exceptionInfo );
2360   blob_->updateNoCopy( data, length, Blob::MallocAllocator );
2361   throwImageException();
2362   (void) DestroyExceptionInfo( &exceptionInfo );
2363 }
2364
2365 // Write image to an array of pixels with storage type specified
2366 // by user (ExportImagePixels), e.g.
2367 // image.write( 0, 0, 640, 1, "RGB", 0, pixels );
2368 void Magick::Image::write ( const ssize_t x_,
2369                             const ssize_t y_,
2370                             const size_t columns_,
2371                             const size_t rows_,
2372                             const std::string &map_,
2373                             const StorageType type_,
2374                             void *pixels_ )
2375 {
2376   ExceptionInfo exceptionInfo;
2377   GetExceptionInfo( &exceptionInfo );
2378   ExportImagePixels( image(), x_, y_, columns_, rows_, map_.c_str(), type_,
2379                  pixels_,
2380     &exceptionInfo);
2381   throwException( exceptionInfo );
2382   (void) DestroyExceptionInfo( &exceptionInfo );
2383 }
2384
2385 // Zoom image
2386 void Magick::Image::zoom( const Geometry &geometry_ )
2387 {
2388   // Calculate new size.  This code should be supported using binary arguments
2389   // in the ImageMagick library.
2390   ssize_t x = 0;
2391   ssize_t y = 0;
2392   size_t width = columns();
2393   size_t height = rows();
2394
2395   ParseMetaGeometry (static_cast<std::string>(geometry_).c_str(),
2396                      &x, &y,
2397                      &width, &height );
2398
2399   ExceptionInfo exceptionInfo;
2400   GetExceptionInfo( &exceptionInfo );
2401   MagickCore::Image* newImage =
2402     ResizeImage( image(),
2403                width,
2404                height,
2405                image()->filter,
2406                image()->blur,
2407                &exceptionInfo);
2408   replaceImage( newImage );
2409   throwException( exceptionInfo );
2410   (void) DestroyExceptionInfo( &exceptionInfo );
2411 }
2412
2413 /*
2414  * Methods for setting image attributes
2415  *
2416  */
2417
2418 // Join images into a single multi-image file
2419 void Magick::Image::adjoin ( const bool flag_ )
2420 {
2421   modifyImage();
2422   options()->adjoin( flag_ );
2423 }
2424 bool Magick::Image::adjoin ( void ) const
2425 {
2426   return constOptions()->adjoin();
2427 }
2428
2429 // Remove pixel aliasing
2430 void Magick::Image::antiAlias( const bool flag_ )
2431 {
2432   modifyImage();
2433   options()->antiAlias( static_cast<size_t>(flag_) );
2434 }
2435 bool Magick::Image::antiAlias( void )
2436 {
2437   return static_cast<bool>( options()->antiAlias( ) );
2438 }
2439
2440 // Animation inter-frame delay
2441 void Magick::Image::animationDelay ( const size_t delay_ )
2442 {
2443   modifyImage();
2444   image()->delay = delay_;
2445 }
2446 size_t Magick::Image::animationDelay ( void ) const
2447 {
2448   return constImage()->delay;
2449 }
2450
2451 // Number of iterations to play animation
2452 void Magick::Image::animationIterations ( const size_t iterations_ )
2453 {
2454   modifyImage();
2455   image()->iterations = iterations_;
2456 }
2457 size_t Magick::Image::animationIterations ( void ) const
2458 {
2459   return constImage()->iterations;
2460 }
2461
2462 // Access/Update a named image attribute
2463 void Magick::Image::attribute ( const std::string name_,
2464                                 const std::string value_ )
2465 {
2466   modifyImage();
2467   ExceptionInfo exceptionInfo;
2468   GetExceptionInfo( &exceptionInfo );
2469   SetImageProperty( image(), name_.c_str(), value_.c_str(), &exceptionInfo );
2470   throwException( exceptionInfo );
2471   (void) DestroyExceptionInfo( &exceptionInfo );
2472 }
2473 std::string Magick::Image::attribute ( const std::string name_ )
2474 {
2475   ExceptionInfo exceptionInfo;
2476   GetExceptionInfo( &exceptionInfo );
2477   const char *value = GetImageProperty( constImage(), name_.c_str(),
2478     &exceptionInfo );
2479   throwException( exceptionInfo );
2480   (void) DestroyExceptionInfo( &exceptionInfo );
2481
2482   if ( value )
2483     return std::string( value );
2484
2485   return std::string(); // Intentionally no exception
2486 }
2487
2488 // Background color
2489 void Magick::Image::backgroundColor ( const Color &backgroundColor_ )
2490 {
2491   modifyImage();
2492
2493   if ( backgroundColor_.isValid() )
2494     {
2495       image()->background_color = backgroundColor_;
2496     }
2497   else
2498     {
2499       image()->background_color = Color();
2500     }
2501
2502   options()->backgroundColor( backgroundColor_ );
2503 }
2504 Magick::Color Magick::Image::backgroundColor ( void ) const
2505 {
2506   return constOptions()->backgroundColor( );
2507 }
2508
2509 // Background fill texture
2510 void Magick::Image::backgroundTexture ( const std::string &backgroundTexture_ )
2511 {
2512   modifyImage();
2513   options()->backgroundTexture( backgroundTexture_ );
2514 }
2515 std::string Magick::Image::backgroundTexture ( void ) const
2516 {
2517   return constOptions()->backgroundTexture( );
2518 }
2519
2520 // Original image columns
2521 size_t Magick::Image::baseColumns ( void ) const
2522 {
2523   return constImage()->magick_columns;
2524 }
2525
2526 // Original image name
2527 std::string Magick::Image::baseFilename ( void ) const
2528 {
2529   return std::string(constImage()->magick_filename);
2530 }
2531
2532 // Original image rows
2533 size_t Magick::Image::baseRows ( void ) const
2534 {
2535   return constImage()->magick_rows;
2536 }
2537
2538 // Border color
2539 void Magick::Image::borderColor ( const Color &borderColor_ )
2540 {
2541   modifyImage();
2542
2543   if ( borderColor_.isValid() )
2544     {
2545       image()->border_color = borderColor_;
2546     }
2547   else
2548     {
2549       image()->border_color = Color();
2550     }
2551
2552   options()->borderColor( borderColor_ );
2553 }
2554 Magick::Color Magick::Image::borderColor ( void ) const
2555 {
2556   return constOptions()->borderColor( );
2557 }
2558
2559 // Return smallest bounding box enclosing non-border pixels. The
2560 // current fuzz value is used when discriminating between pixels.
2561 // This is the crop bounding box used by crop(Geometry(0,0));
2562 Magick::Geometry Magick::Image::boundingBox ( void ) const
2563 {
2564   ExceptionInfo exceptionInfo;
2565   GetExceptionInfo( &exceptionInfo );
2566   RectangleInfo bbox = GetImageBoundingBox( constImage(), &exceptionInfo);
2567   throwException( exceptionInfo );
2568   (void) DestroyExceptionInfo( &exceptionInfo );
2569   return Geometry( bbox );
2570 }
2571
2572 // Text bounding-box base color
2573 void Magick::Image::boxColor ( const Color &boxColor_ )
2574 {
2575   modifyImage();
2576   options()->boxColor( boxColor_ );
2577 }
2578 Magick::Color Magick::Image::boxColor ( void ) const
2579 {
2580   return constOptions()->boxColor( );
2581 }
2582
2583 // Pixel cache threshold.  Once this threshold is exceeded, all
2584 // subsequent pixels cache operations are to/from disk.
2585 // This setting is shared by all Image objects.
2586 /* static */
2587 void Magick::Image::cacheThreshold ( const size_t threshold_ )
2588 {
2589   SetMagickResourceLimit( MemoryResource, threshold_ );
2590 }
2591
2592 void Magick::Image::chromaBluePrimary ( const double x_, const double y_ )
2593 {
2594   modifyImage();
2595   image()->chromaticity.blue_primary.x = x_;
2596   image()->chromaticity.blue_primary.y = y_;
2597 }
2598 void Magick::Image::chromaBluePrimary ( double *x_, double *y_ ) const
2599 {
2600   *x_ = constImage()->chromaticity.blue_primary.x;
2601   *y_ = constImage()->chromaticity.blue_primary.y;
2602 }
2603
2604 void Magick::Image::chromaGreenPrimary ( const double x_, const double y_ )
2605 {
2606   modifyImage();
2607   image()->chromaticity.green_primary.x = x_;
2608   image()->chromaticity.green_primary.y = y_;
2609 }
2610 void Magick::Image::chromaGreenPrimary ( double *x_, double *y_ ) const
2611 {
2612   *x_ = constImage()->chromaticity.green_primary.x;
2613   *y_ = constImage()->chromaticity.green_primary.y;
2614 }
2615
2616 void Magick::Image::chromaRedPrimary ( const double x_, const double y_ )
2617 {
2618   modifyImage();
2619   image()->chromaticity.red_primary.x = x_;
2620   image()->chromaticity.red_primary.y = y_;
2621 }
2622 void Magick::Image::chromaRedPrimary ( double *x_, double *y_ ) const
2623 {
2624   *x_ = constImage()->chromaticity.red_primary.x;
2625   *y_ = constImage()->chromaticity.red_primary.y;
2626 }
2627
2628 void Magick::Image::chromaWhitePoint ( const double x_, const double y_ )
2629 {
2630   modifyImage();
2631   image()->chromaticity.white_point.x = x_;
2632   image()->chromaticity.white_point.y = y_;
2633 }
2634 void Magick::Image::chromaWhitePoint ( double *x_, double *y_ ) const
2635 {
2636   *x_ = constImage()->chromaticity.white_point.x;
2637   *y_ = constImage()->chromaticity.white_point.y;
2638 }
2639
2640 // Set image storage class
2641 void Magick::Image::classType ( const ClassType class_ )
2642 {
2643   if ( classType() == PseudoClass && class_ == DirectClass )
2644     {
2645       // Use SyncImage to synchronize the DirectClass pixels with the
2646       // color map and then set to DirectClass type.
2647       modifyImage();
2648       ExceptionInfo exceptionInfo;
2649       GetExceptionInfo( &exceptionInfo );
2650       SyncImage( image(), &exceptionInfo );
2651       throwException( exceptionInfo );
2652       (void) DestroyExceptionInfo( &exceptionInfo );
2653       image()->colormap = (PixelInfo *)
2654         RelinquishMagickMemory( image()->colormap );
2655       image()->storage_class = static_cast<MagickCore::ClassType>(DirectClass);
2656       return;
2657     }
2658
2659   if ( classType() == DirectClass && class_ == PseudoClass )
2660     {
2661       // Quantize to create PseudoClass color map
2662       modifyImage();
2663       quantizeColors(MaxColormapSize);
2664       quantize();
2665       image()->storage_class = static_cast<MagickCore::ClassType>(PseudoClass);
2666     }
2667 }
2668
2669 // Associate a clip mask with the image. The clip mask must be the
2670 // same dimensions as the image. Pass an invalid image to unset an
2671 // existing clip mask.
2672 void Magick::Image::clipMask ( const Magick::Image & clipMask_ )
2673 {
2674   modifyImage();
2675
2676   ExceptionInfo exceptionInfo;
2677   GetExceptionInfo( &exceptionInfo );
2678   if( clipMask_.isValid() )
2679     {
2680       // Set clip mask
2681       SetImageMask( image(), clipMask_.constImage(), &exceptionInfo );
2682     }
2683   else
2684     {
2685       // Unset existing clip mask
2686       SetImageMask( image(), 0, &exceptionInfo );
2687     }
2688    throwException( exceptionInfo );
2689    (void) DestroyExceptionInfo( &exceptionInfo );
2690 }
2691 Magick::Image Magick::Image::clipMask ( void  ) const
2692 {
2693    ExceptionInfo exceptionInfo;
2694    GetExceptionInfo( &exceptionInfo );
2695    MagickCore::Image* image = GetImageMask( constImage(), &exceptionInfo );
2696    throwException( exceptionInfo );
2697    (void) DestroyExceptionInfo( &exceptionInfo );
2698    return Magick::Image( image );
2699 }
2700
2701 void Magick::Image::colorFuzz ( const double fuzz_ )
2702 {
2703   modifyImage();
2704   image()->fuzz = fuzz_;
2705   options()->colorFuzz( fuzz_ );
2706 }
2707 double Magick::Image::colorFuzz ( void ) const
2708 {
2709   return constOptions()->colorFuzz( );
2710 }
2711
2712 // Set color in colormap at index
2713 void Magick::Image::colorMap ( const size_t index_,
2714                                const Color &color_ )
2715 {
2716   MagickCore::Image* imageptr = image();
2717
2718   if (index_ > (MaxColormapSize-1) )
2719     throwExceptionExplicit( OptionError,
2720                             "Colormap index must be less than MaxColormapSize" );
2721   
2722   if ( !color_.isValid() )
2723     throwExceptionExplicit( OptionError,
2724                             "Color argument is invalid");
2725   modifyImage();
2726
2727   // Ensure that colormap size is large enough
2728   if ( colorMapSize() < (index_+1) )
2729     colorMapSize( index_ + 1 );
2730
2731   // Set color at index in colormap
2732   (imageptr->colormap)[index_] = color_;
2733 }
2734 // Return color in colormap at index
2735 Magick::Color Magick::Image::colorMap ( const size_t index_ ) const
2736 {
2737   const MagickCore::Image* imageptr = constImage();
2738
2739   if ( !imageptr->colormap )
2740     throwExceptionExplicit( OptionError,
2741                             "Image does not contain a colormap");
2742
2743   if ( index_ > imageptr->colors-1 )
2744     throwExceptionExplicit( OptionError,
2745                             "Index out of range");
2746
2747   return Magick::Color( (imageptr->colormap)[index_] );
2748 }
2749
2750 // Colormap size (number of colormap entries)
2751 void Magick::Image::colorMapSize ( const size_t entries_ )
2752 {
2753   if (entries_ >MaxColormapSize )
2754     throwExceptionExplicit( OptionError,
2755                             "Colormap entries must not exceed MaxColormapSize" );
2756
2757   modifyImage();
2758
2759   MagickCore::Image* imageptr = image();
2760
2761   if( !imageptr->colormap )
2762     {
2763       // Allocate colormap
2764       imageptr->colormap =
2765         static_cast<PixelInfo*>(AcquireMagickMemory(entries_*sizeof(PixelInfo)));
2766       imageptr->colors = 0;
2767     }
2768   else if ( entries_ > imageptr->colors )
2769     {
2770       // Re-allocate colormap
2771       imageptr->colormap=(PixelInfo *)
2772         ResizeMagickMemory(imageptr->colormap,(entries_)*sizeof(PixelInfo));
2773     }
2774
2775   // Initialize any new colormap entries as all black
2776   Color black(0,0,0);
2777   for( size_t i=imageptr->colors; i<(entries_-1); i++ )
2778     (imageptr->colormap)[i] = black;
2779
2780   imageptr->colors = entries_;
2781 }
2782 size_t Magick::Image::colorMapSize ( void )
2783 {
2784   const MagickCore::Image* imageptr = constImage();
2785
2786   if ( !imageptr->colormap )
2787     throwExceptionExplicit( OptionError,
2788                             "Image does not contain a colormap");
2789
2790   return imageptr->colors;
2791 }
2792
2793 // Image colorspace
2794 void Magick::Image::colorSpace( const ColorspaceType colorSpace_ )
2795 {
2796   // Nothing to do?
2797   if ( image()->colorspace == colorSpace_ )
2798     return;
2799
2800   modifyImage();
2801
2802   ExceptionInfo exceptionInfo;
2803   GetExceptionInfo( &exceptionInfo );
2804   if ( colorSpace_ != RGBColorspace &&
2805        colorSpace_ != sRGBColorspace &&
2806        colorSpace_ != TransparentColorspace &&
2807        colorSpace_ != GRAYColorspace )
2808     {
2809       if (image()->colorspace != RGBColorspace &&
2810           image()->colorspace != sRGBColorspace &&
2811           image()->colorspace != TransparentColorspace &&
2812           image()->colorspace != GRAYColorspace)
2813         {
2814           /* Transform to RGB colorspace as intermediate step */
2815           TransformRGBImage( image(), image()->colorspace, &exceptionInfo );
2816           throwImageException();
2817         }
2818       /* Transform to final non-RGB colorspace */
2819       RGBTransformImage( image(), colorSpace_, &exceptionInfo );
2820       throwException( exceptionInfo );
2821       (void) DestroyExceptionInfo( &exceptionInfo );
2822       return;
2823     }
2824
2825   if ( colorSpace_ == RGBColorspace ||
2826        colorSpace_ == sRGBColorspace ||
2827        colorSpace_ == TransparentColorspace ||
2828        colorSpace_ == GRAYColorspace )
2829     {
2830       /* Transform to a RGB-type colorspace */
2831       TransformRGBImage( image(), image()->colorspace, &exceptionInfo );
2832       throwException( exceptionInfo );
2833       (void) DestroyExceptionInfo( &exceptionInfo );
2834       return;
2835     }
2836   throwException( exceptionInfo );
2837   (void) DestroyExceptionInfo( &exceptionInfo );
2838 }
2839 Magick::ColorspaceType Magick::Image::colorSpace ( void ) const
2840 {
2841   return constImage()->colorspace;
2842 }
2843
2844 // Set image colorspace type.
2845 void Magick::Image::colorspaceType( const ColorspaceType colorSpace_ )
2846 {
2847   modifyImage();
2848   options()->colorspaceType( colorSpace_ );
2849 }
2850 Magick::ColorspaceType Magick::Image::colorspaceType ( void ) const
2851 {
2852   return constOptions()->colorspaceType();
2853 }
2854
2855
2856 // Comment string
2857 void Magick::Image::comment ( const std::string &comment_ )
2858 {
2859   modifyImage();
2860   ExceptionInfo exceptionInfo;
2861   GetExceptionInfo( &exceptionInfo );
2862   SetImageProperty( image(), "Comment", NULL, &exceptionInfo );
2863   if ( comment_.length() > 0 )
2864     SetImageProperty( image(), "Comment", comment_.c_str(), &exceptionInfo );
2865   throwException( exceptionInfo );
2866   (void) DestroyExceptionInfo( &exceptionInfo );
2867 }
2868 std::string Magick::Image::comment ( void ) const
2869 {
2870   ExceptionInfo exceptionInfo;
2871   GetExceptionInfo( &exceptionInfo );
2872   const char *value = GetImageProperty( constImage(), "Comment",
2873     &exceptionInfo );
2874   throwException( exceptionInfo );
2875   (void) DestroyExceptionInfo( &exceptionInfo );
2876
2877   if ( value )
2878     return std::string( value );
2879
2880   return std::string(); // Intentionally no exception
2881 }
2882
2883 // Composition operator to be used when composition is implicitly used
2884 // (such as for image flattening).
2885 void Magick::Image::compose (const CompositeOperator compose_)
2886 {
2887   image()->compose=compose_;
2888 }
2889
2890 Magick::CompositeOperator Magick::Image::compose ( void ) const
2891 {
2892   return constImage()->compose;
2893 }
2894
2895 // Compression algorithm
2896 void Magick::Image::compressType ( const CompressionType compressType_ )
2897 {
2898   modifyImage();
2899   image()->compression = compressType_;
2900   options()->compressType( compressType_ );
2901 }
2902 Magick::CompressionType Magick::Image::compressType ( void ) const
2903 {
2904   return constImage()->compression;
2905 }
2906
2907 // Enable printing of debug messages from ImageMagick
2908 void Magick::Image::debug ( const bool flag_ )
2909 {
2910   modifyImage();
2911   options()->debug( flag_ );
2912 }
2913 bool Magick::Image::debug ( void ) const
2914 {
2915   return constOptions()->debug();
2916 }
2917
2918 // Tagged image format define (set/access coder-specific option) The
2919 // magick_ option specifies the coder the define applies to.  The key_
2920 // option provides the key specific to that coder.  The value_ option
2921 // provides the value to set (if any). See the defineSet() method if the
2922 // key must be removed entirely.
2923 void Magick::Image::defineValue ( const std::string &magick_,
2924                                   const std::string &key_,
2925                                   const std::string &value_ )
2926 {
2927   modifyImage();
2928   std::string format = magick_ + ":" + key_;
2929   std::string option = value_;
2930   (void) SetImageOption ( imageInfo(), format.c_str(), option.c_str() );
2931 }
2932 std::string Magick::Image::defineValue ( const std::string &magick_,
2933                                          const std::string &key_ ) const
2934 {
2935   std::string definition = magick_ + ":" + key_;
2936   const char *option =
2937     GetImageOption ( constImageInfo(), definition.c_str() );
2938   if (option)
2939     return std::string( option );
2940   return std::string( );
2941 }
2942
2943 // Tagged image format define. Similar to the defineValue() method
2944 // except that passing the flag_ value 'true' creates a value-less
2945 // define with that format and key. Passing the flag_ value 'false'
2946 // removes any existing matching definition. The method returns 'true'
2947 // if a matching key exists, and 'false' if no matching key exists.
2948 void Magick::Image::defineSet ( const std::string &magick_,
2949                                 const std::string &key_,
2950                                 bool flag_ )
2951 {
2952   modifyImage();
2953   std::string definition = magick_ + ":" + key_;
2954   if (flag_)
2955     {
2956       (void) SetImageOption ( imageInfo(), definition.c_str(),  "" );
2957     }
2958   else
2959     {
2960       DeleteImageOption( imageInfo(), definition.c_str() );
2961     }
2962 }
2963 bool Magick::Image::defineSet ( const std::string &magick_,
2964                                 const std::string &key_ ) const
2965 {
2966   std::string key = magick_ + ":" + key_;
2967   const char *option =
2968     GetImageOption ( constImageInfo(), key.c_str() );
2969   if (option)
2970     return true;
2971   return false;
2972 }
2973
2974 // Pixel resolution
2975 void Magick::Image::density ( const Geometry &density_ )
2976 {
2977   modifyImage();
2978   options()->density( density_ );
2979   if ( density_.isValid() )
2980     {
2981       image()->resolution.x = density_.width();
2982       if ( density_.height() != 0 )
2983         {
2984           image()->resolution.y = density_.height();
2985         }
2986       else
2987         {
2988           image()->resolution.y = density_.width();
2989         }
2990     }
2991   else
2992     {
2993       // Reset to default
2994       image()->resolution.x = 0;
2995       image()->resolution.y = 0;
2996     }
2997 }
2998 Magick::Geometry Magick::Image::density ( void ) const
2999 {
3000   if (isValid())
3001     {
3002       ssize_t x_resolution=72;
3003       ssize_t y_resolution=72;
3004
3005       if (constImage()->resolution.x > 0.0)
3006         x_resolution=static_cast<ssize_t>(constImage()->resolution.x + 0.5);
3007
3008       if (constImage()->resolution.y > 0.0)
3009         y_resolution=static_cast<ssize_t>(constImage()->resolution.y + 0.5);
3010
3011       return Geometry(x_resolution,y_resolution);
3012     }
3013
3014   return constOptions()->density( );
3015 }
3016
3017 // Image depth (bits allocated to red/green/blue components)
3018 void Magick::Image::depth ( const size_t depth_ )
3019 {
3020   size_t depth = depth_;
3021
3022   if (depth > MAGICKCORE_QUANTUM_DEPTH)
3023     depth=MAGICKCORE_QUANTUM_DEPTH;
3024
3025   modifyImage();
3026   image()->depth=depth;
3027   options()->depth( depth );
3028 }
3029 size_t Magick::Image::depth ( void ) const
3030 {
3031   return constImage()->depth;
3032 }
3033
3034 std::string Magick::Image::directory ( void ) const
3035 {
3036   if ( constImage()->directory )
3037     return std::string( constImage()->directory );
3038
3039   throwExceptionExplicit( CorruptImageWarning,
3040                           "Image does not contain a directory");
3041
3042   return std::string();
3043 }
3044
3045 // Endianness (little like Intel or big like SPARC) for image
3046 // formats which support endian-specific options.
3047 void Magick::Image::endian ( const Magick::EndianType endian_ )
3048 {
3049   modifyImage();
3050   options()->endian( endian_ );
3051   image()->endian = endian_;
3052 }
3053 Magick::EndianType Magick::Image::endian ( void ) const
3054 {
3055   return constImage()->endian;
3056 }
3057
3058 // EXIF profile (BLOB)
3059 void Magick::Image::exifProfile( const Magick::Blob &exifProfile_ )
3060 {
3061   modifyImage();
3062   if ( exifProfile_.data() != 0 )
3063     {
3064       StringInfo * exif_profile = AcquireStringInfo( exifProfile_.length() );
3065       SetStringInfoDatum(exif_profile ,(unsigned char *) exifProfile_.data());
3066       ExceptionInfo exceptionInfo;
3067       GetExceptionInfo( &exceptionInfo );
3068       (void) SetImageProfile( image(), "exif", exif_profile, &exceptionInfo);
3069       exif_profile =DestroyStringInfo( exif_profile );
3070       throwException( exceptionInfo );
3071       (void) DestroyExceptionInfo( &exceptionInfo );
3072     }
3073 }
3074 Magick::Blob Magick::Image::exifProfile( void ) const
3075 {
3076   const StringInfo * exif_profile = GetImageProfile( constImage(), "exif" );
3077   if ( exif_profile == (StringInfo *) NULL)
3078     return Blob( 0, 0 );
3079   return Blob(GetStringInfoDatum(exif_profile),GetStringInfoLength(exif_profile));
3080
3081
3082 // Image file name
3083 void Magick::Image::fileName ( const std::string &fileName_ )
3084 {
3085   modifyImage();
3086
3087   fileName_.copy( image()->filename,
3088                   sizeof(image()->filename) - 1 );
3089   image()->filename[ fileName_.length() ] = 0; // Null terminate
3090   
3091   options()->fileName( fileName_ );
3092   
3093 }
3094 std::string Magick::Image::fileName ( void ) const
3095 {
3096   return constOptions()->fileName( );
3097 }
3098
3099 // Image file size
3100 off_t Magick::Image::fileSize ( void ) const
3101 {
3102   return (off_t) GetBlobSize( constImage() );
3103 }
3104
3105 // Color to use when drawing inside an object
3106 void Magick::Image::fillColor ( const Magick::Color &fillColor_ )
3107 {
3108   modifyImage();
3109   options()->fillColor(fillColor_);
3110 }
3111 Magick::Color Magick::Image::fillColor ( void ) const
3112 {
3113   return constOptions()->fillColor();
3114 }
3115
3116 // Rule to use when filling drawn objects
3117 void Magick::Image::fillRule ( const Magick::FillRule &fillRule_ )
3118 {
3119   modifyImage();
3120   options()->fillRule(fillRule_);
3121 }
3122 Magick::FillRule Magick::Image::fillRule ( void ) const
3123 {
3124   return constOptions()->fillRule();
3125 }
3126
3127 // Pattern to use while filling drawn objects.
3128 void Magick::Image::fillPattern ( const Image &fillPattern_ )
3129 {
3130   modifyImage();
3131   if(fillPattern_.isValid())
3132     options()->fillPattern( fillPattern_.constImage() );
3133   else
3134     options()->fillPattern( static_cast<MagickCore::Image*>(NULL) );
3135 }
3136 Magick::Image  Magick::Image::fillPattern ( void  ) const
3137 {
3138   // FIXME: This is inordinately innefficient
3139   Image texture;
3140   
3141   const MagickCore::Image* tmpTexture = constOptions()->fillPattern( );
3142
3143   if ( tmpTexture )
3144     {
3145       ExceptionInfo exceptionInfo;
3146       GetExceptionInfo( &exceptionInfo );
3147       MagickCore::Image* image =
3148         CloneImage( tmpTexture,
3149                     0, // columns
3150                     0, // rows
3151                     MagickTrue, // orphan
3152                     &exceptionInfo);
3153       texture.replaceImage( image );
3154       throwException( exceptionInfo );
3155       (void) DestroyExceptionInfo( &exceptionInfo );
3156     }
3157   return texture;
3158 }
3159
3160 // Filter used by zoom
3161 void Magick::Image::filterType ( const Magick::FilterTypes filterType_ )
3162 {
3163   modifyImage();
3164   image()->filter = filterType_;
3165 }
3166 Magick::FilterTypes Magick::Image::filterType ( void ) const
3167 {
3168   return constImage()->filter;
3169 }
3170
3171 // Font name
3172 void Magick::Image::font ( const std::string &font_ )
3173 {
3174   modifyImage();
3175   options()->font( font_ );
3176 }
3177 std::string Magick::Image::font ( void ) const
3178 {
3179   return constOptions()->font( );
3180 }
3181
3182 // Font point size
3183 void Magick::Image::fontPointsize ( const double pointSize_ )
3184 {
3185   modifyImage();
3186   options()->fontPointsize( pointSize_ );
3187 }
3188 double Magick::Image::fontPointsize ( void ) const
3189 {
3190   return constOptions()->fontPointsize( );
3191 }
3192
3193 // Font type metrics
3194 void Magick::Image::fontTypeMetrics( const std::string &text_,
3195                                      TypeMetric *metrics )
3196 {
3197   DrawInfo *drawInfo = options()->drawInfo();
3198   drawInfo->text = const_cast<char *>(text_.c_str());
3199   ExceptionInfo exceptionInfo;
3200   GetExceptionInfo( &exceptionInfo );
3201   GetTypeMetrics( image(), drawInfo, &(metrics->_typeMetric), &exceptionInfo );
3202   drawInfo->text = 0;
3203   throwException( exceptionInfo );
3204   (void) DestroyExceptionInfo( &exceptionInfo );
3205 }
3206
3207 // Image format string
3208 std::string Magick::Image::format ( void ) const
3209 {
3210   ExceptionInfo exceptionInfo;
3211   GetExceptionInfo( &exceptionInfo );
3212   const MagickInfo * magick_info
3213     = GetMagickInfo( constImage()->magick, &exceptionInfo);
3214   throwException( exceptionInfo );
3215   (void) DestroyExceptionInfo( &exceptionInfo );
3216
3217   if (( magick_info != 0 ) && 
3218       ( *magick_info->description != '\0' ))
3219     return std::string(magick_info->description);
3220
3221   throwExceptionExplicit( CorruptImageWarning,
3222                           "Unrecognized image magick type" );
3223   return std::string();
3224 }
3225
3226 // Gamma adjustment
3227 double Magick::Image::gamma ( void ) const
3228 {
3229   return constImage()->gamma;
3230 }
3231
3232 Magick::Geometry Magick::Image::geometry ( void ) const
3233 {
3234   if ( constImage()->geometry )
3235   {
3236     return Geometry(constImage()->geometry);
3237   }
3238
3239   throwExceptionExplicit( OptionWarning,
3240                           "Image does not contain a geometry");
3241
3242   return Geometry();
3243 }
3244
3245 void Magick::Image::gifDisposeMethod ( const size_t disposeMethod_ )
3246 {
3247   modifyImage();
3248   image()->dispose = (DisposeType) disposeMethod_;
3249 }
3250 size_t Magick::Image::gifDisposeMethod ( void ) const
3251 {
3252   // FIXME: It would be better to return an enumeration
3253   return constImage()->dispose;
3254 }
3255
3256 // ICC ICM color profile (BLOB)
3257 void Magick::Image::iccColorProfile( const Magick::Blob &colorProfile_ )
3258 {
3259   profile("icm",colorProfile_);
3260 }
3261 Magick::Blob Magick::Image::iccColorProfile( void ) const
3262 {
3263   const StringInfo * color_profile = GetImageProfile( constImage(), "icc" );
3264   if ( color_profile == (StringInfo *) NULL)
3265     return Blob( 0, 0 );
3266   return Blob( GetStringInfoDatum(color_profile), GetStringInfoLength(color_profile) );
3267 }
3268
3269 void Magick::Image::interlaceType ( const Magick::InterlaceType interlace_ )
3270 {
3271   modifyImage();
3272   image()->interlace = interlace_;
3273   options()->interlaceType ( interlace_ );
3274 }
3275 Magick::InterlaceType Magick::Image::interlaceType ( void ) const
3276 {
3277   return constImage()->interlace;
3278 }
3279
3280 // IPTC profile (BLOB)
3281 void Magick::Image::iptcProfile( const Magick::Blob &iptcProfile_ )
3282 {
3283   modifyImage();
3284   if (  iptcProfile_.data() != 0 )
3285     {
3286       StringInfo * iptc_profile = AcquireStringInfo( iptcProfile_.length() );
3287       SetStringInfoDatum(iptc_profile ,(unsigned char *) iptcProfile_.data());
3288       ExceptionInfo exceptionInfo;
3289       GetExceptionInfo( &exceptionInfo );
3290       (void) SetImageProfile( image(), "iptc", iptc_profile, &exceptionInfo);
3291       iptc_profile =DestroyStringInfo( iptc_profile );
3292       throwException( exceptionInfo );
3293       (void) DestroyExceptionInfo( &exceptionInfo );
3294     }
3295 }
3296 Magick::Blob Magick::Image::iptcProfile( void ) const
3297 {
3298   const StringInfo * iptc_profile = GetImageProfile( constImage(), "iptc" );
3299   if ( iptc_profile == (StringInfo *) NULL)
3300     return Blob( 0, 0 );
3301   return Blob( GetStringInfoDatum(iptc_profile), GetStringInfoLength(iptc_profile));
3302 }
3303
3304 // Does object contain valid image?
3305 void Magick::Image::isValid ( const bool isValid_ )
3306 {
3307   if ( !isValid_ )
3308     {
3309       delete _imgRef;
3310       _imgRef = new ImageRef;
3311     }
3312   else if ( !isValid() )
3313     {
3314       // Construct with single-pixel black image to make
3315       // image valid.  This is an obvious hack.
3316       size( Geometry(1,1) );
3317       read( "xc:#000000" );
3318     }
3319 }
3320
3321 bool Magick::Image::isValid ( void ) const
3322 {
3323   if ( rows() && columns() )
3324     return true;
3325
3326   return false;
3327 }
3328
3329 // Label image
3330 void Magick::Image::label ( const std::string &label_ )
3331 {
3332   modifyImage();
3333   ExceptionInfo exceptionInfo;
3334   GetExceptionInfo( &exceptionInfo );
3335   SetImageProperty ( image(), "Label", NULL, &exceptionInfo );
3336   if ( label_.length() > 0 )
3337     SetImageProperty ( image(), "Label", label_.c_str(), &exceptionInfo );
3338   throwException( exceptionInfo );
3339   (void) DestroyExceptionInfo( &exceptionInfo );
3340 }
3341 std::string Magick::Image::label ( void ) const
3342 {
3343   ExceptionInfo exceptionInfo;
3344   GetExceptionInfo( &exceptionInfo );
3345   const char *value = GetImageProperty( constImage(), "Label", &exceptionInfo );
3346   throwException( exceptionInfo );
3347   (void) DestroyExceptionInfo( &exceptionInfo );
3348
3349   if ( value )
3350     return std::string( value );
3351
3352   return std::string();
3353 }
3354
3355 void Magick::Image::magick ( const std::string &magick_ )
3356 {
3357   modifyImage();
3358
3359   magick_.copy( image()->magick,
3360                 sizeof(image()->magick) - 1 );
3361   image()->magick[ magick_.length() ] = 0;
3362   
3363   options()->magick( magick_ );
3364 }
3365 std::string Magick::Image::magick ( void ) const
3366 {
3367   if ( *(constImage()->magick) != '\0' )
3368     return std::string(constImage()->magick);
3369
3370   return constOptions()->magick( );
3371 }
3372
3373 void Magick::Image::matte ( const bool matteFlag_ )
3374 {
3375   modifyImage();
3376
3377   // If matte channel is requested, but image doesn't already have a
3378   // matte channel, then create an opaque matte channel.  Likewise, if
3379   // the image already has a matte channel but a matte channel is not
3380   // desired, then set the matte channel to opaque.
3381   ExceptionInfo exceptionInfo;
3382   GetExceptionInfo( &exceptionInfo );
3383   if ((matteFlag_ && !constImage()->matte) ||
3384       (constImage()->matte && !matteFlag_))
3385     SetImageAlpha(image(),OpaqueAlpha,&exceptionInfo);
3386   throwException( exceptionInfo );
3387   (void) DestroyExceptionInfo( &exceptionInfo );
3388
3389   image()->matte = (MagickBooleanType) matteFlag_;
3390 }
3391 bool Magick::Image::matte ( void ) const
3392 {
3393   if ( constImage()->matte )
3394     return true;
3395   else
3396     return false;
3397 }
3398
3399 void Magick::Image::matteColor ( const Color &matteColor_ )
3400 {
3401   modifyImage();
3402   
3403   if ( matteColor_.isValid() )
3404     {
3405       image()->matte_color = matteColor_;
3406       options()->matteColor( matteColor_ );
3407     }
3408   else
3409     {
3410       // Set to default matte color
3411       Color tmpColor( "#BDBDBD" );
3412       image()->matte_color = tmpColor;
3413       options()->matteColor( tmpColor );
3414     }
3415 }
3416 Magick::Color Magick::Image::matteColor ( void ) const
3417 {
3418   return Color( ClampToQuantum( constImage()->matte_color.red ),
3419                 ClampToQuantum( constImage()->matte_color.green ),
3420                 ClampToQuantum( constImage()->matte_color.blue ) );
3421 }
3422
3423 double Magick::Image::meanErrorPerPixel ( void ) const
3424 {
3425   return(constImage()->error.mean_error_per_pixel);
3426 }
3427
3428 // Image modulus depth (minimum number of bits required to support
3429 // red/green/blue components without loss of accuracy)
3430 void Magick::Image::modulusDepth ( const size_t depth_ )
3431 {
3432   modifyImage();
3433   ExceptionInfo exceptionInfo;
3434   GetExceptionInfo( &exceptionInfo );
3435   SetImageDepth( image(), depth_, &exceptionInfo );
3436   throwException( exceptionInfo );
3437   (void) DestroyExceptionInfo( &exceptionInfo );
3438   options()->depth( depth_ );
3439 }
3440 size_t Magick::Image::modulusDepth ( void ) const
3441 {
3442   ExceptionInfo exceptionInfo;
3443   GetExceptionInfo( &exceptionInfo );
3444   size_t depth=GetImageDepth( constImage(), &exceptionInfo );
3445   throwException( exceptionInfo );
3446   (void) DestroyExceptionInfo( &exceptionInfo );
3447   return depth;
3448 }
3449
3450 void Magick::Image::monochrome ( const bool monochromeFlag_ )
3451 {
3452   modifyImage();
3453   options()->monochrome( monochromeFlag_ );
3454 }
3455 bool Magick::Image::monochrome ( void ) const
3456 {
3457   return constOptions()->monochrome( );
3458 }
3459
3460 Magick::Geometry Magick::Image::montageGeometry ( void ) const
3461 {
3462   if ( constImage()->montage )
3463     return Magick::Geometry(constImage()->montage);
3464
3465   throwExceptionExplicit( CorruptImageWarning,
3466                           "Image does not contain a montage" );
3467
3468   return Magick::Geometry();
3469 }
3470
3471 double Magick::Image::normalizedMaxError ( void ) const
3472 {
3473   return(constImage()->error.normalized_maximum_error);
3474 }
3475
3476 double Magick::Image::normalizedMeanError ( void ) const
3477 {
3478   return constImage()->error.normalized_mean_error;
3479 }
3480
3481 // Image orientation
3482 void Magick::Image::orientation ( const Magick::OrientationType orientation_ )
3483 {
3484   modifyImage();
3485   image()->orientation = orientation_;
3486 }
3487 Magick::OrientationType Magick::Image::orientation ( void ) const
3488 {
3489   return constImage()->orientation;
3490 }
3491
3492 void Magick::Image::penColor ( const Color &penColor_ )
3493 {
3494   modifyImage();
3495   options()->fillColor(penColor_);
3496   options()->strokeColor(penColor_);
3497 }
3498 Magick::Color Magick::Image::penColor ( void  ) const
3499 {
3500   return constOptions()->fillColor();
3501 }
3502
3503 void Magick::Image::penTexture ( const Image &penTexture_ )
3504 {
3505   modifyImage();
3506   if(penTexture_.isValid())
3507     options()->fillPattern( penTexture_.constImage() );
3508   else
3509     options()->fillPattern( static_cast<MagickCore::Image*>(NULL) );
3510 }
3511
3512 Magick::Image  Magick::Image::penTexture ( void  ) const
3513 {
3514   // FIXME: This is inordinately innefficient
3515   Image texture;
3516   
3517   const MagickCore::Image* tmpTexture = constOptions()->fillPattern( );
3518
3519   if ( tmpTexture )
3520     {
3521       ExceptionInfo exceptionInfo;
3522       GetExceptionInfo( &exceptionInfo );
3523       MagickCore::Image* image =
3524         CloneImage( tmpTexture,
3525                     0, // columns
3526                     0, // rows
3527                     MagickTrue, // orphan
3528                     &exceptionInfo);
3529       texture.replaceImage( image );
3530       throwException( exceptionInfo );
3531   (void) DestroyExceptionInfo( &exceptionInfo );
3532     }
3533   return texture;
3534 }
3535
3536 // Set the color of a pixel.
3537 void Magick::Image::pixelColor ( const ssize_t x_, const ssize_t y_,
3538                                  const Color &color_ )
3539 {
3540   // Test arguments to ensure they are within the image.
3541   if ( y_ > (ssize_t) rows() || x_ > (ssize_t) columns() )
3542     throwExceptionExplicit( OptionError,
3543             "Access outside of image boundary" );
3544       
3545   modifyImage();
3546
3547   // Set image to DirectClass
3548   classType( DirectClass );
3549
3550   // Get pixel view
3551   Pixels pixels(*this);
3552     // Set pixel value
3553   Quantum *pixel = pixels.get(x_, y_, 1, 1 );
3554   PixelInfo packet = color_;
3555   MagickCore::SetPixelInfoPixel(constImage(),&packet,pixel);
3556   // Tell ImageMagick that pixels have been updated
3557   pixels.sync();
3558
3559   return;
3560 }
3561
3562 // Get the color of a pixel
3563 Magick::Color Magick::Image::pixelColor ( const ssize_t x_,
3564                                           const ssize_t y_ ) const
3565 {
3566   ClassType storage_class;
3567   storage_class = classType();
3568   // DirectClass
3569   const Quantum* pixel = getConstPixels( x_, y_, 1, 1 );
3570   if ( pixel )
3571     {
3572       PixelInfo packet;
3573       MagickCore::GetPixelInfoPixel(constImage(),pixel,&packet);
3574       return Color( packet );
3575     }
3576
3577   return Color(); // invalid
3578 }
3579
3580 // Preferred size and location of an image canvas.
3581 void Magick::Image::page ( const Magick::Geometry &pageSize_ )
3582 {
3583   modifyImage();
3584   options()->page( pageSize_ );
3585   image()->page = pageSize_;
3586 }
3587 Magick::Geometry Magick::Image::page ( void ) const
3588 {
3589   return Geometry( constImage()->page.width,
3590                    constImage()->page.height,
3591                    AbsoluteValue(constImage()->page.x),
3592                    AbsoluteValue(constImage()->page.y),
3593                    constImage()->page.x < 0 ? true : false,
3594                    constImage()->page.y < 0 ? true : false);
3595 }
3596
3597 // Add a named profile to an image or remove a named profile by
3598 // passing an empty Blob (use default Blob constructor).
3599 // Valid names are:
3600 // "*", "8BIM", "ICM", "IPTC", or a generic profile name.
3601 void Magick::Image::profile( const std::string name_,
3602                              const Magick::Blob &profile_ )
3603 {
3604   modifyImage();
3605   ExceptionInfo exceptionInfo;
3606   GetExceptionInfo( &exceptionInfo );
3607   ssize_t result = ProfileImage( image(), name_.c_str(),
3608                              (unsigned char *)profile_.data(),
3609                              profile_.length(), &exceptionInfo);
3610   throwException( exceptionInfo );
3611   (void) DestroyExceptionInfo( &exceptionInfo );
3612
3613 }
3614
3615 // Retrieve a named profile from the image.
3616 // Valid names are:
3617 // "8BIM", "8BIMTEXT", "APP1", "APP1JPEG", "ICC", "ICM", & "IPTC" or
3618 // an existing generic profile name.
3619 Magick::Blob Magick::Image::profile( const std::string name_ ) const
3620 {
3621   const MagickCore::Image* image = constImage();
3622                                                                                 
3623   const StringInfo * profile = GetImageProfile( image, name_.c_str() );
3624                                                                                 
3625   if ( profile != (StringInfo *) NULL)
3626       return Blob( (void*) GetStringInfoDatum(profile), GetStringInfoLength(profile));
3627                                                                                 
3628   Blob blob;
3629   Image temp_image = *this;
3630   temp_image.write( &blob, name_ );
3631   return blob;
3632 }
3633
3634 void Magick::Image::quality ( const size_t quality_ )
3635 {
3636   modifyImage();
3637   image()->quality = quality_;
3638   options()->quality( quality_ );
3639 }
3640 size_t Magick::Image::quality ( void ) const
3641 {
3642   return constImage()->quality;
3643 }
3644
3645 void Magick::Image::quantizeColors ( const size_t colors_ )
3646 {
3647   modifyImage();
3648   options()->quantizeColors( colors_ );
3649 }
3650 size_t Magick::Image::quantizeColors ( void ) const
3651 {
3652   return constOptions()->quantizeColors( );
3653 }
3654
3655 void Magick::Image::quantizeColorSpace
3656   ( const Magick::ColorspaceType colorSpace_ )
3657 {
3658   modifyImage();
3659   options()->quantizeColorSpace( colorSpace_ );
3660 }
3661 Magick::ColorspaceType Magick::Image::quantizeColorSpace ( void ) const
3662 {
3663   return constOptions()->quantizeColorSpace( );
3664 }
3665
3666 void Magick::Image::quantizeDither ( const bool ditherFlag_ )
3667 {
3668   modifyImage();
3669   options()->quantizeDither( ditherFlag_ );
3670 }
3671 bool Magick::Image::quantizeDither ( void ) const
3672 {
3673   return constOptions()->quantizeDither( );
3674 }
3675
3676 void Magick::Image::quantizeTreeDepth ( const size_t treeDepth_ )
3677 {
3678   modifyImage();
3679   options()->quantizeTreeDepth( treeDepth_ );
3680 }
3681 size_t Magick::Image::quantizeTreeDepth ( void ) const
3682 {
3683   return constOptions()->quantizeTreeDepth( );
3684 }
3685
3686 void Magick::Image::renderingIntent
3687   ( const Magick::RenderingIntent renderingIntent_ )
3688 {
3689   modifyImage();
3690   image()->rendering_intent = renderingIntent_;
3691 }
3692 Magick::RenderingIntent Magick::Image::renderingIntent ( void ) const
3693 {
3694   return static_cast<Magick::RenderingIntent>(constImage()->rendering_intent);
3695 }
3696
3697 void Magick::Image::resolutionUnits
3698   ( const Magick::ResolutionType resolutionUnits_ )
3699 {
3700   modifyImage();
3701   image()->units = resolutionUnits_;
3702   options()->resolutionUnits( resolutionUnits_ );
3703 }
3704 Magick::ResolutionType Magick::Image::resolutionUnits ( void ) const
3705 {
3706   return constOptions()->resolutionUnits( );
3707 }
3708
3709 void Magick::Image::scene ( const size_t scene_ )
3710 {
3711   modifyImage();
3712   image()->scene = scene_;
3713 }
3714 size_t Magick::Image::scene ( void ) const
3715 {
3716   return constImage()->scene;
3717 }
3718
3719 std::string Magick::Image::signature ( const bool force_ ) const
3720 {
3721   Lock( &_imgRef->_mutexLock );
3722
3723   // Re-calculate image signature if necessary
3724   ExceptionInfo exceptionInfo;
3725   GetExceptionInfo( &exceptionInfo );
3726   if ( force_ ||
3727        !GetImageProperty(constImage(), "Signature", &exceptionInfo) ||
3728        constImage()->taint )
3729     {
3730       SignatureImage( const_cast<MagickCore::Image *>(constImage()), &exceptionInfo );
3731     }
3732
3733   const char *property = GetImageProperty(constImage(), "Signature",
3734     &exceptionInfo);
3735   throwException( exceptionInfo );
3736   (void) DestroyExceptionInfo( &exceptionInfo );
3737
3738   return std::string( property );
3739 }
3740
3741 void Magick::Image::size ( const Geometry &geometry_ )
3742 {
3743   modifyImage();
3744   options()->size( geometry_ );
3745   image()->rows = geometry_.height();
3746   image()->columns = geometry_.width();
3747 }
3748 Magick::Geometry Magick::Image::size ( void ) const
3749 {
3750   return Magick::Geometry( constImage()->columns, constImage()->rows );
3751 }
3752
3753 // Splice image
3754 void Magick::Image::splice( const Geometry &geometry_ )
3755 {
3756   RectangleInfo spliceInfo = geometry_;
3757   ExceptionInfo exceptionInfo;
3758   GetExceptionInfo( &exceptionInfo );
3759   MagickCore::Image* newImage =
3760     SpliceImage( image(), &spliceInfo, &exceptionInfo);
3761   replaceImage( newImage );
3762   throwException( exceptionInfo );
3763   (void) DestroyExceptionInfo( &exceptionInfo );
3764 }
3765
3766 // Obtain image statistics. Statistics are normalized to the range of
3767 // 0.0 to 1.0 and are output to the specified ImageStatistics
3768 // structure.
3769 void Magick::Image::statistics ( ImageStatistics *statistics ) 
3770 {
3771   double
3772     maximum,
3773     minimum;
3774
3775   ExceptionInfo exceptionInfo;
3776   GetExceptionInfo( &exceptionInfo );
3777
3778   ChannelType channel_mask = SetPixelChannelMask( image(), RedChannel);
3779   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3780   statistics->red.minimum=minimum;
3781   statistics->red.maximum=maximum;
3782   (void) GetImageMean( image(),&statistics->red.mean,
3783     &statistics->red.standard_deviation,&exceptionInfo);
3784   (void) GetImageKurtosis( image(),&statistics->red.kurtosis,
3785     &statistics->red.skewness,&exceptionInfo);
3786   (void) SetPixelChannelMapMask( image(), channel_mask );
3787
3788   channel_mask = SetPixelChannelMask( image(), GreenChannel);
3789   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3790   statistics->green.minimum=minimum;
3791   statistics->green.maximum=maximum;
3792   (void) GetImageMean( image(),&statistics->green.mean,
3793     &statistics->green.standard_deviation,&exceptionInfo);
3794   (void) GetImageKurtosis( image(),&statistics->green.kurtosis,
3795     &statistics->green.skewness,&exceptionInfo);
3796   (void) SetPixelChannelMapMask( image(), channel_mask );
3797
3798   channel_mask = SetPixelChannelMask( image(), GreenChannel);
3799   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3800   statistics->blue.minimum=minimum;
3801   statistics->blue.maximum=maximum;
3802   (void) GetImageMean( image(),&statistics->blue.mean,
3803     &statistics->blue.standard_deviation,&exceptionInfo);
3804   (void) GetImageKurtosis( image(),&statistics->blue.kurtosis,
3805     &statistics->blue.skewness,&exceptionInfo);
3806   (void) SetPixelChannelMapMask( image(), channel_mask );
3807
3808   channel_mask = SetPixelChannelMask( image(), AlphaChannel);
3809   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3810   statistics->alpha.minimum=minimum;
3811   statistics->alpha.maximum=maximum;
3812   (void) GetImageMean( image(),&statistics->alpha.mean,
3813     &statistics->alpha.standard_deviation,&exceptionInfo);
3814   (void) GetImageKurtosis( image(),&statistics->alpha.kurtosis,
3815     &statistics->alpha.skewness,&exceptionInfo);
3816   (void) SetPixelChannelMapMask( image(), channel_mask );
3817
3818   throwException( exceptionInfo );
3819   (void) DestroyExceptionInfo( &exceptionInfo );
3820 }
3821
3822 // Strip strips an image of all profiles and comments.
3823 void Magick::Image::strip ( void )
3824 {
3825   modifyImage();
3826   ExceptionInfo exceptionInfo;
3827   GetExceptionInfo( &exceptionInfo );
3828   StripImage( image(), &exceptionInfo );
3829   throwException( exceptionInfo );
3830   (void) DestroyExceptionInfo( &exceptionInfo );
3831 }
3832
3833 // enabled/disable stroke anti-aliasing
3834 void Magick::Image::strokeAntiAlias ( const bool flag_ )
3835 {
3836   modifyImage();
3837   options()->strokeAntiAlias(flag_);
3838 }
3839 bool Magick::Image::strokeAntiAlias ( void ) const
3840 {
3841   return constOptions()->strokeAntiAlias();
3842 }
3843
3844 // Color to use when drawing object outlines
3845 void Magick::Image::strokeColor ( const Magick::Color &strokeColor_ )
3846 {
3847   modifyImage();
3848   options()->strokeColor(strokeColor_);
3849 }
3850 Magick::Color Magick::Image::strokeColor ( void ) const
3851 {
3852   return constOptions()->strokeColor();
3853 }
3854
3855 // dash pattern for drawing vector objects (default one)
3856 void Magick::Image::strokeDashArray ( const double* strokeDashArray_ )
3857 {
3858   modifyImage();
3859   options()->strokeDashArray( strokeDashArray_ );
3860 }
3861
3862 const double* Magick::Image::strokeDashArray ( void ) const
3863 {
3864   return constOptions()->strokeDashArray( );
3865 }
3866
3867 // dash offset for drawing vector objects (default one)
3868 void Magick::Image::strokeDashOffset ( const double strokeDashOffset_ )
3869 {
3870   modifyImage();
3871   options()->strokeDashOffset( strokeDashOffset_ );
3872 }
3873
3874 double Magick::Image::strokeDashOffset ( void ) const
3875 {
3876   return constOptions()->strokeDashOffset( );
3877 }
3878
3879 // Specify the shape to be used at the end of open subpaths when they
3880 // are stroked. Values of LineCap are UndefinedCap, ButtCap, RoundCap,
3881 // and SquareCap.
3882 void Magick::Image::strokeLineCap ( const Magick::LineCap lineCap_ )
3883 {
3884   modifyImage();
3885   options()->strokeLineCap( lineCap_ );
3886 }
3887 Magick::LineCap Magick::Image::strokeLineCap ( void ) const
3888 {
3889   return constOptions()->strokeLineCap( );
3890 }
3891
3892 // Specify the shape to be used at the corners of paths (or other
3893 // vector shapes) when they are stroked. Values of LineJoin are
3894 // UndefinedJoin, MiterJoin, RoundJoin, and BevelJoin.
3895 void Magick::Image::strokeLineJoin ( const Magick::LineJoin lineJoin_ )
3896 {
3897   modifyImage();
3898   options()->strokeLineJoin( lineJoin_ );
3899 }
3900 Magick::LineJoin Magick::Image::strokeLineJoin ( void ) const
3901 {
3902   return constOptions()->strokeLineJoin( );
3903 }
3904
3905 // Specify miter limit. When two line segments meet at a sharp angle
3906 // and miter joins have been specified for 'lineJoin', it is possible
3907 // for the miter to extend far beyond the thickness of the line
3908 // stroking the path. The miterLimit' imposes a limit on the ratio of
3909 // the miter length to the 'lineWidth'. The default value of this
3910 // parameter is 4.
3911 void Magick::Image::strokeMiterLimit ( const size_t strokeMiterLimit_ )
3912 {
3913   modifyImage();
3914   options()->strokeMiterLimit( strokeMiterLimit_ );
3915 }
3916 size_t Magick::Image::strokeMiterLimit ( void ) const
3917 {
3918   return constOptions()->strokeMiterLimit( );
3919 }
3920
3921 // Pattern to use while stroking drawn objects.
3922 void Magick::Image::strokePattern ( const Image &strokePattern_ )
3923 {
3924   modifyImage();
3925   if(strokePattern_.isValid())
3926     options()->strokePattern( strokePattern_.constImage() );
3927   else
3928     options()->strokePattern( static_cast<MagickCore::Image*>(NULL) );
3929 }
3930 Magick::Image  Magick::Image::strokePattern ( void  ) const
3931 {
3932   // FIXME: This is inordinately innefficient
3933   Image texture;
3934   
3935   const MagickCore::Image* tmpTexture = constOptions()->strokePattern( );
3936
3937   if ( tmpTexture )
3938     {
3939       ExceptionInfo exceptionInfo;
3940       GetExceptionInfo( &exceptionInfo );
3941       MagickCore::Image* image =
3942         CloneImage( tmpTexture,
3943                     0, // columns
3944                     0, // rows
3945                     MagickTrue, // orphan
3946                     &exceptionInfo);
3947       throwException( exceptionInfo );
3948       (void) DestroyExceptionInfo( &exceptionInfo );
3949       texture.replaceImage( image );
3950     }
3951   return texture;
3952 }
3953
3954 // Stroke width for drawing lines, circles, ellipses, etc.
3955 void Magick::Image::strokeWidth ( const double strokeWidth_ )
3956 {
3957   modifyImage();
3958   options()->strokeWidth( strokeWidth_ );
3959 }
3960 double Magick::Image::strokeWidth ( void ) const
3961 {
3962   return constOptions()->strokeWidth( );
3963 }
3964
3965 void Magick::Image::subImage ( const size_t subImage_ )
3966 {
3967   modifyImage();
3968   options()->subImage( subImage_ );
3969 }
3970 size_t Magick::Image::subImage ( void ) const
3971 {
3972   return constOptions()->subImage( );
3973 }
3974
3975 void Magick::Image::subRange ( const size_t subRange_ )
3976 {
3977   modifyImage();
3978   options()->subRange( subRange_ );
3979 }
3980 size_t Magick::Image::subRange ( void ) const
3981 {
3982   return constOptions()->subRange( );
3983 }
3984
3985 // Annotation text encoding (e.g. "UTF-16")
3986 void Magick::Image::textEncoding ( const std::string &encoding_ )
3987 {
3988   modifyImage();
3989   options()->textEncoding( encoding_ );
3990 }
3991 std::string Magick::Image::textEncoding ( void ) const
3992 {
3993   return constOptions()->textEncoding( );
3994 }
3995
3996 size_t Magick::Image::totalColors ( void )
3997 {
3998   ExceptionInfo exceptionInfo;
3999   GetExceptionInfo( &exceptionInfo );
4000   size_t colors = GetNumberColors( image(), 0, &exceptionInfo);
4001   throwException( exceptionInfo );
4002   (void) DestroyExceptionInfo( &exceptionInfo );
4003   return colors;
4004 }
4005
4006 // Origin of coordinate system to use when annotating with text or drawing
4007 void Magick::Image::transformOrigin ( const double x_, const double y_ )
4008 {
4009   modifyImage();
4010   options()->transformOrigin( x_, y_ );
4011 }
4012
4013 // Rotation to use when annotating with text or drawing
4014 void Magick::Image::transformRotation ( const double angle_ )
4015 {
4016   modifyImage();
4017   options()->transformRotation( angle_ );
4018 }
4019
4020 // Reset transformation parameters to default
4021 void Magick::Image::transformReset ( void )
4022 {
4023   modifyImage();
4024   options()->transformReset();
4025 }
4026
4027 // Scale to use when annotating with text or drawing
4028 void Magick::Image::transformScale ( const double sx_, const double sy_ )
4029 {
4030   modifyImage();
4031   options()->transformScale( sx_, sy_ );
4032 }
4033
4034 // Skew to use in X axis when annotating with text or drawing
4035 void Magick::Image::transformSkewX ( const double skewx_ )
4036 {
4037   modifyImage();
4038   options()->transformSkewX( skewx_ );
4039 }
4040
4041 // Skew to use in Y axis when annotating with text or drawing
4042 void Magick::Image::transformSkewY ( const double skewy_ )
4043 {
4044   modifyImage();
4045   options()->transformSkewY( skewy_ );
4046 }
4047
4048 // Image representation type
4049 Magick::ImageType Magick::Image::type ( void ) const
4050 {
4051
4052   ExceptionInfo exceptionInfo;
4053   GetExceptionInfo( &exceptionInfo );
4054   ImageType image_type = constOptions()->type();
4055   if ( image_type == UndefinedType )
4056     image_type= GetImageType( constImage(), &exceptionInfo);
4057   throwException( exceptionInfo );
4058   (void) DestroyExceptionInfo( &exceptionInfo );
4059   return image_type;
4060 }
4061 void Magick::Image::type ( const Magick::ImageType type_)
4062 {
4063   ExceptionInfo exceptionInfo;
4064   GetExceptionInfo( &exceptionInfo );
4065   modifyImage();
4066   options()->type( type_ );
4067   SetImageType( image(), type_, &exceptionInfo );
4068   throwException( exceptionInfo );
4069   (void) DestroyExceptionInfo( &exceptionInfo );
4070 }
4071
4072 void Magick::Image::verbose ( const bool verboseFlag_ )
4073 {
4074   modifyImage();
4075   options()->verbose( verboseFlag_ );
4076 }
4077 bool Magick::Image::verbose ( void ) const
4078 {
4079   return constOptions()->verbose( );
4080 }
4081
4082 void Magick::Image::view ( const std::string &view_ )
4083 {
4084   modifyImage();
4085   options()->view( view_ );
4086 }
4087 std::string Magick::Image::view ( void ) const
4088 {
4089   return constOptions()->view( );
4090 }
4091
4092 // Virtual pixel method
4093 void Magick::Image::virtualPixelMethod ( const VirtualPixelMethod virtual_pixel_method_ )
4094 {
4095   modifyImage();
4096   SetImageVirtualPixelMethod( image(), virtual_pixel_method_ );
4097 }
4098 Magick::VirtualPixelMethod Magick::Image::virtualPixelMethod ( void ) const
4099 {
4100   return GetImageVirtualPixelMethod( constImage() );
4101 }
4102
4103 void Magick::Image::x11Display ( const std::string &display_ )
4104 {
4105   modifyImage();
4106   options()->x11Display( display_ );
4107 }
4108 std::string Magick::Image::x11Display ( void ) const
4109 {
4110   return constOptions()->x11Display( );
4111 }
4112
4113 double Magick::Image::xResolution ( void ) const
4114 {
4115   return constImage()->resolution.x;
4116 }
4117 double Magick::Image::yResolution ( void ) const
4118 {
4119   return constImage()->resolution.y;
4120 }
4121
4122 // Copy Constructor
4123 Magick::Image::Image( const Image & image_ )
4124   : _imgRef(image_._imgRef)
4125 {
4126   Lock( &_imgRef->_mutexLock );
4127
4128   // Increase reference count
4129   ++_imgRef->_refCount;
4130 }
4131
4132 // Assignment operator
4133 Magick::Image& Magick::Image::operator=( const Magick::Image &image_ )
4134 {
4135   if( this != &image_ )
4136     {
4137       {
4138         Lock( &image_._imgRef->_mutexLock );
4139         ++image_._imgRef->_refCount;
4140       }
4141
4142       bool doDelete = false;
4143       {
4144         Lock( &_imgRef->_mutexLock );
4145         if ( --_imgRef->_refCount == 0 )
4146           doDelete = true;
4147       }
4148
4149       if ( doDelete )
4150         {
4151           // Delete old image reference with associated image and options.
4152           delete _imgRef;
4153           _imgRef = 0;
4154         }
4155       // Use new image reference
4156       _imgRef = image_._imgRef;
4157     }
4158
4159   return *this;
4160 }
4161
4162 //////////////////////////////////////////////////////////////////////    
4163 //
4164 // Low-level Pixel Access Routines
4165 //
4166 // Also see the Pixels class, which provides support for multiple
4167 // cache views. The low-level pixel access routines in the Image
4168 // class are provided in order to support backward compatability.
4169 //
4170 //////////////////////////////////////////////////////////////////////
4171
4172 // Transfers read-only pixels from the image to the pixel cache as
4173 // defined by the specified region
4174 const Magick::Quantum* Magick::Image::getConstPixels
4175   ( const ssize_t x_, const ssize_t y_,
4176     const size_t columns_,
4177     const size_t rows_ ) const
4178 {
4179   ExceptionInfo exceptionInfo;
4180   GetExceptionInfo( &exceptionInfo );
4181   const Quantum* p = (*GetVirtualPixels)( constImage(),
4182                                                 x_, y_,
4183                                                 columns_, rows_,
4184                                                 &exceptionInfo );
4185   throwException( exceptionInfo );
4186   (void) DestroyExceptionInfo( &exceptionInfo );
4187   return p;
4188 }
4189
4190 // Obtain read-only pixel associated pixels channels
4191 const void* Magick::Image::getConstMetacontent ( void ) const
4192 {
4193   const void* result = GetVirtualMetacontent( constImage() );
4194
4195   if( !result )
4196     throwImageException();
4197
4198   return result;
4199 }
4200
4201 // Obtain image pixel associated pixels channels
4202 void* Magick::Image::getMetacontent ( void )
4203 {
4204   void* result = GetAuthenticMetacontent( image() );
4205
4206   if( !result )
4207     throwImageException();
4208
4209   return ( result );
4210 }
4211
4212 // Transfers pixels from the image to the pixel cache as defined
4213 // by the specified region. Modified pixels may be subsequently
4214 // transferred back to the image via syncPixels.
4215 Magick::Quantum* Magick::Image::getPixels ( const ssize_t x_, const ssize_t y_,
4216                                                 const size_t columns_,
4217                                                 const size_t rows_ )
4218 {
4219   modifyImage();
4220   ExceptionInfo exceptionInfo;
4221   GetExceptionInfo( &exceptionInfo );
4222   Quantum* result = (*GetAuthenticPixels)( image(),
4223                                            x_, y_,
4224                                            columns_, rows_, &exceptionInfo );
4225   throwException( exceptionInfo );
4226   (void) DestroyExceptionInfo( &exceptionInfo );
4227
4228   return result;
4229 }
4230
4231 // Allocates a pixel cache region to store image pixels as defined
4232 // by the region rectangle.  This area is subsequently transferred
4233 // from the pixel cache to the image via syncPixels.
4234 Magick::Quantum* Magick::Image::setPixels ( const ssize_t x_, const ssize_t y_,
4235                                                 const size_t columns_,
4236                                                 const size_t rows_ )
4237 {
4238   modifyImage();
4239   ExceptionInfo exceptionInfo;
4240   GetExceptionInfo( &exceptionInfo );
4241   Quantum* result = (*QueueAuthenticPixels)( image(),
4242                                            x_, y_,
4243                                            columns_, rows_, &exceptionInfo );
4244   throwException( exceptionInfo );
4245   (void) DestroyExceptionInfo( &exceptionInfo );
4246
4247   return result;
4248 }
4249
4250 // Transfers the image cache pixels to the image.
4251 void Magick::Image::syncPixels ( void )
4252 {
4253   ExceptionInfo exceptionInfo;
4254   GetExceptionInfo( &exceptionInfo );
4255   (*SyncAuthenticPixels)( image(), &exceptionInfo );
4256   throwException( exceptionInfo );
4257   (void) DestroyExceptionInfo( &exceptionInfo );
4258 }
4259
4260 // Transfers one or more pixel components from a buffer or file
4261 // into the image pixel cache of an image.
4262 // Used to support image decoders.
4263 void Magick::Image::readPixels ( const Magick::QuantumType quantum_,
4264                                  const unsigned char *source_ )
4265 {
4266   QuantumInfo
4267     *quantum_info;
4268
4269   quantum_info=AcquireQuantumInfo(imageInfo(),image());
4270   ExceptionInfo exceptionInfo;
4271   GetExceptionInfo( &exceptionInfo );
4272   ImportQuantumPixels(image(),(MagickCore::CacheView *) NULL,quantum_info,
4273     quantum_,source_, &exceptionInfo);
4274   throwException( exceptionInfo );
4275   (void) DestroyExceptionInfo( &exceptionInfo );
4276   quantum_info=DestroyQuantumInfo(quantum_info);
4277 }
4278
4279 // Transfers one or more pixel components from the image pixel
4280 // cache to a buffer or file.
4281 // Used to support image encoders.
4282 void Magick::Image::writePixels ( const Magick::QuantumType quantum_,
4283                                   unsigned char *destination_ )
4284 {
4285   QuantumInfo
4286     *quantum_info;
4287
4288   quantum_info=AcquireQuantumInfo(imageInfo(),image());
4289   ExceptionInfo exceptionInfo;
4290   GetExceptionInfo( &exceptionInfo );
4291   ExportQuantumPixels(image(),(MagickCore::CacheView *) NULL,quantum_info,
4292     quantum_,destination_, &exceptionInfo);
4293   quantum_info=DestroyQuantumInfo(quantum_info);
4294   throwException( exceptionInfo );
4295   (void) DestroyExceptionInfo( &exceptionInfo );
4296 }
4297
4298 /////////////////////////////////////////////////////////////////////
4299 //
4300 // No end-user methods beyond this point
4301 //
4302 /////////////////////////////////////////////////////////////////////
4303
4304
4305 //
4306 // Construct using existing image and default options
4307 //
4308 Magick::Image::Image ( MagickCore::Image* image_ )
4309   : _imgRef(new ImageRef( image_))
4310 {
4311 }
4312
4313 // Get Magick::Options*
4314 Magick::Options* Magick::Image::options( void )
4315 {
4316   return _imgRef->options();
4317 }
4318 const Magick::Options* Magick::Image::constOptions( void ) const
4319 {
4320   return _imgRef->options();
4321 }
4322
4323 // Get MagickCore::Image*
4324 MagickCore::Image*& Magick::Image::image( void )
4325 {
4326   return _imgRef->image();
4327 }
4328 const MagickCore::Image* Magick::Image::constImage( void ) const
4329 {
4330   return _imgRef->image();
4331 }
4332
4333 // Get ImageInfo *
4334 MagickCore::ImageInfo* Magick::Image::imageInfo( void )
4335 {
4336   return _imgRef->options()->imageInfo();
4337 }
4338 const MagickCore::ImageInfo * Magick::Image::constImageInfo( void ) const
4339 {
4340   return _imgRef->options()->imageInfo();
4341 }
4342
4343 // Get QuantizeInfo *
4344 MagickCore::QuantizeInfo* Magick::Image::quantizeInfo( void )
4345 {
4346   return _imgRef->options()->quantizeInfo();
4347 }
4348 const MagickCore::QuantizeInfo * Magick::Image::constQuantizeInfo( void ) const
4349 {
4350   return _imgRef->options()->quantizeInfo();
4351 }
4352
4353 //
4354 // Replace current image
4355 //
4356 MagickCore::Image * Magick::Image::replaceImage
4357   ( MagickCore::Image* replacement_ )
4358 {
4359   MagickCore::Image* image;
4360   
4361   if( replacement_ )
4362     image = replacement_;
4363   else
4364     {
4365       ExceptionInfo exceptionInfo;
4366       GetExceptionInfo( &exceptionInfo );
4367       image = AcquireImage(constImageInfo(), &exceptionInfo);
4368       throwException( exceptionInfo );
4369       (void) DestroyExceptionInfo( &exceptionInfo );
4370     }
4371
4372   {
4373     Lock( &_imgRef->_mutexLock );
4374
4375     if ( _imgRef->_refCount == 1 )
4376       {
4377         // We own the image, just replace it, and de-register
4378         _imgRef->id( -1 );
4379         _imgRef->image(image);
4380       }
4381     else
4382       {
4383         // We don't own the image, dereference and replace with copy
4384         --_imgRef->_refCount;
4385         _imgRef = new ImageRef( image, constOptions() );
4386       }
4387   }
4388
4389   return _imgRef->_image;
4390 }
4391
4392 //
4393 // Prepare to modify image or image options
4394 // Replace current image and options with copy if reference count > 1
4395 //
4396 void Magick::Image::modifyImage( void )
4397 {
4398   {
4399     Lock( &_imgRef->_mutexLock );
4400     if ( _imgRef->_refCount == 1 )
4401       {
4402         // De-register image and return
4403         _imgRef->id( -1 );
4404         return;
4405       }
4406   }
4407
4408   ExceptionInfo exceptionInfo;
4409   GetExceptionInfo( &exceptionInfo );
4410   replaceImage( CloneImage( image(),
4411                             0, // columns
4412                             0, // rows
4413                             MagickTrue, // orphan
4414                             &exceptionInfo) );
4415   throwException( exceptionInfo );
4416   (void) DestroyExceptionInfo( &exceptionInfo );
4417   return;
4418 }
4419
4420 //
4421 // Test for an ImageMagick reported error and throw exception if one
4422 // has been reported.  Secretly resets image->exception back to default
4423 // state even though this method is const.
4424 //
4425 void Magick::Image::throwImageException( void ) const
4426 {
4427   // Throw C++ exception while resetting Image exception to default state
4428 }
4429
4430 // Register image with image registry or obtain registration id
4431 ssize_t Magick::Image::registerId( void )
4432 {
4433   Lock( &_imgRef->_mutexLock );
4434   if( _imgRef->id() < 0 )
4435     {
4436       char id[MaxTextExtent];
4437       ExceptionInfo exceptionInfo;
4438       GetExceptionInfo( &exceptionInfo );
4439       _imgRef->id(_imgRef->id()+1);
4440       sprintf(id,"%.20g\n",(double) _imgRef->id());
4441       SetImageRegistry(ImageRegistryType, id, image(), &exceptionInfo);
4442       throwException( exceptionInfo );
4443   (void) DestroyExceptionInfo( &exceptionInfo );
4444     }
4445   return _imgRef->id();
4446 }
4447
4448 // Unregister image from image registry
4449 void Magick::Image::unregisterId( void )
4450 {
4451   modifyImage();
4452   _imgRef->id( -1 );
4453 }
4454
4455 //
4456 // Create a local wrapper around MagickCoreTerminus
4457 //
4458 namespace Magick
4459 {
4460   extern "C" {
4461     void MagickPlusPlusDestroyMagick(void);
4462   }
4463 }
4464
4465 void Magick::MagickPlusPlusDestroyMagick(void)
4466 {
4467   if (magick_initialized)
4468     {
4469       magick_initialized=false;
4470       MagickCore::MagickCoreTerminus();
4471     }
4472 }
4473
4474 // C library initialization routine
4475 void MagickPPExport Magick::InitializeMagick(const char *path_)
4476 {
4477   MagickCore::MagickCoreGenesis(path_,MagickFalse);
4478   if (!magick_initialized)
4479     magick_initialized=true;
4480 }
4481
4482 //
4483 // Cleanup class to ensure that ImageMagick singletons are destroyed
4484 // so as to avoid any resemblence to a memory leak (which seems to
4485 // confuse users)
4486 //
4487 namespace Magick
4488 {
4489
4490   class MagickCleanUp
4491   {
4492   public:
4493     MagickCleanUp( void );
4494     ~MagickCleanUp( void );
4495   };
4496
4497   // The destructor for this object is invoked when the destructors for
4498   // static objects in this translation unit are invoked.
4499   static MagickCleanUp magickCleanUpGuard;
4500 }
4501
4502 Magick::MagickCleanUp::MagickCleanUp ( void )
4503 {
4504   // Don't even think about invoking InitializeMagick here!
4505 }
4506
4507 Magick::MagickCleanUp::~MagickCleanUp ( void )
4508 {
4509   MagickPlusPlusDestroyMagick();
4510 }