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