1 // This may look like C code, but it is really -*- C++ -*-
2 //
3 // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002
4 // Copyright Dirk Lemstra 2014-2015
5 //
6 // Implementation of ImageRef
7 //
8 // This is an internal implementation class.
9 //
10 
11 #define MAGICKCORE_IMPLEMENTATION  1
12 #define MAGICK_PLUSPLUS_IMPLEMENTATION 1
13 
14 #include "Magick++/ImageRef.h"
15 #include "Magick++/Exception.h"
16 #include "Magick++/Options.h"
17 
ImageRef(void)18 Magick::ImageRef::ImageRef(void)
19   : _image(0),
20     _mutexLock(),
21     _options(new Options),
22     _refCount(1)
23 {
24   GetPPException;
25   _image=AcquireImage(_options->imageInfo(),exceptionInfo);
26   ThrowPPException(false);
27 }
28 
ImageRef(MagickCore::Image * image_)29 Magick::ImageRef::ImageRef(MagickCore::Image *image_)
30   : _image(image_),
31     _mutexLock(),
32     _options(new Options),
33     _refCount(1)
34 {
35 }
36 
~ImageRef(void)37 Magick::ImageRef::~ImageRef(void)
38 {
39   // Deallocate image
40   if (_image != (MagickCore::Image*) NULL)
41     _image=DestroyImageList(_image);
42 
43   // Deallocate image options
44   delete _options;
45   _options=(Options *) NULL;
46 }
47 
decrease()48 size_t Magick::ImageRef::decrease()
49 {
50   size_t
51     count;
52 
53   _mutexLock.lock();
54   if (_refCount == 0)
55     {
56       _mutexLock.unlock();
57       throwExceptionExplicit(MagickCore::OptionError,
58         "Invalid call to decrease");
59       return(0);
60     }
61   count=--_refCount;
62   _mutexLock.unlock();
63   return(count);
64 }
65 
image(void)66 MagickCore::Image *&Magick::ImageRef::image(void)
67 {
68   return(_image);
69 }
70 
increase()71 void Magick::ImageRef::increase()
72 {
73   _mutexLock.lock();
74   _refCount++;
75   _mutexLock.unlock();
76 }
77 
isShared()78 bool Magick::ImageRef::isShared()
79 {
80   bool
81     isShared;
82 
83   _mutexLock.lock();
84   isShared=(_refCount > 1);
85   _mutexLock.unlock();
86   return(isShared);
87 }
88 
options(Magick::Options * options_)89 void  Magick::ImageRef::options(Magick::Options *options_)
90 {
91   delete _options;
92   _options=options_;
93 }
94 
options(void)95 Magick::Options *Magick::ImageRef::options(void)
96 {
97   return(_options);
98 }
99 
replaceImage(ImageRef * imgRef,MagickCore::Image * replacement_)100 Magick::ImageRef *Magick::ImageRef::replaceImage(ImageRef *imgRef,
101   MagickCore::Image *replacement_)
102 {
103   Magick::ImageRef
104     *instance;
105 
106   imgRef->_mutexLock.lock();
107   if (imgRef->_refCount == 1)
108     {
109       // We can replace the image if we own it.
110       instance=imgRef;
111       if (imgRef->_image != (MagickCore::Image*) NULL)
112         (void) DestroyImageList(imgRef->_image);
113       imgRef->_image=replacement_;
114       imgRef->_mutexLock.unlock();
115     }
116   else
117     {
118       // We don't own the image, create a new ImageRef instance.
119       instance=new ImageRef(replacement_,imgRef->_options);
120       imgRef->_refCount--;
121       imgRef->_mutexLock.unlock();
122     }
123   return(instance);
124 }
125 
signature(const bool force_)126 std::string Magick::ImageRef::signature(const bool force_)
127 {
128   const char
129     *property;
130 
131   // Re-calculate image signature if necessary
132   GetPPException;
133   _mutexLock.lock();
134   property=(const char *) NULL;
135   if (!force_ && (_image->taint == MagickFalse))
136     property=GetImageProperty(_image,"Signature",exceptionInfo);
137   if (property == (const char *) NULL)
138     {
139       (void) SignatureImage(_image,exceptionInfo);
140       property=GetImageProperty(_image,"Signature",exceptionInfo);
141     }
142   _mutexLock.unlock();
143   ThrowPPException(true);
144 
145   return(std::string(property));
146 }
147 
ImageRef(MagickCore::Image * image_,const Options * options_)148 Magick::ImageRef::ImageRef(MagickCore::Image *image_,const Options *options_)
149   : _image(image_),
150     _mutexLock(),
151     _options(0),
152     _refCount(1)
153 {
154   _options=new Options(*options_);
155 }