Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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