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