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