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