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