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