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