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