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