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