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