mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
milkImage.hpp
Go to the documentation of this file.
1 /** \file milkImage.hpp
2  * \brief Interface to MILK::ImageStreamIO shared memory streams
3  * \ingroup image_processing_files
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef improc_milkImage_hpp
28 #define improc_milkImage_hpp
29 
30 #ifdef MXLIB_MILK
31 
32 #ifdef MXLIB_CUDA
33 #define HAVE_CUDA
34 #endif
35 
36 #include <ImageStreamIO/ImageStreamIO.h>
37 
38 #include "../mxException.hpp"
39 #include "eigenImage.hpp"
40 
41 namespace mx
42 {
43 namespace improc
44 {
45 
46 template<typename typeT>
47 struct ImageStructTypeCode;
48 
49 template<>
50 struct ImageStructTypeCode<uint8_t>
51 {
52  constexpr static int TypeCode = _DATATYPE_UINT8;
53 };
54 
55 template<>
56 struct ImageStructTypeCode<int8_t>
57 {
58  constexpr static int TypeCode = _DATATYPE_INT8;
59 };
60 
61 template<>
62 struct ImageStructTypeCode<char>
63 {
64  constexpr static int TypeCode = _DATATYPE_INT8;
65 };
66 
67 template<>
68 struct ImageStructTypeCode<uint16_t>
69 {
70  constexpr static int TypeCode = _DATATYPE_UINT16;
71 };
72 
73 template<>
74 struct ImageStructTypeCode<int16_t>
75 {
76  constexpr static int TypeCode = _DATATYPE_INT16;
77 };
78 
79 template<>
80 struct ImageStructTypeCode<uint32_t>
81 {
82  constexpr static int TypeCode = _DATATYPE_UINT32;
83 };
84 
85 template<>
86 struct ImageStructTypeCode<int32_t>
87 {
88  constexpr static int TypeCode = _DATATYPE_INT32;
89 };
90 
91 template<>
92 struct ImageStructTypeCode<uint64_t>
93 {
94  constexpr static int TypeCode = _DATATYPE_UINT64;
95 };
96 template<>
97 struct ImageStructTypeCode<int64_t>
98 {
99  constexpr static int TypeCode = _DATATYPE_INT64;
100 };
101 template<>
102 struct ImageStructTypeCode<float>
103 {
104  constexpr static int TypeCode = _DATATYPE_FLOAT;
105 };
106 
107 template<>
108 struct ImageStructTypeCode<double>
109 {
110  constexpr static int TypeCode = _DATATYPE_DOUBLE;
111 };
112 
113 template<>
114 struct ImageStructTypeCode<std::complex<float>>
115 {
116  constexpr static int TypeCode = _DATATYPE_COMPLEX_FLOAT;
117 };
118 
119 template<>
120 struct ImageStructTypeCode<std::complex<double>>
121 {
122  constexpr static int TypeCode = _DATATYPE_COMPLEX_DOUBLE;
123 };
124 
125 /// Class to interface with an ImageStreamIO image in shared memory
126 /**
127  *
128  * Use with Eigen::Map (aliased as mx::improc::eigenMap)
129  * \code
130  * using namespace mx::improc;
131  * milkImage<float> mim("image"); //connects to image.im.shm
132  * eigenMap<float> im(mim); //the conversion operator passes a reference to the internal map
133  * im.setRandom(); // im is now a map pointed at the image data. Eigen functions are now available.
134  * im(64,64) *= 2000;
135  * im /= 0.2;
136  * \endcode
137  * Once you have changed something via the Eigen::Map you want to notify others connected to the stream
138  * via
139  * \code
140  * mim.post();
141  * \endcode
142  *
143  * \ingroup eigen_image_processing
144  */
145 template<typename _dataT>
147 {
148 public:
149 
150  typedef _dataT dataT; ///< The data type
151 
152 protected:
153 
154  std::string m_name; ///< The image name, from name.im.shm (the .im.shm should not be given).
155 
156  IMAGE * m_image {nullptr}; ///< Pointer to the ImageStreamIO IMAGE structure.
157 
158  dataT * m_raw {nullptr}; //The raw pointer address is stored here for checks
159 
160  uint64_t m_size_0 {0}; ///< The size[0] of the image when last opened.
161 
162  uint64_t m_size_1 {0}; ///< The size[1] of the image when last opened.
163 
164 public:
165 
166  /// Default c'tor
167  milkImage();
168 
169  /// Constructor which opens the specified image
170  milkImage( const std::string & imname /**< [in] The image name, from name.im.shm (the .im.shm should not be given).*/ );
171 
172  /// Open and connect to an image, allocating the eigenMap.
173  /**
174  * \throws std::invalid_argument if the image type_code does not match dataT.
175  */
176  void open( const std::string & imname /**< [in] The image name, from name.im.shm (the .im.shm should not be given).*/);
177 
178  /// Create and connect to an image, allocating the eigenMap.
179  /**
180  * \throws std::invalid_argument if the image type_code does not match dataT.
181  */
182  void create( const std::string & imname, ///< [in] The image name, for name.im.shm (the .im.shm should not be given).
183  uint32_t sz0, ///< [in] the x size of the image
184  uint32_t sz1 ///< [in] the y size of the image
185  );
186 
187  /// Checks if the image is connected and is still the same format as when connected.
188  /** Checks on pointer value, size[], and data_type.
189  *
190  * \returns true if connected and no changes
191  * \returns false if not connected or something changed. All maps are now invalid.
192  */
193  bool valid();
194 
195  /// Reopens the image.
196  /** Same as
197  * \code
198  * close();
199  * open(m_name);
200  * \endcode
201  */
202  void reopen();
203 
204  // Close the image
205  void close();
206 
207  /// Conversion operator returns an eigenMap
208  /** Use this like
209  * \code
210  * milkImage<float> mim("imname");
211  * eigenMap<float> im(mim); //you now have an Eigen interface to the image
212  * \endcode
213  * but with caution:
214  * - there is no way to know if the image has changed
215  *
216  * Note: we assume this does a move
217  *
218  * \returns an Eigen::Map<Array,-1,-1> object
219  *
220  * \throws mx::err::mxException if the image is not opened
221  *
222  */
223  operator eigenMap<dataT>();
224 
225  /// Update the metadata and post all semaphores
226  /**
227  * \throws mx::err::mxException if the image is not opened
228  */
229  void post();
230 
231 };
232 
233 template<typename dataT>
235 {
236 }
237 
238 template<typename dataT>
239 milkImage<dataT>::milkImage( const std::string & imname )
240 {
241  open(imname);
242 }
243 
244 template<typename dataT>
245 void milkImage<dataT>::open( const std::string & imname )
246 {
247  if(m_image)
248  {
249  ImageStreamIO_closeIm(m_image);
250  delete m_image;
251  m_image = nullptr;
252  }
253 
254  m_image = new IMAGE;
255 
256  errno_t rv = ImageStreamIO_openIm(m_image, imname.c_str());
257 
258  if(rv != IMAGESTREAMIO_SUCCESS)
259  {
260  delete m_image;
261  m_image = nullptr;
262  throw err::mxException("", 0, "", 0, "", 0, "ImageStreamIO_openIm returned an error");
263  }
264 
265  if(ImageStructTypeCode<dataT>::TypeCode != m_image->md->datatype)
266  {
267  delete m_image;
268  m_image = nullptr;
269  throw std::invalid_argument("shmim datatype does not match template type");
270  }
271 
272  m_name = imname;
273  m_raw = (dataT*) m_image->array.raw;
274  m_size_0 = m_image->md->size[0];
275  m_size_1 = m_image->md->size[1];
276 }
277 
278 template<typename dataT>
279 void milkImage<dataT>::create( const std::string & imname,
280  uint32_t sz0,
281  uint32_t sz1
282  )
283 {
284  if(m_image)
285  {
286  ImageStreamIO_closeIm(m_image);
287  delete m_image;
288  m_image = nullptr;
289  }
290 
291  m_image = new IMAGE;
292 
293  uint32_t imsize[3];
294  imsize[0] = sz0;
295  imsize[1] = sz1;
296  imsize[2] = 1;
297 
298  errno_t rv = ImageStreamIO_createIm_gpu(m_image, imname.c_str(), 3, imsize, ImageStructTypeCode<dataT>::TypeCode,
299  -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL, 0);
300 
301  if(rv != IMAGESTREAMIO_SUCCESS)
302  {
303  delete m_image;
304  m_image = nullptr;
305  throw err::mxException("", 0, "", 0, "", 0, "ImageStreamIO_createIm_gpu returned an error");
306  }
307 
308  if(ImageStructTypeCode<dataT>::TypeCode != m_image->md->datatype)
309  {
310  delete m_image;
311  m_image = nullptr;
312  throw std::invalid_argument("shmim datatype does not match template type");
313  }
314 
315  m_name = imname;
316  m_raw = (dataT*) m_image->array.raw;
317  m_size_0 = m_image->md->size[0];
318  m_size_1 = m_image->md->size[1];
319 
320 }
321 
322 template<typename dataT>
324 {
325  if(m_image == nullptr)
326  {
327  throw err::mxException("", 0, "", 0, "", 0, "Image is not open");
328  }
329 
330  if(!valid())
331  {
332  throw err::mxException("", 0, "", 0, "", 0, "Image is not valid");
333  }
334 
335  return eigenMap<dataT>((dataT*)m_image->array.raw, m_image->md->size[0], m_image->md->size[1]);
336 }
337 
338 template<typename dataT>
340 {
341  close();
342  open(m_name);
343 }
344 
345 template<typename dataT>
347 {
348  if(m_image == nullptr)
349  {
350  throw err::mxException("", 0, "", 0, "", 0, "Image is not open");
351  }
352 
353  errno_t rv = ImageStreamIO_closeIm(m_image);
354  delete m_image;
355  m_image = nullptr;
356 
357  if(rv != IMAGESTREAMIO_SUCCESS) throw err::mxException("", 0, "", 0, "", 0, "ImageStreamIO_closeIm returned an error");
358 }
359 
360 template<typename dataT>
362 {
363  if(m_image == nullptr)
364  {
365  return false;
366  }
367 
368  if( m_raw != (dataT*) m_image->array.raw ||
369  m_size_0 != m_image->md->size[0] ||
370  m_size_1 != m_image->md->size[1] ||
371  ImageStructTypeCode<dataT>::TypeCode != m_image->md->datatype )
372  {
373  return false;
374  }
375 
376  return true;
377 }
378 
379 template<typename dataT>
381 {
382  if(m_image == nullptr)
383  {
384  throw err::mxException("", 0, "", 0, "", 0, "Image is not open");
385  }
386 
387  errno_t rv = ImageStreamIO_UpdateIm(m_image);
388 
389  if(rv != IMAGESTREAMIO_SUCCESS) throw err::mxException("", 0, "", 0, "", 0, "ImageStreamIO_closeIm returned an error");
390 }
391 
392 }
393 }
394 
395 #endif //MXLIB_MILK
396 #endif //improc_milkImage_hpp
397 
The mxlib exception class.
Definition: mxException.hpp:45
Class to interface with an ImageStreamIO image in shared memory.
Definition: milkImage.hpp:147
milkImage()
Default c'tor.
Definition: milkImage.hpp:234
uint64_t m_size_1
The size[1] of the image when last opened.
Definition: milkImage.hpp:162
void create(const std::string &imname, uint32_t sz0, uint32_t sz1)
Create and connect to an image, allocating the eigenMap.
Definition: milkImage.hpp:279
IMAGE * m_image
Pointer to the ImageStreamIO IMAGE structure.
Definition: milkImage.hpp:156
_dataT dataT
The data type.
Definition: milkImage.hpp:150
std::string m_name
The image name, from name.im.shm (the .im.shm should not be given).
Definition: milkImage.hpp:154
bool valid()
Checks if the image is connected and is still the same format as when connected.
Definition: milkImage.hpp:361
void reopen()
Reopens the image.
Definition: milkImage.hpp:339
void post()
Update the metadata and post all semaphores.
Definition: milkImage.hpp:380
void open(const std::string &imname)
Open and connect to an image, allocating the eigenMap.
Definition: milkImage.hpp:245
uint64_t m_size_0
The size[0] of the image when last opened.
Definition: milkImage.hpp:160
Tools for using the eigen library for image processing.
Eigen::Map< Eigen::Array< scalarT, -1, -1 > > eigenMap
Definition of the eigenMap type, which is an alias for Eigen::Map<Array>.
Definition: eigenImage.hpp:50
The mxlib c++ namespace.
Definition: mxError.hpp:107