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