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
18Magick::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
29Magick::ImageRef::ImageRef(MagickCore::Image *image_)
30  : _image(image_),
31    _mutexLock(),
32    _options(new Options),
33    _refCount(1)
34{
35}
36
37Magick::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
48size_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
66MagickCore::Image *&Magick::ImageRef::image(void)
67{
68  return(_image);
69}
70
71void Magick::ImageRef::increase()
72{
73  _mutexLock.lock();
74  _refCount++;
75  _mutexLock.unlock();
76}
77
78bool Magick::ImageRef::isShared()
79{
80  bool
81    isShared;
82
83  _mutexLock.lock();
84  isShared=(_refCount > 1);
85  _mutexLock.unlock();
86  return(isShared);
87}
88
89void  Magick::ImageRef::options(Magick::Options *options_)
90{
91  delete _options;
92  _options=options_;
93}
94
95Magick::Options *Magick::ImageRef::options(void)
96{
97  return(_options);
98}
99
100Magick::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
126std::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
148Magick::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}