root/ImageMagick/trunk/Magick++/lib/Image.cpp

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