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
mitkOclImage.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 
17 #include "mitkOclImage.h"
18 #include "mitkImageDataItem.h"
19 #include "mitkCommon.h"
20 #include "mitkLogMacros.h"
21 
22 #include "mitkOclUtils.h"
23 
24 #include <mitkImageReadAccessor.h>
25 #include <fstream>
26 
27 mitk::OclImage::OclImage() : m_gpuImage(NULL), m_context(NULL), m_bufferSize(0), m_gpuModified(false), m_cpuModified(false),
28  m_Image(NULL), m_dim(0), m_Dims(NULL), m_BpE(1), m_formatSupported(false)
29 {
30 }
31 
33 {
34  MITK_INFO << "OclImage Destructor";
35 
36  //release GMEM Image buffer
37  if (m_gpuImage) clReleaseMemObject(m_gpuImage);
38 }
39 
40 
41 cl_mem mitk::OclImage::CreateGPUImage(unsigned int _wi, unsigned int _he, unsigned int _de,
42  unsigned int _bpp)
43 {
44  MITK_INFO << "CreateGPUImage call with: BPP=" << _bpp;
45 
46  this->m_Dims = new unsigned int[MAX_DIMS];
47 
48  m_Dims[0] = _wi;
49  m_Dims[1] = _he;
50  m_Dims[2] = _de;
51 
52  for (unsigned int i=3; i<MAX_DIMS; i++)
53  m_Dims[i] = 1;
54 
55  m_bufferSize = _wi * _he * _de;
56 
57  m_BpE = _bpp;
58 
61 
62  cl_context gpuContext = resources->GetContext();
63 
64  int clErr;
65  m_gpuImage = clCreateBuffer( gpuContext, CL_MEM_READ_WRITE, m_bufferSize * m_BpE, NULL, &clErr);
66 
67  CHECK_OCL_ERR(clErr);
68 
69  return m_gpuImage;
70 }
71 
73 {
74  this->m_Image = _image;
75  this->m_cpuModified = true;
76  this->m_gpuModified = false;
77 
78  this->m_gpuImage = NULL;
79 
80  // compute the size of the GMEM buffer
81  this->m_dim = this->m_Image->GetDimension();
82  this->m_Dims = this->m_Image->GetDimensions();
83  MITK_INFO << "Image: " << this->m_Dims[0] <<"x"<< this->m_Dims[1] <<"x"<< this->m_Dims[2];
84 
85  // get the dimensions
86  this->m_bufferSize = 1;
87  for (unsigned int i=0; i<this->m_dim; i++)
88  {
89  this->m_bufferSize *= this->m_Dims[i];
90  }
91 
92  // multiply by sizeof(PixelType)
93  this->m_BpE = ( this->m_Image->GetPixelType().GetBpe() / 8);
94 }
95 
97 {
98  if (_type) return m_cpuModified;
99  else return m_gpuModified;
100 }
101 
103 {
104  // defines... GPU: 0, CPU: 1
105  m_cpuModified = _type;
106  m_gpuModified = !_type;
107 }
108 
109 int mitk::OclImage::TransferDataToGPU(cl_command_queue gpuComQueue)
110 {
111  cl_int clErr = 0;
112 
113  // check whether an image present
114  if (!m_Image->IsInitialized()){
115  MITK_ERROR("ocl.Image") << "(mitk) Image not initialized!\n";
116  return -1;
117  }
118 
119  // there is a need for copy only if RAM-Data newer then GMEM data
120  if (m_cpuModified)
121  {
122  //check the buffer
123  if(m_gpuImage == NULL)
124  {
125  clErr = this->AllocateGPUImage();
126  }
127 
128  if (m_Image->IsInitialized() &&
129  (clErr == CL_SUCCESS))
130  {
131  const size_t origin[3] = {0, 0, 0};
132  const size_t region[3] = {m_Dims[0], m_Dims[1], m_Dims[2]};
133 
134  if( this->m_formatSupported )
135  {
136  mitk::ImageReadAccessor accessor(m_Image);
137  clErr = clEnqueueWriteImage( gpuComQueue, m_gpuImage, CL_TRUE, origin, region, 0, 0, accessor.GetData(), 0, NULL, NULL);
138  }
139  else
140  {
141  MITK_ERROR << "Selected image format currently not supported...";
142  }
143 
144  CHECK_OCL_ERR(clErr);
145  }
146  m_gpuModified = true;
147  }
148 
149  return clErr;
150 }
151 
152 cl_int mitk::OclImage::AllocateGPUImage()
153 {
154  cl_int clErr = 0;
155 
158 
159  cl_context gpuContext = resources->GetContext();
160 
161  // initialize both proposed and supported format variables to same value
162  this->m_proposedFormat = this->ConvertPixelTypeToOCLFormat();
163  this->m_supportedFormat = this->m_proposedFormat;
164 
165  // test the current format for HW support
166  this->m_formatSupported = resources->GetIsFormatSupported( &(this->m_supportedFormat) );
167 
168  // create an transfer kernel object in case the proposed format is not supported
169  if( !(this->m_formatSupported) )
170  {
171  mitkThrowException(mitk::ImageTypeIsNotSupportedByGPU) << "Original format not supported on the installed graphics card.";
172  }
173 
174  // create new buffer
175  if( this->m_dim > 2)
176  {
177  //Create a 3D Image
178  m_gpuImage = clCreateImage3D(gpuContext, CL_MEM_READ_ONLY, &m_supportedFormat, *(m_Dims), *(m_Dims+1), *(m_Dims+2), 0, 0, NULL, &clErr);
179  }
180  else
181  {
182  //Create a 2D Image
183  m_gpuImage = clCreateImage2D(gpuContext, CL_MEM_READ_ONLY, &m_supportedFormat, *(m_Dims), *(m_Dims+1), 0, NULL, &clErr);
184  }
185  CHECK_OCL_ERR(clErr);
186 
187  return clErr;
188 }
189 
190 cl_mem mitk::OclImage::GetGPUImage(cl_command_queue gpuComQueue)
191 {
192  // clGetMemObjectInfo()
193  cl_mem_object_type memInfo;
194  cl_int clErr = 0;
195 
196  // query image object info only if already initialized
197  if( this->m_gpuImage )
198  {
199  clErr = clGetMemObjectInfo(this->m_gpuImage, CL_MEM_TYPE, sizeof(cl_mem_object_type), &memInfo, NULL );
200  CHECK_OCL_ERR(clErr);
201  }
202 
203  MITK_INFO << "Querying info for object, recieving: " << memInfo;
204 
205  // test if m_gpuImage CL_MEM_IMAGE_2/3D
206  // if not, copy buffer to image
207  if (memInfo == CL_MEM_OBJECT_BUFFER)
208  {
209  MITK_WARN << " Passed oclImage is a buffer-object, creating image";
210 
211  //hold a copy of the buffer gmem pointer
212  cl_mem tempBuffer = this->m_gpuImage;
213 
214  const size_t origin[3] = {0, 0, 0};
215  size_t region[3] = {this->m_Dims[0], this->m_Dims[1], 1};
216 
217  clErr = this->AllocateGPUImage();
218 
219  this->m_dim = 3;
220 
221  //copy last data to the image data
222  clErr = clEnqueueCopyBufferToImage( gpuComQueue, tempBuffer, m_gpuImage, 0, origin, region, 0, NULL, NULL);
223  CHECK_OCL_ERR(clErr);
224 
225  //release pointer
226  clReleaseMemObject(tempBuffer);
227  }
228  return m_gpuImage;
229 }
230 
231 void mitk::OclImage::SetPixelType(const cl_image_format *_image)
232 {
233  this->m_proposedFormat.image_channel_data_type = _image->image_channel_data_type;
234  this->m_proposedFormat.image_channel_order = _image->image_channel_order;
235 }
236 
237 void* mitk::OclImage::TransferDataToCPU(cl_command_queue gpuComQueue)
238 {
239  cl_int clErr = 0;
240 
241  // if image created on GPU, needs to create mitk::Image
242  if( m_Image.IsNull() ){
243  MITK_INFO << "Image not initialized, creating new one.";
244  m_Image = mitk::Image::New();
245  }
246 
247  // check buffersize/image size
248  char* data = new char[m_bufferSize * m_BpE];
249 
250  // debug info
251  oclPrintMemObjectInfo( m_gpuImage );
252 
253  clErr = clEnqueueReadBuffer( gpuComQueue, m_gpuImage, CL_FALSE, 0, m_bufferSize * m_BpE, data ,0, NULL, NULL);
254  CHECK_OCL_ERR(clErr);
255 
256  clFlush( gpuComQueue );
257  // the cpu data is same as gpu
258  this->m_gpuModified = false;
259 
260  return (void*) data;
261 }
262 
263 cl_image_format mitk::OclImage::ConvertPixelTypeToOCLFormat()
264 {
265  cl_image_format texFormat;
266  //single channel Gray-Valued Images
267  texFormat.image_channel_order = CL_R;
268 
269  MITK_INFO << "Class own value: " << this->m_BpE;
270 
271  switch ( this->m_BpE )
272  {
273  case 1:
274  texFormat.image_channel_data_type = CL_UNSIGNED_INT8;
275  MITK_INFO<< "PixelType: UCHAR => CLFormat: [CL_UNORM_INT8, CL_R]";
276  break;
277  case 2:
278  texFormat.image_channel_data_type = CL_SIGNED_INT16;
279  // texFormat.image_channel_order = CL_R;
280  MITK_INFO<< "PixelType: SHORT => CLFormat: [CL_SIGNED_INT16, CL_R]";
281  break;
282  case 4:
283  texFormat.image_channel_data_type = CL_FLOAT;
284  MITK_INFO<< "Choosing CL_FLOAT";
285  break;
286  default:
287  texFormat.image_channel_data_type = CL_UNORM_INT8;
288  texFormat.image_channel_order = CL_RG;
289  MITK_INFO<< "Choosing (default) short: 2-Channel UCHAR";
290  break;
291  }
292 
293  return texFormat;
294 }
295 
297 {
298  if (this->m_dim > idx)
299  {
300  return m_Dims[idx];
301  }
302  else
303  {
304  MITK_WARN << "Trying to access non-existing dimension.";
305  return 1;
306  }
307 }
308 
309 void mitk::OclImage::SetDimensions(unsigned int* Dims)
310 {
311  m_Dims = Dims;
312 }
313 
314 void mitk::OclImage::SetDimension(unsigned short dim)
315 {
316  m_dim = dim;
317 }
318 
320 {
321  if (this->m_dim > idx)
322  {
323  const mitk::Vector3D imSpacing = m_Image->GetSlicedGeometry()->GetSpacing();
324 
325  return imSpacing[idx];
326  }
327  else
328  {
329  MITK_WARN << "Trying to access non-existing dimension.";
330  return 1;
331  }
332 }
333 
335 {
336  this->m_Image = mitk::Image::New();
337 }
338 
339 void mitk::OclImage::GetOffset(float* _imOffset) const
340 {
341  itk::Vector<float, 3> result2;
342  result2.Fill(0.0f);
343 
344  result2 = this->m_Image->GetGeometry()->GetIndexToWorldTransform()->GetOffset();
345 
346  _imOffset[0] = result2[0];
347  _imOffset[1] = result2[1];
348  _imOffset[2] = result2[2];
349 }
#define CHECK_OCL_ERR(_er)
Definition: mitkOclUtils.h:25
virtual ~OclImage()
Destructor.
ServiceReferenceU GetServiceReference(const std::string &clazz)
cl_mem CreateGPUImage(unsigned int, unsigned int, unsigned int, unsigned int)
#define MITK_INFO
Definition: mitkLogMacros.h:22
cl_mem GetGPUImage(cl_command_queue)
Checks whether gpuImage is a valid clImage object.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
const void * GetData() const
Gives const access to the data.
The ImageTypeIsNotSupportedByGPU class specialized exception class for unsupported image formats...
Definition: mitkOclImage.h:197
void GetOffset(float *) const
Returns the image offset (needed for WorldToIndex Transform.
void * GetService(const ServiceReferenceBase &reference)
void SetDimensions(unsigned int *Dims)
Set the image dimensions through an unsigned int array.
int GetDimension() const
returns the dimensionality of the image
Definition: mitkOclImage.h:109
OclImage()
Constructor.
void SetDimension(unsigned short dim)
Set the dimensionality of the image.
#define MITK_WARN
Definition: mitkLogMacros.h:23
float GetSpacing(int)
returns the spacing of the image for specified dimension
void InitializeMITKImage()
Initialize the internal variable of type mitk::Image.
virtual void * TransferDataToCPU(cl_command_queue)
Copies the in GMEM stored data to RAM.
bool IsModified(int _type)
Returns the status of the image buffer.
virtual int TransferDataToGPU(cl_command_queue)
Copies the RAM-stored data to GMEM.
static Pointer New()
#define mitkThrowException(classname)
void InitializeByMitkImage(mitk::Image::Pointer _image)
Initialze the OclImage with an mitkImage.
#define MAX_DIMS
Definition: mitkOclImage.h:23
virtual cl_context GetContext() const =0
Returns a valid OpenCL Context (if applicable) or NULL if none present.
ImageReadAccessor class to get locked read access for a particular image part.
void Modified(int _type)
Set the modified flag for one of the buffers.
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void oclPrintMemObjectInfo(cl_mem memobj)
Prints the available memory info about the given object to std::cout.
void SetPixelType(const cl_image_format *)
Set the pixel type for the image to be used.
Declaration of the OpenCL Resources micro-service.