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