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