/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /*========================================================================= * * Portions of this file are subject to the VTK Toolkit Version 3 copyright. * * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen * * For complete copyright, license and disclaimer of warranty information * please refer to the NOTICE file at the top of the ITK source tree. * *=========================================================================*/ #ifndef itkImportImageContainer_hxx #define itkImportImageContainer_hxx #include // For copy_n. namespace itk { template ImportImageContainer::~ImportImageContainer() { DeallocateManagedMemory(); } /** * Tell the container to allocate enough memory to allow at least * as many elements as the size given to be stored. */ template void ImportImageContainer::Reserve(ElementIdentifier size, const bool UseValueInitialization) { // Reserve has a Resize semantics. We keep it that way for // backwards compatibility . // See https://www.itk.org/Bug/view.php?id=2893 for details if (m_ImportPointer) { if (size > m_Capacity) { TElement * temp = this->AllocateElements(size, UseValueInitialization); // only copy the portion of the data used in the old buffer std::copy_n(m_ImportPointer, m_Size, temp); DeallocateManagedMemory(); m_ImportPointer = temp; m_ContainerManageMemory = true; m_Capacity = size; m_Size = size; this->Modified(); } else { m_Size = size; this->Modified(); } } else { m_ImportPointer = this->AllocateElements(size, UseValueInitialization); m_Capacity = size; m_Size = size; m_ContainerManageMemory = true; this->Modified(); } } /** * Tell the container to try to minimize its memory usage for storage of * the current number of elements. */ template void ImportImageContainer::Squeeze() { if (m_ImportPointer) { if (m_Size < m_Capacity) { const TElementIdentifier size = m_Size; TElement * temp = this->AllocateElements(size, false); std::copy_n(m_ImportPointer, m_Size, temp); DeallocateManagedMemory(); m_ImportPointer = temp; m_ContainerManageMemory = true; m_Capacity = size; m_Size = size; this->Modified(); } } } /** * Tell the container to try to minimize its memory usage for storage of * the current number of elements. */ template void ImportImageContainer::Initialize() { if (m_ImportPointer) { DeallocateManagedMemory(); m_ContainerManageMemory = true; this->Modified(); } } /** * Set the pointer from which the image data is imported. "num" is * the number of pixels in the block of memory. If * "LetContainerManageMemory" is false, then the application retains * the responsibility of freeing the memory for this image data. If * "LetContainerManageMemory" is true, then this class will free the * memory when this object is destroyed. */ template void ImportImageContainer::SetImportPointer(TElement * ptr, TElementIdentifier num, bool LetContainerManageMemory) { DeallocateManagedMemory(); m_ImportPointer = ptr; m_ContainerManageMemory = LetContainerManageMemory; m_Capacity = num; m_Size = num; this->Modified(); } template TElement * ImportImageContainer::AllocateElements(ElementIdentifier size, bool UseValueInitialization) const { TElement * data; try { if (UseValueInitialization) { data = new TElement[size](); } else { data = new TElement[size]; } } catch (...) { data = nullptr; } if (!data) { // We cannot construct an error string here because we may be out // of memory. Do not use the exception macro. throw MemoryAllocationError(__FILE__, __LINE__, "Failed to allocate memory for image.", ITK_LOCATION); } return data; } template void ImportImageContainer::DeallocateManagedMemory() { // Encapsulate all image memory deallocation here if (m_ContainerManageMemory) { delete[] m_ImportPointer; } m_ImportPointer = nullptr; m_Capacity = 0; m_Size = 0; } template void ImportImageContainer::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Pointer: " << static_cast(m_ImportPointer) << std::endl; os << indent << "Container manages memory: " << (m_ContainerManageMemory ? "true" : "false") << std::endl; os << indent << "Size: " << m_Size << std::endl; os << indent << "Capacity: " << m_Capacity << std::endl; } } // end namespace itk #endif