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