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