Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkCompressedImageContainer.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 #include "mitkImageReadAccessor.h"
19 
20 #include "itk_zlib.h"
21 
22 #include <stdlib.h>
23 
24 mitk::CompressedImageContainer::CompressedImageContainer() : m_PixelType(nullptr), m_ImageGeometry(nullptr)
25 {
26 }
27 
29 {
30  for (auto iter = m_ByteBuffers.begin(); iter != m_ByteBuffers.end(); ++iter)
31  {
32  free(iter->first);
33  }
34 
35  delete m_PixelType;
36 }
37 
39 {
40  for (auto iter = m_ByteBuffers.begin(); iter != m_ByteBuffers.end(); ++iter)
41  {
42  free(iter->first);
43  }
44 
45  m_ByteBuffers.clear();
46 
47  // Compress diff image using zlib (will be restored on demand)
48  // determine memory size occupied by voxel data
49  m_ImageDimension = image->GetDimension();
50  m_ImageDimensions.clear();
51 
52  m_PixelType = new mitk::PixelType(image->GetPixelType());
53 
54  m_OneTimeStepImageSizeInBytes = m_PixelType->GetSize(); // bits per element divided by 8
55  for (unsigned int i = 0; i < m_ImageDimension; ++i)
56  {
57  unsigned int currentImageDimension = image->GetDimension(i);
58  m_ImageDimensions.push_back(currentImageDimension);
59  if (i < 3)
60  {
61  m_OneTimeStepImageSizeInBytes *= currentImageDimension; // only the 3D memory size
62  }
63  }
64 
65  m_ImageGeometry = image->GetGeometry();
66 
67  m_NumberOfTimeSteps = 1;
68  if (m_ImageDimension > 3)
69  {
70  m_NumberOfTimeSteps = image->GetDimension(3);
71  }
72 
73  for (unsigned int timestep = 0; timestep < m_NumberOfTimeSteps; ++timestep)
74  {
75  // allocate a buffer as specified by zlib
76  unsigned long bufferSize =
77  m_OneTimeStepImageSizeInBytes + static_cast<unsigned long>(m_OneTimeStepImageSizeInBytes * 0.2) + 12;
78  unsigned char *byteBuffer = (unsigned char *)malloc(bufferSize);
79 
80  if (itk::Object::GetDebug())
81  {
82  // compress image here into a buffer
83  MITK_INFO << "Using ZLib version: '" << zlibVersion() << "'" << std::endl
84  << "Attempting to compress " << m_OneTimeStepImageSizeInBytes << " image bytes into a buffer of size "
85  << bufferSize << std::endl;
86  }
87 
88  ImageReadAccessor imgAcc(image, image->GetVolumeData(timestep));
89  ::Bytef *dest(byteBuffer);
90  ::uLongf destLen(bufferSize);
91  ::Bytef *source((unsigned char *)imgAcc.GetData());
92  ::uLongf sourceLen(m_OneTimeStepImageSizeInBytes);
93  int zlibRetVal = ::compress(dest, &destLen, source, sourceLen);
94  if (itk::Object::GetDebug())
95  {
96  if (zlibRetVal == Z_OK)
97  {
98  MITK_INFO << "Success, using " << destLen << " bytes of the buffer (ratio "
99  << ((double)destLen / (double)sourceLen) << ")" << std::endl;
100  }
101  else
102  {
103  switch (zlibRetVal)
104  {
105  case Z_MEM_ERROR:
106  MITK_ERROR << "not enough memory" << std::endl;
107  break;
108  case Z_BUF_ERROR:
109  MITK_ERROR << "output buffer too small" << std::endl;
110  break;
111  default:
112  MITK_ERROR << "other, unspecified error" << std::endl;
113  break;
114  }
115  }
116  }
117 
118  // only use the neccessary amount of memory, realloc the buffer!
119  byteBuffer = (unsigned char *)realloc(byteBuffer, destLen);
120  bufferSize = destLen;
121  // MITK_INFO << "Using " << bufferSize << " bytes to store compressed image (" << destLen << " needed)" <<
122  // std::endl;
123 
124  m_ByteBuffers.push_back(std::pair<unsigned char *, unsigned long>(byteBuffer, bufferSize));
125  }
126 }
127 
129 {
130  if (m_ByteBuffers.empty())
131  return nullptr;
132 
133  // uncompress image data, create an Image
134  Image::Pointer image = Image::New();
135  unsigned int dims[20]; // more than 20 dimensions and bang
136  for (unsigned int dim = 0; dim < m_ImageDimension; ++dim)
137  dims[dim] = m_ImageDimensions[dim];
138 
139  image->Initialize(*m_PixelType, m_ImageDimension, dims); // this IS needed, right ?? But it does allocate memory ->
140  // does create one big lump of memory (also in windows)
141 
142  unsigned int timeStep(0);
143  for (auto iter = m_ByteBuffers.begin(); iter != m_ByteBuffers.end(); ++iter, ++timeStep)
144  {
145  ImageReadAccessor imgAcc(image, image->GetVolumeData(timeStep));
146  ::Bytef *dest((unsigned char *)imgAcc.GetData());
147  ::uLongf destLen(m_OneTimeStepImageSizeInBytes);
148  ::Bytef *source(iter->first);
149  ::uLongf sourceLen(iter->second);
150  int zlibRetVal = ::uncompress(dest, &destLen, source, sourceLen);
151  if (itk::Object::GetDebug())
152  {
153  if (zlibRetVal == Z_OK)
154  {
155  MITK_INFO << "Success, destLen now " << destLen << " bytes" << std::endl;
156  }
157  else
158  {
159  switch (zlibRetVal)
160  {
161  case Z_DATA_ERROR:
162  MITK_ERROR << "compressed data corrupted" << std::endl;
163  break;
164  case Z_MEM_ERROR:
165  MITK_ERROR << "not enough memory" << std::endl;
166  break;
167  case Z_BUF_ERROR:
168  MITK_ERROR << "output buffer too small" << std::endl;
169  break;
170  default:
171  MITK_ERROR << "other, unspecified error" << std::endl;
172  break;
173  }
174  }
175  }
176  }
177 
178  image->SetGeometry(m_ImageGeometry);
179  image->Modified();
180 
181  return image;
182 }
#define MITK_INFO
Definition: mitkLogMacros.h:22
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void SetImage(Image *)
Creates a compressed version of the image.
virtual ImageDataItemPointer GetVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:330
Image::Pointer GetImage()
Creates a full mitk::Image from its compressed version.
Image class for storing images.
Definition: mitkImage.h:76
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:105
static Pointer New()
unsigned short PixelType
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
ImageReadAccessor class to get locked read access for a particular image part.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129