1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 /*=========================================================================
19  *
20  *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  *  For complete copyright, license and disclaimer of warranty information
25  *  please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 #ifndef itkImportImageContainer_hxx
29 #define itkImportImageContainer_hxx
30 
31 #include "itkImportImageContainer.h"
32 
33 namespace itk
34 {
35 template< typename TElementIdentifier, typename TElement >
36 ImportImageContainer< TElementIdentifier, TElement >
ImportImageContainer()37 ::ImportImageContainer()
38 {
39   m_ImportPointer = nullptr;
40   m_ContainerManageMemory = true;
41   m_Capacity = 0;
42   m_Size = 0;
43 }
44 
45 template< typename TElementIdentifier, typename TElement >
46 ImportImageContainer< TElementIdentifier, TElement >
~ImportImageContainer()47 ::~ImportImageContainer()
48 {
49   DeallocateManagedMemory();
50 }
51 
52 /**
53  * Tell the container to allocate enough memory to allow at least
54  * as many elements as the size given to be stored.
55  */
56 template< typename TElementIdentifier, typename TElement >
57 void
58 ImportImageContainer< TElementIdentifier, TElement >
Reserve(ElementIdentifier size,const bool UseDefaultConstructor)59 ::Reserve(ElementIdentifier size, const bool UseDefaultConstructor )
60 {
61   // Reserve has a Resize semantics. We keep it that way for
62   // backwards compatibility .
63   // See https://www.itk.org/Bug/view.php?id=2893 for details
64   if ( m_ImportPointer )
65     {
66     if ( size > m_Capacity )
67       {
68       TElement *temp = this->AllocateElements(size, UseDefaultConstructor);
69       // only copy the portion of the data used in the old buffer
70       std::copy(m_ImportPointer,
71                 m_ImportPointer+m_Size,
72                 temp);
73 
74       DeallocateManagedMemory();
75 
76       m_ImportPointer = temp;
77       m_ContainerManageMemory = true;
78       m_Capacity = size;
79       m_Size = size;
80       this->Modified();
81       }
82     else
83       {
84       m_Size = size;
85       this->Modified();
86       }
87     }
88   else
89     {
90     m_ImportPointer = this->AllocateElements(size, UseDefaultConstructor);
91     m_Capacity = size;
92     m_Size = size;
93     m_ContainerManageMemory = true;
94     this->Modified();
95     }
96 }
97 
98 /**
99  * Tell the container to try to minimize its memory usage for storage of
100  * the current number of elements.
101  */
102 template< typename TElementIdentifier, typename TElement >
103 void
104 ImportImageContainer< TElementIdentifier, TElement >
Squeeze()105 ::Squeeze()
106 {
107   if ( m_ImportPointer )
108     {
109     if ( m_Size < m_Capacity )
110       {
111       const TElementIdentifier size = m_Size;
112       TElement *               temp = this->AllocateElements(size, false);
113       std::copy(m_ImportPointer,
114                 m_ImportPointer+m_Size,
115                 temp);
116 
117       DeallocateManagedMemory();
118 
119       m_ImportPointer = temp;
120       m_ContainerManageMemory = true;
121       m_Capacity = size;
122       m_Size = size;
123 
124       this->Modified();
125       }
126     }
127 }
128 
129 /**
130  * Tell the container to try to minimize its memory usage for storage of
131  * the current number of elements.
132  */
133 template< typename TElementIdentifier, typename TElement >
134 void
135 ImportImageContainer< TElementIdentifier, TElement >
Initialize()136 ::Initialize()
137 {
138   if ( m_ImportPointer )
139     {
140     DeallocateManagedMemory();
141 
142     m_ContainerManageMemory = true;
143 
144     this->Modified();
145     }
146 }
147 
148 /**
149  * Set the pointer from which the image data is imported.  "num" is
150  * the number of pixels in the block of memory. If
151  * "LetContainerManageMemory" is false, then the application retains
152  * the responsibility of freeing the memory for this image data.  If
153  * "LetContainerManageMemory" is true, then this class will free the
154  * memory when this object is destroyed.
155  */
156 template< typename TElementIdentifier, typename TElement >
157 void
158 ImportImageContainer< TElementIdentifier, TElement >
SetImportPointer(TElement * ptr,TElementIdentifier num,bool LetContainerManageMemory)159 ::SetImportPointer(TElement *ptr, TElementIdentifier num,
160                    bool LetContainerManageMemory)
161 {
162   DeallocateManagedMemory();
163   m_ImportPointer = ptr;
164   m_ContainerManageMemory = LetContainerManageMemory;
165   m_Capacity = num;
166   m_Size = num;
167 
168   this->Modified();
169 }
170 
171 template< typename TElementIdentifier, typename TElement >
172 TElement *ImportImageContainer< TElementIdentifier, TElement >
AllocateElements(ElementIdentifier size,bool UseDefaultConstructor) const173 ::AllocateElements(ElementIdentifier size, bool UseDefaultConstructor ) const
174 {
175   // Encapsulate all image memory allocation here to throw an
176   // exception when memory allocation fails even when the compiler
177   // does not do this by default.
178   TElement *data;
179 
180   try
181     {
182     if ( UseDefaultConstructor )
183       {
184       data = new TElement[size](); //POD types initialized to 0, others use default constructor.
185       }
186     else
187       {
188       data = new TElement[size]; //Faster but uninitialized
189       }
190     }
191   catch ( ... )
192     {
193     data = nullptr;
194     }
195   if ( !data )
196     {
197     // We cannot construct an error string here because we may be out
198     // of memory.  Do not use the exception macro.
199     throw MemoryAllocationError(__FILE__, __LINE__,
200                                 "Failed to allocate memory for image.",
201                                 ITK_LOCATION);
202     }
203   return data;
204 }
205 
206 template< typename TElementIdentifier, typename TElement >
207 void ImportImageContainer< TElementIdentifier, TElement >
DeallocateManagedMemory()208 ::DeallocateManagedMemory()
209 {
210   // Encapsulate all image memory deallocation here
211   if ( m_ContainerManageMemory )
212     {
213     delete[] m_ImportPointer;
214     }
215   m_ImportPointer = nullptr;
216   m_Capacity = 0;
217   m_Size = 0;
218 }
219 
220 template< typename TElementIdentifier, typename TElement >
221 void
222 ImportImageContainer< TElementIdentifier, TElement >
PrintSelf(std::ostream & os,Indent indent) const223 ::PrintSelf(std::ostream & os, Indent indent) const
224 {
225   Superclass::PrintSelf(os, indent);
226 
227   os << indent << "Pointer: " << static_cast< void * >( m_ImportPointer ) << std::endl;
228   os << indent << "Container manages memory: "
229      << ( m_ContainerManageMemory ? "true" : "false" ) << std::endl;
230   os << indent << "Size: " << m_Size << std::endl;
231   os << indent << "Capacity: " << m_Capacity << std::endl;
232 }
233 } // end namespace itk
234 
235 #endif
236