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