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