]> 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 =
2696      GetImageClipMask( constImage(), &exceptionInfo );
2697    throwException( exceptionInfo );
2698    (void) DestroyExceptionInfo( &exceptionInfo );
2699    return Magick::Image( image );
2700 }
2701
2702 void Magick::Image::colorFuzz ( const double fuzz_ )
2703 {
2704   modifyImage();
2705   image()->fuzz = fuzz_;
2706   options()->colorFuzz( fuzz_ );
2707 }
2708 double Magick::Image::colorFuzz ( void ) const
2709 {
2710   return constOptions()->colorFuzz( );
2711 }
2712
2713 // Set color in colormap at index
2714 void Magick::Image::colorMap ( const size_t index_,
2715                                const Color &color_ )
2716 {
2717   MagickCore::Image* imageptr = image();
2718
2719   if (index_ > (MaxColormapSize-1) )
2720     throwExceptionExplicit( OptionError,
2721                             "Colormap index must be less than MaxColormapSize" );
2722   
2723   if ( !color_.isValid() )
2724     throwExceptionExplicit( OptionError,
2725                             "Color argument is invalid");
2726   modifyImage();
2727
2728   // Ensure that colormap size is large enough
2729   if ( colorMapSize() < (index_+1) )
2730     colorMapSize( index_ + 1 );
2731
2732   // Set color at index in colormap
2733   (imageptr->colormap)[index_] = color_;
2734 }
2735 // Return color in colormap at index
2736 Magick::Color Magick::Image::colorMap ( const size_t index_ ) const
2737 {
2738   const MagickCore::Image* imageptr = constImage();
2739
2740   if ( !imageptr->colormap )
2741     throwExceptionExplicit( OptionError,
2742                             "Image does not contain a colormap");
2743
2744   if ( index_ > imageptr->colors-1 )
2745     throwExceptionExplicit( OptionError,
2746                             "Index out of range");
2747
2748   return Magick::Color( (imageptr->colormap)[index_] );
2749 }
2750
2751 // Colormap size (number of colormap entries)
2752 void Magick::Image::colorMapSize ( const size_t entries_ )
2753 {
2754   if (entries_ >MaxColormapSize )
2755     throwExceptionExplicit( OptionError,
2756                             "Colormap entries must not exceed MaxColormapSize" );
2757
2758   modifyImage();
2759
2760   MagickCore::Image* imageptr = image();
2761
2762   if( !imageptr->colormap )
2763     {
2764       // Allocate colormap
2765       imageptr->colormap =
2766         static_cast<PixelInfo*>(AcquireMagickMemory(entries_*sizeof(PixelInfo)));
2767       imageptr->colors = 0;
2768     }
2769   else if ( entries_ > imageptr->colors )
2770     {
2771       // Re-allocate colormap
2772       imageptr->colormap=(PixelInfo *)
2773         ResizeMagickMemory(imageptr->colormap,(entries_)*sizeof(PixelInfo));
2774     }
2775
2776   // Initialize any new colormap entries as all black
2777   Color black(0,0,0);
2778   for( size_t i=imageptr->colors; i<(entries_-1); i++ )
2779     (imageptr->colormap)[i] = black;
2780
2781   imageptr->colors = entries_;
2782 }
2783 size_t Magick::Image::colorMapSize ( void )
2784 {
2785   const MagickCore::Image* imageptr = constImage();
2786
2787   if ( !imageptr->colormap )
2788     throwExceptionExplicit( OptionError,
2789                             "Image does not contain a colormap");
2790
2791   return imageptr->colors;
2792 }
2793
2794 // Image colorspace
2795 void Magick::Image::colorSpace( const ColorspaceType colorSpace_ )
2796 {
2797   // Nothing to do?
2798   if ( image()->colorspace == colorSpace_ )
2799     return;
2800
2801   modifyImage();
2802
2803   ExceptionInfo exceptionInfo;
2804   GetExceptionInfo( &exceptionInfo );
2805   if ( colorSpace_ != RGBColorspace &&
2806        colorSpace_ != sRGBColorspace &&
2807        colorSpace_ != TransparentColorspace &&
2808        colorSpace_ != GRAYColorspace )
2809     {
2810       if (image()->colorspace != RGBColorspace &&
2811           image()->colorspace != sRGBColorspace &&
2812           image()->colorspace != TransparentColorspace &&
2813           image()->colorspace != GRAYColorspace)
2814         {
2815           /* Transform to RGB colorspace as intermediate step */
2816           TransformRGBImage( image(), image()->colorspace, &exceptionInfo );
2817           throwImageException();
2818         }
2819       /* Transform to final non-RGB colorspace */
2820       RGBTransformImage( image(), colorSpace_, &exceptionInfo );
2821       throwException( exceptionInfo );
2822       (void) DestroyExceptionInfo( &exceptionInfo );
2823       return;
2824     }
2825
2826   if ( colorSpace_ == RGBColorspace ||
2827        colorSpace_ == sRGBColorspace ||
2828        colorSpace_ == TransparentColorspace ||
2829        colorSpace_ == GRAYColorspace )
2830     {
2831       /* Transform to a RGB-type colorspace */
2832       TransformRGBImage( image(), image()->colorspace, &exceptionInfo );
2833       throwException( exceptionInfo );
2834       (void) DestroyExceptionInfo( &exceptionInfo );
2835       return;
2836     }
2837   throwException( exceptionInfo );
2838   (void) DestroyExceptionInfo( &exceptionInfo );
2839 }
2840 Magick::ColorspaceType Magick::Image::colorSpace ( void ) const
2841 {
2842   return constImage()->colorspace;
2843 }
2844
2845 // Set image colorspace type.
2846 void Magick::Image::colorspaceType( const ColorspaceType colorSpace_ )
2847 {
2848   modifyImage();
2849   options()->colorspaceType( colorSpace_ );
2850 }
2851 Magick::ColorspaceType Magick::Image::colorspaceType ( void ) const
2852 {
2853   return constOptions()->colorspaceType();
2854 }
2855
2856
2857 // Comment string
2858 void Magick::Image::comment ( const std::string &comment_ )
2859 {
2860   modifyImage();
2861   ExceptionInfo exceptionInfo;
2862   GetExceptionInfo( &exceptionInfo );
2863   SetImageProperty( image(), "Comment", NULL, &exceptionInfo );
2864   if ( comment_.length() > 0 )
2865     SetImageProperty( image(), "Comment", comment_.c_str(), &exceptionInfo );
2866   throwException( exceptionInfo );
2867   (void) DestroyExceptionInfo( &exceptionInfo );
2868 }
2869 std::string Magick::Image::comment ( void ) const
2870 {
2871   ExceptionInfo exceptionInfo;
2872   GetExceptionInfo( &exceptionInfo );
2873   const char *value = GetImageProperty( constImage(), "Comment",
2874     &exceptionInfo );
2875   throwException( exceptionInfo );
2876   (void) DestroyExceptionInfo( &exceptionInfo );
2877
2878   if ( value )
2879     return std::string( value );
2880
2881   return std::string(); // Intentionally no exception
2882 }
2883
2884 // Composition operator to be used when composition is implicitly used
2885 // (such as for image flattening).
2886 void Magick::Image::compose (const CompositeOperator compose_)
2887 {
2888   image()->compose=compose_;
2889 }
2890
2891 Magick::CompositeOperator Magick::Image::compose ( void ) const
2892 {
2893   return constImage()->compose;
2894 }
2895
2896 // Compression algorithm
2897 void Magick::Image::compressType ( const CompressionType compressType_ )
2898 {
2899   modifyImage();
2900   image()->compression = compressType_;
2901   options()->compressType( compressType_ );
2902 }
2903 Magick::CompressionType Magick::Image::compressType ( void ) const
2904 {
2905   return constImage()->compression;
2906 }
2907
2908 // Enable printing of debug messages from ImageMagick
2909 void Magick::Image::debug ( const bool flag_ )
2910 {
2911   modifyImage();
2912   options()->debug( flag_ );
2913 }
2914 bool Magick::Image::debug ( void ) const
2915 {
2916   return constOptions()->debug();
2917 }
2918
2919 // Tagged image format define (set/access coder-specific option) The
2920 // magick_ option specifies the coder the define applies to.  The key_
2921 // option provides the key specific to that coder.  The value_ option
2922 // provides the value to set (if any). See the defineSet() method if the
2923 // key must be removed entirely.
2924 void Magick::Image::defineValue ( const std::string &magick_,
2925                                   const std::string &key_,
2926                                   const std::string &value_ )
2927 {
2928   modifyImage();
2929   std::string format = magick_ + ":" + key_;
2930   std::string option = value_;
2931   (void) SetImageOption ( imageInfo(), format.c_str(), option.c_str() );
2932 }
2933 std::string Magick::Image::defineValue ( const std::string &magick_,
2934                                          const std::string &key_ ) const
2935 {
2936   std::string definition = magick_ + ":" + key_;
2937   const char *option =
2938     GetImageOption ( constImageInfo(), definition.c_str() );
2939   if (option)
2940     return std::string( option );
2941   return std::string( );
2942 }
2943
2944 // Tagged image format define. Similar to the defineValue() method
2945 // except that passing the flag_ value 'true' creates a value-less
2946 // define with that format and key. Passing the flag_ value 'false'
2947 // removes any existing matching definition. The method returns 'true'
2948 // if a matching key exists, and 'false' if no matching key exists.
2949 void Magick::Image::defineSet ( const std::string &magick_,
2950                                 const std::string &key_,
2951                                 bool flag_ )
2952 {
2953   modifyImage();
2954   std::string definition = magick_ + ":" + key_;
2955   if (flag_)
2956     {
2957       (void) SetImageOption ( imageInfo(), definition.c_str(),  "" );
2958     }
2959   else
2960     {
2961       DeleteImageOption( imageInfo(), definition.c_str() );
2962     }
2963 }
2964 bool Magick::Image::defineSet ( const std::string &magick_,
2965                                 const std::string &key_ ) const
2966 {
2967   std::string key = magick_ + ":" + key_;
2968   const char *option =
2969     GetImageOption ( constImageInfo(), key.c_str() );
2970   if (option)
2971     return true;
2972   return false;
2973 }
2974
2975 // Pixel resolution
2976 void Magick::Image::density ( const Geometry &density_ )
2977 {
2978   modifyImage();
2979   options()->density( density_ );
2980   if ( density_.isValid() )
2981     {
2982       image()->resolution.x = density_.width();
2983       if ( density_.height() != 0 )
2984         {
2985           image()->resolution.y = density_.height();
2986         }
2987       else
2988         {
2989           image()->resolution.y = density_.width();
2990         }
2991     }
2992   else
2993     {
2994       // Reset to default
2995       image()->resolution.x = 0;
2996       image()->resolution.y = 0;
2997     }
2998 }
2999 Magick::Geometry Magick::Image::density ( void ) const
3000 {
3001   if (isValid())
3002     {
3003       ssize_t x_resolution=72;
3004       ssize_t y_resolution=72;
3005
3006       if (constImage()->resolution.x > 0.0)
3007         x_resolution=static_cast<ssize_t>(constImage()->resolution.x + 0.5);
3008
3009       if (constImage()->resolution.y > 0.0)
3010         y_resolution=static_cast<ssize_t>(constImage()->resolution.y + 0.5);
3011
3012       return Geometry(x_resolution,y_resolution);
3013     }
3014
3015   return constOptions()->density( );
3016 }
3017
3018 // Image depth (bits allocated to red/green/blue components)
3019 void Magick::Image::depth ( const size_t depth_ )
3020 {
3021   size_t depth = depth_;
3022
3023   if (depth > MAGICKCORE_QUANTUM_DEPTH)
3024     depth=MAGICKCORE_QUANTUM_DEPTH;
3025
3026   modifyImage();
3027   image()->depth=depth;
3028   options()->depth( depth );
3029 }
3030 size_t Magick::Image::depth ( void ) const
3031 {
3032   return constImage()->depth;
3033 }
3034
3035 std::string Magick::Image::directory ( void ) const
3036 {
3037   if ( constImage()->directory )
3038     return std::string( constImage()->directory );
3039
3040   throwExceptionExplicit( CorruptImageWarning,
3041                           "Image does not contain a directory");
3042
3043   return std::string();
3044 }
3045
3046 // Endianness (little like Intel or big like SPARC) for image
3047 // formats which support endian-specific options.
3048 void Magick::Image::endian ( const Magick::EndianType endian_ )
3049 {
3050   modifyImage();
3051   options()->endian( endian_ );
3052   image()->endian = endian_;
3053 }
3054 Magick::EndianType Magick::Image::endian ( void ) const
3055 {
3056   return constImage()->endian;
3057 }
3058
3059 // EXIF profile (BLOB)
3060 void Magick::Image::exifProfile( const Magick::Blob &exifProfile_ )
3061 {
3062   modifyImage();
3063   if ( exifProfile_.data() != 0 )
3064     {
3065       StringInfo * exif_profile = AcquireStringInfo( exifProfile_.length() );
3066       SetStringInfoDatum(exif_profile ,(unsigned char *) exifProfile_.data());
3067       ExceptionInfo exceptionInfo;
3068       GetExceptionInfo( &exceptionInfo );
3069       (void) SetImageProfile( image(), "exif", exif_profile, &exceptionInfo);
3070       exif_profile =DestroyStringInfo( exif_profile );
3071       throwException( exceptionInfo );
3072       (void) DestroyExceptionInfo( &exceptionInfo );
3073     }
3074 }
3075 Magick::Blob Magick::Image::exifProfile( void ) const
3076 {
3077   const StringInfo * exif_profile = GetImageProfile( constImage(), "exif" );
3078   if ( exif_profile == (StringInfo *) NULL)
3079     return Blob( 0, 0 );
3080   return Blob(GetStringInfoDatum(exif_profile),GetStringInfoLength(exif_profile));
3081
3082
3083 // Image file name
3084 void Magick::Image::fileName ( const std::string &fileName_ )
3085 {
3086   modifyImage();
3087
3088   fileName_.copy( image()->filename,
3089                   sizeof(image()->filename) - 1 );
3090   image()->filename[ fileName_.length() ] = 0; // Null terminate
3091   
3092   options()->fileName( fileName_ );
3093   
3094 }
3095 std::string Magick::Image::fileName ( void ) const
3096 {
3097   return constOptions()->fileName( );
3098 }
3099
3100 // Image file size
3101 off_t Magick::Image::fileSize ( void ) const
3102 {
3103   return (off_t) GetBlobSize( constImage() );
3104 }
3105
3106 // Color to use when drawing inside an object
3107 void Magick::Image::fillColor ( const Magick::Color &fillColor_ )
3108 {
3109   modifyImage();
3110   options()->fillColor(fillColor_);
3111 }
3112 Magick::Color Magick::Image::fillColor ( void ) const
3113 {
3114   return constOptions()->fillColor();
3115 }
3116
3117 // Rule to use when filling drawn objects
3118 void Magick::Image::fillRule ( const Magick::FillRule &fillRule_ )
3119 {
3120   modifyImage();
3121   options()->fillRule(fillRule_);
3122 }
3123 Magick::FillRule Magick::Image::fillRule ( void ) const
3124 {
3125   return constOptions()->fillRule();
3126 }
3127
3128 // Pattern to use while filling drawn objects.
3129 void Magick::Image::fillPattern ( const Image &fillPattern_ )
3130 {
3131   modifyImage();
3132   if(fillPattern_.isValid())
3133     options()->fillPattern( fillPattern_.constImage() );
3134   else
3135     options()->fillPattern( static_cast<MagickCore::Image*>(NULL) );
3136 }
3137 Magick::Image  Magick::Image::fillPattern ( void  ) const
3138 {
3139   // FIXME: This is inordinately innefficient
3140   Image texture;
3141   
3142   const MagickCore::Image* tmpTexture = constOptions()->fillPattern( );
3143
3144   if ( tmpTexture )
3145     {
3146       ExceptionInfo exceptionInfo;
3147       GetExceptionInfo( &exceptionInfo );
3148       MagickCore::Image* image =
3149         CloneImage( tmpTexture,
3150                     0, // columns
3151                     0, // rows
3152                     MagickTrue, // orphan
3153                     &exceptionInfo);
3154       texture.replaceImage( image );
3155       throwException( exceptionInfo );
3156       (void) DestroyExceptionInfo( &exceptionInfo );
3157     }
3158   return texture;
3159 }
3160
3161 // Filter used by zoom
3162 void Magick::Image::filterType ( const Magick::FilterTypes filterType_ )
3163 {
3164   modifyImage();
3165   image()->filter = filterType_;
3166 }
3167 Magick::FilterTypes Magick::Image::filterType ( void ) const
3168 {
3169   return constImage()->filter;
3170 }
3171
3172 // Font name
3173 void Magick::Image::font ( const std::string &font_ )
3174 {
3175   modifyImage();
3176   options()->font( font_ );
3177 }
3178 std::string Magick::Image::font ( void ) const
3179 {
3180   return constOptions()->font( );
3181 }
3182
3183 // Font point size
3184 void Magick::Image::fontPointsize ( const double pointSize_ )
3185 {
3186   modifyImage();
3187   options()->fontPointsize( pointSize_ );
3188 }
3189 double Magick::Image::fontPointsize ( void ) const
3190 {
3191   return constOptions()->fontPointsize( );
3192 }
3193
3194 // Font type metrics
3195 void Magick::Image::fontTypeMetrics( const std::string &text_,
3196                                      TypeMetric *metrics )
3197 {
3198   DrawInfo *drawInfo = options()->drawInfo();
3199   drawInfo->text = const_cast<char *>(text_.c_str());
3200   ExceptionInfo exceptionInfo;
3201   GetExceptionInfo( &exceptionInfo );
3202   GetTypeMetrics( image(), drawInfo, &(metrics->_typeMetric), &exceptionInfo );
3203   drawInfo->text = 0;
3204   throwException( exceptionInfo );
3205   (void) DestroyExceptionInfo( &exceptionInfo );
3206 }
3207
3208 // Image format string
3209 std::string Magick::Image::format ( void ) const
3210 {
3211   ExceptionInfo exceptionInfo;
3212   GetExceptionInfo( &exceptionInfo );
3213   const MagickInfo * magick_info
3214     = GetMagickInfo( constImage()->magick, &exceptionInfo);
3215   throwException( exceptionInfo );
3216   (void) DestroyExceptionInfo( &exceptionInfo );
3217
3218   if (( magick_info != 0 ) && 
3219       ( *magick_info->description != '\0' ))
3220     return std::string(magick_info->description);
3221
3222   throwExceptionExplicit( CorruptImageWarning,
3223                           "Unrecognized image magick type" );
3224   return std::string();
3225 }
3226
3227 // Gamma adjustment
3228 double Magick::Image::gamma ( void ) const
3229 {
3230   return constImage()->gamma;
3231 }
3232
3233 Magick::Geometry Magick::Image::geometry ( void ) const
3234 {
3235   if ( constImage()->geometry )
3236   {
3237     return Geometry(constImage()->geometry);
3238   }
3239
3240   throwExceptionExplicit( OptionWarning,
3241                           "Image does not contain a geometry");
3242
3243   return Geometry();
3244 }
3245
3246 void Magick::Image::gifDisposeMethod ( const size_t disposeMethod_ )
3247 {
3248   modifyImage();
3249   image()->dispose = (DisposeType) disposeMethod_;
3250 }
3251 size_t Magick::Image::gifDisposeMethod ( void ) const
3252 {
3253   // FIXME: It would be better to return an enumeration
3254   return constImage()->dispose;
3255 }
3256
3257 // ICC ICM color profile (BLOB)
3258 void Magick::Image::iccColorProfile( const Magick::Blob &colorProfile_ )
3259 {
3260   profile("icm",colorProfile_);
3261 }
3262 Magick::Blob Magick::Image::iccColorProfile( void ) const
3263 {
3264   const StringInfo * color_profile = GetImageProfile( constImage(), "icc" );
3265   if ( color_profile == (StringInfo *) NULL)
3266     return Blob( 0, 0 );
3267   return Blob( GetStringInfoDatum(color_profile), GetStringInfoLength(color_profile) );
3268 }
3269
3270 void Magick::Image::interlaceType ( const Magick::InterlaceType interlace_ )
3271 {
3272   modifyImage();
3273   image()->interlace = interlace_;
3274   options()->interlaceType ( interlace_ );
3275 }
3276 Magick::InterlaceType Magick::Image::interlaceType ( void ) const
3277 {
3278   return constImage()->interlace;
3279 }
3280
3281 // IPTC profile (BLOB)
3282 void Magick::Image::iptcProfile( const Magick::Blob &iptcProfile_ )
3283 {
3284   modifyImage();
3285   if (  iptcProfile_.data() != 0 )
3286     {
3287       StringInfo * iptc_profile = AcquireStringInfo( iptcProfile_.length() );
3288       SetStringInfoDatum(iptc_profile ,(unsigned char *) iptcProfile_.data());
3289       ExceptionInfo exceptionInfo;
3290       GetExceptionInfo( &exceptionInfo );
3291       (void) SetImageProfile( image(), "iptc", iptc_profile, &exceptionInfo);
3292       iptc_profile =DestroyStringInfo( iptc_profile );
3293       throwException( exceptionInfo );
3294       (void) DestroyExceptionInfo( &exceptionInfo );
3295     }
3296 }
3297 Magick::Blob Magick::Image::iptcProfile( void ) const
3298 {
3299   const StringInfo * iptc_profile = GetImageProfile( constImage(), "iptc" );
3300   if ( iptc_profile == (StringInfo *) NULL)
3301     return Blob( 0, 0 );
3302   return Blob( GetStringInfoDatum(iptc_profile), GetStringInfoLength(iptc_profile));
3303 }
3304
3305 // Does object contain valid image?
3306 void Magick::Image::isValid ( const bool isValid_ )
3307 {
3308   if ( !isValid_ )
3309     {
3310       delete _imgRef;
3311       _imgRef = new ImageRef;
3312     }
3313   else if ( !isValid() )
3314     {
3315       // Construct with single-pixel black image to make
3316       // image valid.  This is an obvious hack.
3317       size( Geometry(1,1) );
3318       read( "xc:#000000" );
3319     }
3320 }
3321
3322 bool Magick::Image::isValid ( void ) const
3323 {
3324   if ( rows() && columns() )
3325     return true;
3326
3327   return false;
3328 }
3329
3330 // Label image
3331 void Magick::Image::label ( const std::string &label_ )
3332 {
3333   modifyImage();
3334   ExceptionInfo exceptionInfo;
3335   GetExceptionInfo( &exceptionInfo );
3336   SetImageProperty ( image(), "Label", NULL, &exceptionInfo );
3337   if ( label_.length() > 0 )
3338     SetImageProperty ( image(), "Label", label_.c_str(), &exceptionInfo );
3339   throwException( exceptionInfo );
3340   (void) DestroyExceptionInfo( &exceptionInfo );
3341 }
3342 std::string Magick::Image::label ( void ) const
3343 {
3344   ExceptionInfo exceptionInfo;
3345   GetExceptionInfo( &exceptionInfo );
3346   const char *value = GetImageProperty( constImage(), "Label", &exceptionInfo );
3347   throwException( exceptionInfo );
3348   (void) DestroyExceptionInfo( &exceptionInfo );
3349
3350   if ( value )
3351     return std::string( value );
3352
3353   return std::string();
3354 }
3355
3356 void Magick::Image::magick ( const std::string &magick_ )
3357 {
3358   modifyImage();
3359
3360   magick_.copy( image()->magick,
3361                 sizeof(image()->magick) - 1 );
3362   image()->magick[ magick_.length() ] = 0;
3363   
3364   options()->magick( magick_ );
3365 }
3366 std::string Magick::Image::magick ( void ) const
3367 {
3368   if ( *(constImage()->magick) != '\0' )
3369     return std::string(constImage()->magick);
3370
3371   return constOptions()->magick( );
3372 }
3373
3374 void Magick::Image::matte ( const bool matteFlag_ )
3375 {
3376   modifyImage();
3377
3378   // If matte channel is requested, but image doesn't already have a
3379   // matte channel, then create an opaque matte channel.  Likewise, if
3380   // the image already has a matte channel but a matte channel is not
3381   // desired, then set the matte channel to opaque.
3382   ExceptionInfo exceptionInfo;
3383   GetExceptionInfo( &exceptionInfo );
3384   if ((matteFlag_ && !constImage()->matte) ||
3385       (constImage()->matte && !matteFlag_))
3386     SetImageAlpha(image(),OpaqueAlpha,&exceptionInfo);
3387   throwException( exceptionInfo );
3388   (void) DestroyExceptionInfo( &exceptionInfo );
3389
3390   image()->matte = (MagickBooleanType) matteFlag_;
3391 }
3392 bool Magick::Image::matte ( void ) const
3393 {
3394   if ( constImage()->matte )
3395     return true;
3396   else
3397     return false;
3398 }
3399
3400 void Magick::Image::matteColor ( const Color &matteColor_ )
3401 {
3402   modifyImage();
3403   
3404   if ( matteColor_.isValid() )
3405     {
3406       image()->matte_color = matteColor_;
3407       options()->matteColor( matteColor_ );
3408     }
3409   else
3410     {
3411       // Set to default matte color
3412       Color tmpColor( "#BDBDBD" );
3413       image()->matte_color = tmpColor;
3414       options()->matteColor( tmpColor );
3415     }
3416 }
3417 Magick::Color Magick::Image::matteColor ( void ) const
3418 {
3419   return Color( ClampToQuantum( constImage()->matte_color.red ),
3420                 ClampToQuantum( constImage()->matte_color.green ),
3421                 ClampToQuantum( constImage()->matte_color.blue ) );
3422 }
3423
3424 double Magick::Image::meanErrorPerPixel ( void ) const
3425 {
3426   return(constImage()->error.mean_error_per_pixel);
3427 }
3428
3429 // Image modulus depth (minimum number of bits required to support
3430 // red/green/blue components without loss of accuracy)
3431 void Magick::Image::modulusDepth ( const size_t depth_ )
3432 {
3433   modifyImage();
3434   ExceptionInfo exceptionInfo;
3435   GetExceptionInfo( &exceptionInfo );
3436   SetImageDepth( image(), depth_, &exceptionInfo );
3437   throwException( exceptionInfo );
3438   (void) DestroyExceptionInfo( &exceptionInfo );
3439   options()->depth( depth_ );
3440 }
3441 size_t Magick::Image::modulusDepth ( void ) const
3442 {
3443   ExceptionInfo exceptionInfo;
3444   GetExceptionInfo( &exceptionInfo );
3445   size_t depth=GetImageDepth( constImage(), &exceptionInfo );
3446   throwException( exceptionInfo );
3447   (void) DestroyExceptionInfo( &exceptionInfo );
3448   return depth;
3449 }
3450
3451 void Magick::Image::monochrome ( const bool monochromeFlag_ )
3452 {
3453   modifyImage();
3454   options()->monochrome( monochromeFlag_ );
3455 }
3456 bool Magick::Image::monochrome ( void ) const
3457 {
3458   return constOptions()->monochrome( );
3459 }
3460
3461 Magick::Geometry Magick::Image::montageGeometry ( void ) const
3462 {
3463   if ( constImage()->montage )
3464     return Magick::Geometry(constImage()->montage);
3465
3466   throwExceptionExplicit( CorruptImageWarning,
3467                           "Image does not contain a montage" );
3468
3469   return Magick::Geometry();
3470 }
3471
3472 double Magick::Image::normalizedMaxError ( void ) const
3473 {
3474   return(constImage()->error.normalized_maximum_error);
3475 }
3476
3477 double Magick::Image::normalizedMeanError ( void ) const
3478 {
3479   return constImage()->error.normalized_mean_error;
3480 }
3481
3482 // Image orientation
3483 void Magick::Image::orientation ( const Magick::OrientationType orientation_ )
3484 {
3485   modifyImage();
3486   image()->orientation = orientation_;
3487 }
3488 Magick::OrientationType Magick::Image::orientation ( void ) const
3489 {
3490   return constImage()->orientation;
3491 }
3492
3493 void Magick::Image::penColor ( const Color &penColor_ )
3494 {
3495   modifyImage();
3496   options()->fillColor(penColor_);
3497   options()->strokeColor(penColor_);
3498 }
3499 Magick::Color Magick::Image::penColor ( void  ) const
3500 {
3501   return constOptions()->fillColor();
3502 }
3503
3504 void Magick::Image::penTexture ( const Image &penTexture_ )
3505 {
3506   modifyImage();
3507   if(penTexture_.isValid())
3508     options()->fillPattern( penTexture_.constImage() );
3509   else
3510     options()->fillPattern( static_cast<MagickCore::Image*>(NULL) );
3511 }
3512
3513 Magick::Image  Magick::Image::penTexture ( void  ) const
3514 {
3515   // FIXME: This is inordinately innefficient
3516   Image texture;
3517   
3518   const MagickCore::Image* tmpTexture = constOptions()->fillPattern( );
3519
3520   if ( tmpTexture )
3521     {
3522       ExceptionInfo exceptionInfo;
3523       GetExceptionInfo( &exceptionInfo );
3524       MagickCore::Image* image =
3525         CloneImage( tmpTexture,
3526                     0, // columns
3527                     0, // rows
3528                     MagickTrue, // orphan
3529                     &exceptionInfo);
3530       texture.replaceImage( image );
3531       throwException( exceptionInfo );
3532   (void) DestroyExceptionInfo( &exceptionInfo );
3533     }
3534   return texture;
3535 }
3536
3537 // Set the color of a pixel.
3538 void Magick::Image::pixelColor ( const ssize_t x_, const ssize_t y_,
3539                                  const Color &color_ )
3540 {
3541   // Test arguments to ensure they are within the image.
3542   if ( y_ > (ssize_t) rows() || x_ > (ssize_t) columns() )
3543     throwExceptionExplicit( OptionError,
3544             "Access outside of image boundary" );
3545       
3546   modifyImage();
3547
3548   // Set image to DirectClass
3549   classType( DirectClass );
3550
3551   // Get pixel view
3552   Pixels pixels(*this);
3553     // Set pixel value
3554   Quantum *pixel = pixels.get(x_, y_, 1, 1 );
3555   PixelInfo packet = color_;
3556   MagickCore::SetPixelInfoPixel(constImage(),&packet,pixel);
3557   // Tell ImageMagick that pixels have been updated
3558   pixels.sync();
3559
3560   return;
3561 }
3562
3563 // Get the color of a pixel
3564 Magick::Color Magick::Image::pixelColor ( const ssize_t x_,
3565                                           const ssize_t y_ ) const
3566 {
3567   ClassType storage_class;
3568   storage_class = classType();
3569   // DirectClass
3570   const Quantum* pixel = getConstPixels( x_, y_, 1, 1 );
3571   if ( pixel )
3572     {
3573       PixelInfo packet;
3574       MagickCore::GetPixelInfoPixel(constImage(),pixel,&packet);
3575       return Color( packet );
3576     }
3577
3578   return Color(); // invalid
3579 }
3580
3581 // Preferred size and location of an image canvas.
3582 void Magick::Image::page ( const Magick::Geometry &pageSize_ )
3583 {
3584   modifyImage();
3585   options()->page( pageSize_ );
3586   image()->page = pageSize_;
3587 }
3588 Magick::Geometry Magick::Image::page ( void ) const
3589 {
3590   return Geometry( constImage()->page.width,
3591                    constImage()->page.height,
3592                    AbsoluteValue(constImage()->page.x),
3593                    AbsoluteValue(constImage()->page.y),
3594                    constImage()->page.x < 0 ? true : false,
3595                    constImage()->page.y < 0 ? true : false);
3596 }
3597
3598 // Add a named profile to an image or remove a named profile by
3599 // passing an empty Blob (use default Blob constructor).
3600 // Valid names are:
3601 // "*", "8BIM", "ICM", "IPTC", or a generic profile name.
3602 void Magick::Image::profile( const std::string name_,
3603                              const Magick::Blob &profile_ )
3604 {
3605   modifyImage();
3606   ExceptionInfo exceptionInfo;
3607   GetExceptionInfo( &exceptionInfo );
3608   ssize_t result = ProfileImage( image(), name_.c_str(),
3609                              (unsigned char *)profile_.data(),
3610                              profile_.length(), &exceptionInfo);
3611   throwException( exceptionInfo );
3612   (void) DestroyExceptionInfo( &exceptionInfo );
3613
3614 }
3615
3616 // Retrieve a named profile from the image.
3617 // Valid names are:
3618 // "8BIM", "8BIMTEXT", "APP1", "APP1JPEG", "ICC", "ICM", & "IPTC" or
3619 // an existing generic profile name.
3620 Magick::Blob Magick::Image::profile( const std::string name_ ) const
3621 {
3622   const MagickCore::Image* image = constImage();
3623                                                                                 
3624   const StringInfo * profile = GetImageProfile( image, name_.c_str() );
3625                                                                                 
3626   if ( profile != (StringInfo *) NULL)
3627       return Blob( (void*) GetStringInfoDatum(profile), GetStringInfoLength(profile));
3628                                                                                 
3629   Blob blob;
3630   Image temp_image = *this;
3631   temp_image.write( &blob, name_ );
3632   return blob;
3633 }
3634
3635 void Magick::Image::quality ( const size_t quality_ )
3636 {
3637   modifyImage();
3638   image()->quality = quality_;
3639   options()->quality( quality_ );
3640 }
3641 size_t Magick::Image::quality ( void ) const
3642 {
3643   return constImage()->quality;
3644 }
3645
3646 void Magick::Image::quantizeColors ( const size_t colors_ )
3647 {
3648   modifyImage();
3649   options()->quantizeColors( colors_ );
3650 }
3651 size_t Magick::Image::quantizeColors ( void ) const
3652 {
3653   return constOptions()->quantizeColors( );
3654 }
3655
3656 void Magick::Image::quantizeColorSpace
3657   ( const Magick::ColorspaceType colorSpace_ )
3658 {
3659   modifyImage();
3660   options()->quantizeColorSpace( colorSpace_ );
3661 }
3662 Magick::ColorspaceType Magick::Image::quantizeColorSpace ( void ) const
3663 {
3664   return constOptions()->quantizeColorSpace( );
3665 }
3666
3667 void Magick::Image::quantizeDither ( const bool ditherFlag_ )
3668 {
3669   modifyImage();
3670   options()->quantizeDither( ditherFlag_ );
3671 }
3672 bool Magick::Image::quantizeDither ( void ) const
3673 {
3674   return constOptions()->quantizeDither( );
3675 }
3676
3677 void Magick::Image::quantizeTreeDepth ( const size_t treeDepth_ )
3678 {
3679   modifyImage();
3680   options()->quantizeTreeDepth( treeDepth_ );
3681 }
3682 size_t Magick::Image::quantizeTreeDepth ( void ) const
3683 {
3684   return constOptions()->quantizeTreeDepth( );
3685 }
3686
3687 void Magick::Image::renderingIntent
3688   ( const Magick::RenderingIntent renderingIntent_ )
3689 {
3690   modifyImage();
3691   image()->rendering_intent = renderingIntent_;
3692 }
3693 Magick::RenderingIntent Magick::Image::renderingIntent ( void ) const
3694 {
3695   return static_cast<Magick::RenderingIntent>(constImage()->rendering_intent);
3696 }
3697
3698 void Magick::Image::resolutionUnits
3699   ( const Magick::ResolutionType resolutionUnits_ )
3700 {
3701   modifyImage();
3702   image()->units = resolutionUnits_;
3703   options()->resolutionUnits( resolutionUnits_ );
3704 }
3705 Magick::ResolutionType Magick::Image::resolutionUnits ( void ) const
3706 {
3707   return constOptions()->resolutionUnits( );
3708 }
3709
3710 void Magick::Image::scene ( const size_t scene_ )
3711 {
3712   modifyImage();
3713   image()->scene = scene_;
3714 }
3715 size_t Magick::Image::scene ( void ) const
3716 {
3717   return constImage()->scene;
3718 }
3719
3720 std::string Magick::Image::signature ( const bool force_ ) const
3721 {
3722   Lock( &_imgRef->_mutexLock );
3723
3724   // Re-calculate image signature if necessary
3725   ExceptionInfo exceptionInfo;
3726   GetExceptionInfo( &exceptionInfo );
3727   if ( force_ ||
3728        !GetImageProperty(constImage(), "Signature", &exceptionInfo) ||
3729        constImage()->taint )
3730     {
3731       SignatureImage( const_cast<MagickCore::Image *>(constImage()), &exceptionInfo );
3732     }
3733
3734   const char *property = GetImageProperty(constImage(), "Signature",
3735     &exceptionInfo);
3736   throwException( exceptionInfo );
3737   (void) DestroyExceptionInfo( &exceptionInfo );
3738
3739   return std::string( property );
3740 }
3741
3742 void Magick::Image::size ( const Geometry &geometry_ )
3743 {
3744   modifyImage();
3745   options()->size( geometry_ );
3746   image()->rows = geometry_.height();
3747   image()->columns = geometry_.width();
3748 }
3749 Magick::Geometry Magick::Image::size ( void ) const
3750 {
3751   return Magick::Geometry( constImage()->columns, constImage()->rows );
3752 }
3753
3754 // Splice image
3755 void Magick::Image::splice( const Geometry &geometry_ )
3756 {
3757   RectangleInfo spliceInfo = geometry_;
3758   ExceptionInfo exceptionInfo;
3759   GetExceptionInfo( &exceptionInfo );
3760   MagickCore::Image* newImage =
3761     SpliceImage( image(), &spliceInfo, &exceptionInfo);
3762   replaceImage( newImage );
3763   throwException( exceptionInfo );
3764   (void) DestroyExceptionInfo( &exceptionInfo );
3765 }
3766
3767 // Obtain image statistics. Statistics are normalized to the range of
3768 // 0.0 to 1.0 and are output to the specified ImageStatistics
3769 // structure.
3770 void Magick::Image::statistics ( ImageStatistics *statistics ) 
3771 {
3772   double
3773     maximum,
3774     minimum;
3775
3776   ExceptionInfo exceptionInfo;
3777   GetExceptionInfo( &exceptionInfo );
3778
3779   ChannelType channel_mask = SetPixelChannelMask( image(), RedChannel);
3780   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3781   statistics->red.minimum=minimum;
3782   statistics->red.maximum=maximum;
3783   (void) GetImageMean( image(),&statistics->red.mean,
3784     &statistics->red.standard_deviation,&exceptionInfo);
3785   (void) GetImageKurtosis( image(),&statistics->red.kurtosis,
3786     &statistics->red.skewness,&exceptionInfo);
3787   (void) SetPixelChannelMapMask( image(), channel_mask );
3788
3789   channel_mask = SetPixelChannelMask( image(), GreenChannel);
3790   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3791   statistics->green.minimum=minimum;
3792   statistics->green.maximum=maximum;
3793   (void) GetImageMean( image(),&statistics->green.mean,
3794     &statistics->green.standard_deviation,&exceptionInfo);
3795   (void) GetImageKurtosis( image(),&statistics->green.kurtosis,
3796     &statistics->green.skewness,&exceptionInfo);
3797   (void) SetPixelChannelMapMask( image(), channel_mask );
3798
3799   channel_mask = SetPixelChannelMask( image(), GreenChannel);
3800   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3801   statistics->blue.minimum=minimum;
3802   statistics->blue.maximum=maximum;
3803   (void) GetImageMean( image(),&statistics->blue.mean,
3804     &statistics->blue.standard_deviation,&exceptionInfo);
3805   (void) GetImageKurtosis( image(),&statistics->blue.kurtosis,
3806     &statistics->blue.skewness,&exceptionInfo);
3807   (void) SetPixelChannelMapMask( image(), channel_mask );
3808
3809   channel_mask = SetPixelChannelMask( image(), AlphaChannel);
3810   (void) GetImageRange( image(),&minimum,&maximum,&exceptionInfo);
3811   statistics->alpha.minimum=minimum;
3812   statistics->alpha.maximum=maximum;
3813   (void) GetImageMean( image(),&statistics->alpha.mean,
3814     &statistics->alpha.standard_deviation,&exceptionInfo);
3815   (void) GetImageKurtosis( image(),&statistics->alpha.kurtosis,
3816     &statistics->alpha.skewness,&exceptionInfo);
3817   (void) SetPixelChannelMapMask( image(), channel_mask );
3818
3819   throwException( exceptionInfo );
3820   (void) DestroyExceptionInfo( &exceptionInfo );
3821 }
3822
3823 // Strip strips an image of all profiles and comments.
3824 void Magick::Image::strip ( void )
3825 {
3826   modifyImage();
3827   ExceptionInfo exceptionInfo;
3828   GetExceptionInfo( &exceptionInfo );
3829   StripImage( image(), &exceptionInfo );
3830   throwException( exceptionInfo );
3831   (void) DestroyExceptionInfo( &exceptionInfo );
3832 }
3833
3834 // enabled/disable stroke anti-aliasing
3835 void Magick::Image::strokeAntiAlias ( const bool flag_ )
3836 {
3837   modifyImage();
3838   options()->strokeAntiAlias(flag_);
3839 }
3840 bool Magick::Image::strokeAntiAlias ( void ) const
3841 {
3842   return constOptions()->strokeAntiAlias();
3843 }
3844
3845 // Color to use when drawing object outlines
3846 void Magick::Image::strokeColor ( const Magick::Color &strokeColor_ )
3847 {
3848   modifyImage();
3849   options()->strokeColor(strokeColor_);
3850 }
3851 Magick::Color Magick::Image::strokeColor ( void ) const
3852 {
3853   return constOptions()->strokeColor();
3854 }
3855
3856 // dash pattern for drawing vector objects (default one)
3857 void Magick::Image::strokeDashArray ( const double* strokeDashArray_ )
3858 {
3859   modifyImage();
3860   options()->strokeDashArray( strokeDashArray_ );
3861 }
3862
3863 const double* Magick::Image::strokeDashArray ( void ) const
3864 {
3865   return constOptions()->strokeDashArray( );
3866 }
3867
3868 // dash offset for drawing vector objects (default one)
3869 void Magick::Image::strokeDashOffset ( const double strokeDashOffset_ )
3870 {
3871   modifyImage();
3872   options()->strokeDashOffset( strokeDashOffset_ );
3873 }
3874
3875 double Magick::Image::strokeDashOffset ( void ) const
3876 {
3877   return constOptions()->strokeDashOffset( );
3878 }
3879
3880 // Specify the shape to be used at the end of open subpaths when they
3881 // are stroked. Values of LineCap are UndefinedCap, ButtCap, RoundCap,
3882 // and SquareCap.
3883 void Magick::Image::strokeLineCap ( const Magick::LineCap lineCap_ )
3884 {
3885   modifyImage();
3886   options()->strokeLineCap( lineCap_ );
3887 }
3888 Magick::LineCap Magick::Image::strokeLineCap ( void ) const
3889 {
3890   return constOptions()->strokeLineCap( );
3891 }
3892
3893 // Specify the shape to be used at the corners of paths (or other
3894 // vector shapes) when they are stroked. Values of LineJoin are
3895 // UndefinedJoin, MiterJoin, RoundJoin, and BevelJoin.
3896 void Magick::Image::strokeLineJoin ( const Magick::LineJoin lineJoin_ )
3897 {
3898   modifyImage();
3899   options()->strokeLineJoin( lineJoin_ );
3900 }
3901 Magick::LineJoin Magick::Image::strokeLineJoin ( void ) const
3902 {
3903   return constOptions()->strokeLineJoin( );
3904 }
3905
3906 // Specify miter limit. When two line segments meet at a sharp angle
3907 // and miter joins have been specified for 'lineJoin', it is possible
3908 // for the miter to extend far beyond the thickness of the line
3909 // stroking the path. The miterLimit' imposes a limit on the ratio of
3910 // the miter length to the 'lineWidth'. The default value of this
3911 // parameter is 4.
3912 void Magick::Image::strokeMiterLimit ( const size_t strokeMiterLimit_ )
3913 {
3914   modifyImage();
3915   options()->strokeMiterLimit( strokeMiterLimit_ );
3916 }
3917 size_t Magick::Image::strokeMiterLimit ( void ) const
3918 {
3919   return constOptions()->strokeMiterLimit( );
3920 }
3921
3922 // Pattern to use while stroking drawn objects.
3923 void Magick::Image::strokePattern ( const Image &strokePattern_ )
3924 {
3925   modifyImage();
3926   if(strokePattern_.isValid())
3927     options()->strokePattern( strokePattern_.constImage() );
3928   else
3929     options()->strokePattern( static_cast<MagickCore::Image*>(NULL) );
3930 }
3931 Magick::Image  Magick::Image::strokePattern ( void  ) const
3932 {
3933   // FIXME: This is inordinately innefficient
3934   Image texture;
3935   
3936   const MagickCore::Image* tmpTexture = constOptions()->strokePattern( );
3937
3938   if ( tmpTexture )
3939     {
3940       ExceptionInfo exceptionInfo;
3941       GetExceptionInfo( &exceptionInfo );
3942       MagickCore::Image* image =
3943         CloneImage( tmpTexture,
3944                     0, // columns
3945                     0, // rows
3946                     MagickTrue, // orphan
3947                     &exceptionInfo);
3948       throwException( exceptionInfo );
3949       (void) DestroyExceptionInfo( &exceptionInfo );
3950       texture.replaceImage( image );
3951     }
3952   return texture;
3953 }
3954
3955 // Stroke width for drawing lines, circles, ellipses, etc.
3956 void Magick::Image::strokeWidth ( const double strokeWidth_ )
3957 {
3958   modifyImage();
3959   options()->strokeWidth( strokeWidth_ );
3960 }
3961 double Magick::Image::strokeWidth ( void ) const
3962 {
3963   return constOptions()->strokeWidth( );
3964 }
3965
3966 void Magick::Image::subImage ( const size_t subImage_ )
3967 {
3968   modifyImage();
3969   options()->subImage( subImage_ );
3970 }
3971 size_t Magick::Image::subImage ( void ) const
3972 {
3973   return constOptions()->subImage( );
3974 }
3975
3976 void Magick::Image::subRange ( const size_t subRange_ )
3977 {
3978   modifyImage();
3979   options()->subRange( subRange_ );
3980 }
3981 size_t Magick::Image::subRange ( void ) const
3982 {
3983   return constOptions()->subRange( );
3984 }
3985
3986 // Annotation text encoding (e.g. "UTF-16")
3987 void Magick::Image::textEncoding ( const std::string &encoding_ )
3988 {
3989   modifyImage();
3990   options()->textEncoding( encoding_ );
3991 }
3992 std::string Magick::Image::textEncoding ( void ) const
3993 {
3994   return constOptions()->textEncoding( );
3995 }
3996
3997 size_t Magick::Image::totalColors ( void )
3998 {
3999   ExceptionInfo exceptionInfo;
4000   GetExceptionInfo( &exceptionInfo );
4001   size_t colors = GetNumberColors( image(), 0, &exceptionInfo);
4002   throwException( exceptionInfo );
4003   (void) DestroyExceptionInfo( &exceptionInfo );
4004   return colors;
4005 }
4006
4007 // Origin of coordinate system to use when annotating with text or drawing
4008 void Magick::Image::transformOrigin ( const double x_, const double y_ )
4009 {
4010   modifyImage();
4011   options()->transformOrigin( x_, y_ );
4012 }
4013
4014 // Rotation to use when annotating with text or drawing
4015 void Magick::Image::transformRotation ( const double angle_ )
4016 {
4017   modifyImage();
4018   options()->transformRotation( angle_ );
4019 }
4020
4021 // Reset transformation parameters to default
4022 void Magick::Image::transformReset ( void )
4023 {
4024   modifyImage();
4025   options()->transformReset();
4026 }
4027
4028 // Scale to use when annotating with text or drawing
4029 void Magick::Image::transformScale ( const double sx_, const double sy_ )
4030 {
4031   modifyImage();
4032   options()->transformScale( sx_, sy_ );
4033 }
4034
4035 // Skew to use in X axis when annotating with text or drawing
4036 void Magick::Image::transformSkewX ( const double skewx_ )
4037 {
4038   modifyImage();
4039   options()->transformSkewX( skewx_ );
4040 }
4041
4042 // Skew to use in Y axis when annotating with text or drawing
4043 void Magick::Image::transformSkewY ( const double skewy_ )
4044 {
4045   modifyImage();
4046   options()->transformSkewY( skewy_ );
4047 }
4048
4049 // Image representation type
4050 Magick::ImageType Magick::Image::type ( void ) const
4051 {
4052
4053   ExceptionInfo exceptionInfo;
4054   GetExceptionInfo( &exceptionInfo );
4055   ImageType image_type = constOptions()->type();
4056   if ( image_type == UndefinedType )
4057     image_type= GetImageType( constImage(), &exceptionInfo);
4058   throwException( exceptionInfo );
4059   (void) DestroyExceptionInfo( &exceptionInfo );
4060   return image_type;
4061 }
4062 void Magick::Image::type ( const Magick::ImageType type_)
4063 {
4064   ExceptionInfo exceptionInfo;
4065   GetExceptionInfo( &exceptionInfo );
4066   modifyImage();
4067   options()->type( type_ );
4068   SetImageType( image(), type_, &exceptionInfo );
4069   throwException( exceptionInfo );
4070   (void) DestroyExceptionInfo( &exceptionInfo );
4071 }
4072
4073 void Magick::Image::verbose ( const bool verboseFlag_ )
4074 {
4075   modifyImage();
4076   options()->verbose( verboseFlag_ );
4077 }
4078 bool Magick::Image::verbose ( void ) const
4079 {
4080   return constOptions()->verbose( );
4081 }
4082
4083 void Magick::Image::view ( const std::string &view_ )
4084 {
4085   modifyImage();
4086   options()->view( view_ );
4087 }
4088 std::string Magick::Image::view ( void ) const
4089 {
4090   return constOptions()->view( );
4091 }
4092
4093 // Virtual pixel method
4094 void Magick::Image::virtualPixelMethod ( const VirtualPixelMethod virtual_pixel_method_ )
4095 {
4096   modifyImage();
4097   SetImageVirtualPixelMethod( image(), virtual_pixel_method_ );
4098 }
4099 Magick::VirtualPixelMethod Magick::Image::virtualPixelMethod ( void ) const
4100 {
4101   return GetImageVirtualPixelMethod( constImage() );
4102 }
4103
4104 void Magick::Image::x11Display ( const std::string &display_ )
4105 {
4106   modifyImage();
4107   options()->x11Display( display_ );
4108 }
4109 std::string Magick::Image::x11Display ( void ) const
4110 {
4111   return constOptions()->x11Display( );
4112 }
4113
4114 double Magick::Image::xResolution ( void ) const
4115 {
4116   return constImage()->resolution.x;
4117 }
4118 double Magick::Image::yResolution ( void ) const
4119 {
4120   return constImage()->resolution.y;
4121 }
4122
4123 // Copy Constructor
4124 Magick::Image::Image( const Image & image_ )
4125   : _imgRef(image_._imgRef)
4126 {
4127   Lock( &_imgRef->_mutexLock );
4128
4129   // Increase reference count
4130   ++_imgRef->_refCount;
4131 }
4132
4133 // Assignment operator
4134 Magick::Image& Magick::Image::operator=( const Magick::Image &image_ )
4135 {
4136   if( this != &image_ )
4137     {
4138       {
4139         Lock( &image_._imgRef->_mutexLock );
4140         ++image_._imgRef->_refCount;
4141       }
4142
4143       bool doDelete = false;
4144       {
4145         Lock( &_imgRef->_mutexLock );
4146         if ( --_imgRef->_refCount == 0 )
4147           doDelete = true;
4148       }
4149
4150       if ( doDelete )
4151         {
4152           // Delete old image reference with associated image and options.
4153           delete _imgRef;
4154           _imgRef = 0;
4155         }
4156       // Use new image reference
4157       _imgRef = image_._imgRef;
4158     }
4159
4160   return *this;
4161 }
4162
4163 //////////////////////////////////////////////////////////////////////    
4164 //
4165 // Low-level Pixel Access Routines
4166 //
4167 // Also see the Pixels class, which provides support for multiple
4168 // cache views. The low-level pixel access routines in the Image
4169 // class are provided in order to support backward compatability.
4170 //
4171 //////////////////////////////////////////////////////////////////////
4172
4173 // Transfers read-only pixels from the image to the pixel cache as
4174 // defined by the specified region
4175 const Magick::Quantum* Magick::Image::getConstPixels
4176   ( const ssize_t x_, const ssize_t y_,
4177     const size_t columns_,
4178     const size_t rows_ ) const
4179 {
4180   ExceptionInfo exceptionInfo;
4181   GetExceptionInfo( &exceptionInfo );
4182   const Quantum* p = (*GetVirtualPixels)( constImage(),
4183                                                 x_, y_,
4184                                                 columns_, rows_,
4185                                                 &exceptionInfo );
4186   throwException( exceptionInfo );
4187   (void) DestroyExceptionInfo( &exceptionInfo );
4188   return p;
4189 }
4190
4191 // Obtain read-only pixel associated pixels channels
4192 const void* Magick::Image::getConstMetacontent ( void ) const
4193 {
4194   const void* result = GetVirtualMetacontent( constImage() );
4195
4196   if( !result )
4197     throwImageException();
4198
4199   return result;
4200 }
4201
4202 // Obtain image pixel associated pixels channels
4203 void* Magick::Image::getMetacontent ( void )
4204 {
4205   void* result = GetAuthenticMetacontent( image() );
4206
4207   if( !result )
4208     throwImageException();
4209
4210   return ( result );
4211 }
4212
4213 // Transfers pixels from the image to the pixel cache as defined
4214 // by the specified region. Modified pixels may be subsequently
4215 // transferred back to the image via syncPixels.
4216 Magick::Quantum* Magick::Image::getPixels ( const ssize_t x_, const ssize_t y_,
4217                                                 const size_t columns_,
4218                                                 const size_t rows_ )
4219 {
4220   modifyImage();
4221   ExceptionInfo exceptionInfo;
4222   GetExceptionInfo( &exceptionInfo );
4223   Quantum* result = (*GetAuthenticPixels)( image(),
4224                                            x_, y_,
4225                                            columns_, rows_, &exceptionInfo );
4226   throwException( exceptionInfo );
4227   (void) DestroyExceptionInfo( &exceptionInfo );
4228
4229   return result;
4230 }
4231
4232 // Allocates a pixel cache region to store image pixels as defined
4233 // by the region rectangle.  This area is subsequently transferred
4234 // from the pixel cache to the image via syncPixels.
4235 Magick::Quantum* Magick::Image::setPixels ( const ssize_t x_, const ssize_t y_,
4236                                                 const size_t columns_,
4237                                                 const size_t rows_ )
4238 {
4239   modifyImage();
4240   ExceptionInfo exceptionInfo;
4241   GetExceptionInfo( &exceptionInfo );
4242   Quantum* result = (*QueueAuthenticPixels)( image(),
4243                                            x_, y_,
4244                                            columns_, rows_, &exceptionInfo );
4245   throwException( exceptionInfo );
4246   (void) DestroyExceptionInfo( &exceptionInfo );
4247
4248   return result;
4249 }
4250
4251 // Transfers the image cache pixels to the image.
4252 void Magick::Image::syncPixels ( void )
4253 {
4254   ExceptionInfo exceptionInfo;
4255   GetExceptionInfo( &exceptionInfo );
4256   (*SyncAuthenticPixels)( image(), &exceptionInfo );
4257   throwException( exceptionInfo );
4258   (void) DestroyExceptionInfo( &exceptionInfo );
4259 }
4260
4261 // Transfers one or more pixel components from a buffer or file
4262 // into the image pixel cache of an image.
4263 // Used to support image decoders.
4264 void Magick::Image::readPixels ( const Magick::QuantumType quantum_,
4265                                  const unsigned char *source_ )
4266 {
4267   QuantumInfo
4268     *quantum_info;
4269
4270   quantum_info=AcquireQuantumInfo(imageInfo(),image());
4271   ExceptionInfo exceptionInfo;
4272   GetExceptionInfo( &exceptionInfo );
4273   ImportQuantumPixels(image(),(MagickCore::CacheView *) NULL,quantum_info,
4274     quantum_,source_, &exceptionInfo);
4275   throwException( exceptionInfo );
4276   (void) DestroyExceptionInfo( &exceptionInfo );
4277   quantum_info=DestroyQuantumInfo(quantum_info);
4278 }
4279
4280 // Transfers one or more pixel components from the image pixel
4281 // cache to a buffer or file.
4282 // Used to support image encoders.
4283 void Magick::Image::writePixels ( const Magick::QuantumType quantum_,
4284                                   unsigned char *destination_ )
4285 {
4286   QuantumInfo
4287     *quantum_info;
4288
4289   quantum_info=AcquireQuantumInfo(imageInfo(),image());
4290   ExceptionInfo exceptionInfo;
4291   GetExceptionInfo( &exceptionInfo );
4292   ExportQuantumPixels(image(),(MagickCore::CacheView *) NULL,quantum_info,
4293     quantum_,destination_, &exceptionInfo);
4294   quantum_info=DestroyQuantumInfo(quantum_info);
4295   throwException( exceptionInfo );
4296   (void) DestroyExceptionInfo( &exceptionInfo );
4297 }
4298
4299 /////////////////////////////////////////////////////////////////////
4300 //
4301 // No end-user methods beyond this point
4302 //
4303 /////////////////////////////////////////////////////////////////////
4304
4305
4306 //
4307 // Construct using existing image and default options
4308 //
4309 Magick::Image::Image ( MagickCore::Image* image_ )
4310   : _imgRef(new ImageRef( image_))
4311 {
4312 }
4313
4314 // Get Magick::Options*
4315 Magick::Options* Magick::Image::options( void )
4316 {
4317   return _imgRef->options();
4318 }
4319 const Magick::Options* Magick::Image::constOptions( void ) const
4320 {
4321   return _imgRef->options();
4322 }
4323
4324 // Get MagickCore::Image*
4325 MagickCore::Image*& Magick::Image::image( void )
4326 {
4327   return _imgRef->image();
4328 }
4329 const MagickCore::Image* Magick::Image::constImage( void ) const
4330 {
4331   return _imgRef->image();
4332 }
4333
4334 // Get ImageInfo *
4335 MagickCore::ImageInfo* Magick::Image::imageInfo( void )
4336 {
4337   return _imgRef->options()->imageInfo();
4338 }
4339 const MagickCore::ImageInfo * Magick::Image::constImageInfo( void ) const
4340 {
4341   return _imgRef->options()->imageInfo();
4342 }
4343
4344 // Get QuantizeInfo *
4345 MagickCore::QuantizeInfo* Magick::Image::quantizeInfo( void )
4346 {
4347   return _imgRef->options()->quantizeInfo();
4348 }
4349 const MagickCore::QuantizeInfo * Magick::Image::constQuantizeInfo( void ) const
4350 {
4351   return _imgRef->options()->quantizeInfo();
4352 }
4353
4354 //
4355 // Replace current image
4356 //
4357 MagickCore::Image * Magick::Image::replaceImage
4358   ( MagickCore::Image* replacement_ )
4359 {
4360   MagickCore::Image* image;
4361   
4362   if( replacement_ )
4363     image = replacement_;
4364   else
4365     {
4366       ExceptionInfo exceptionInfo;
4367       GetExceptionInfo( &exceptionInfo );
4368       image = AcquireImage(constImageInfo(), &exceptionInfo);
4369       throwException( exceptionInfo );
4370       (void) DestroyExceptionInfo( &exceptionInfo );
4371     }
4372
4373   {
4374     Lock( &_imgRef->_mutexLock );
4375
4376     if ( _imgRef->_refCount == 1 )
4377       {
4378         // We own the image, just replace it, and de-register
4379         _imgRef->id( -1 );
4380         _imgRef->image(image);
4381       }
4382     else
4383       {
4384         // We don't own the image, dereference and replace with copy
4385         --_imgRef->_refCount;
4386         _imgRef = new ImageRef( image, constOptions() );
4387       }
4388   }
4389
4390   return _imgRef->_image;
4391 }
4392
4393 //
4394 // Prepare to modify image or image options
4395 // Replace current image and options with copy if reference count > 1
4396 //
4397 void Magick::Image::modifyImage( void )
4398 {
4399   {
4400     Lock( &_imgRef->_mutexLock );
4401     if ( _imgRef->_refCount == 1 )
4402       {
4403         // De-register image and return
4404         _imgRef->id( -1 );
4405         return;
4406       }
4407   }
4408
4409   ExceptionInfo exceptionInfo;
4410   GetExceptionInfo( &exceptionInfo );
4411   replaceImage( CloneImage( image(),
4412                             0, // columns
4413                             0, // rows
4414                             MagickTrue, // orphan
4415                             &exceptionInfo) );
4416   throwException( exceptionInfo );
4417   (void) DestroyExceptionInfo( &exceptionInfo );
4418   return;
4419 }
4420
4421 //
4422 // Test for an ImageMagick reported error and throw exception if one
4423 // has been reported.  Secretly resets image->exception back to default
4424 // state even though this method is const.
4425 //
4426 void Magick::Image::throwImageException( void ) const
4427 {
4428   // Throw C++ exception while resetting Image exception to default state
4429 }
4430
4431 // Register image with image registry or obtain registration id
4432 ssize_t Magick::Image::registerId( void )
4433 {
4434   Lock( &_imgRef->_mutexLock );
4435   if( _imgRef->id() < 0 )
4436     {
4437       char id[MaxTextExtent];
4438       ExceptionInfo exceptionInfo;
4439       GetExceptionInfo( &exceptionInfo );
4440       _imgRef->id(_imgRef->id()+1);
4441       sprintf(id,"%.20g\n",(double) _imgRef->id());
4442       SetImageRegistry(ImageRegistryType, id, image(), &exceptionInfo);
4443       throwException( exceptionInfo );
4444   (void) DestroyExceptionInfo( &exceptionInfo );
4445     }
4446   return _imgRef->id();
4447 }
4448
4449 // Unregister image from image registry
4450 void Magick::Image::unregisterId( void )
4451 {
4452   modifyImage();
4453   _imgRef->id( -1 );
4454 }
4455
4456 //
4457 // Create a local wrapper around MagickCoreTerminus
4458 //
4459 namespace Magick
4460 {
4461   extern "C" {
4462     void MagickPlusPlusDestroyMagick(void);
4463   }
4464 }
4465
4466 void Magick::MagickPlusPlusDestroyMagick(void)
4467 {
4468   if (magick_initialized)
4469     {
4470       magick_initialized=false;
4471       MagickCore::MagickCoreTerminus();
4472     }
4473 }
4474
4475 // C library initialization routine
4476 void MagickPPExport Magick::InitializeMagick(const char *path_)
4477 {
4478   MagickCore::MagickCoreGenesis(path_,MagickFalse);
4479   if (!magick_initialized)
4480     magick_initialized=true;
4481 }
4482
4483 //
4484 // Cleanup class to ensure that ImageMagick singletons are destroyed
4485 // so as to avoid any resemblence to a memory leak (which seems to
4486 // confuse users)
4487 //
4488 namespace Magick
4489 {
4490
4491   class MagickCleanUp
4492   {
4493   public:
4494     MagickCleanUp( void );
4495     ~MagickCleanUp( void );
4496   };
4497
4498   // The destructor for this object is invoked when the destructors for
4499   // static objects in this translation unit are invoked.
4500   static MagickCleanUp magickCleanUpGuard;
4501 }
4502
4503 Magick::MagickCleanUp::MagickCleanUp ( void )
4504 {
4505   // Don't even think about invoking InitializeMagick here!
4506 }
4507
4508 Magick::MagickCleanUp::~MagickCleanUp ( void )
4509 {
4510   MagickPlusPlusDestroyMagick();
4511 }