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