data_type.hpp
1 #pragma once
2 
3 #include <limits>
4 #include <type_traits>
5 #include <utility>
6 
7 
8 #include <cmath>
9 
10 
11 
12 #include "_cexports/c_img.h"
13 
14 #include "global.hpp"
15 #include "exception.hpp"
16 
17 namespace Cvb
18 {
19 
20 CVB_BEGIN_INLINE_NS
21 
22 
23 
25 
27 class DataType final
28 {
29  public:
30 
32 
37  static DataType FromNativeDescriptor(int dataTypeDescriptor) noexcept
38  {
39  return DataType(dataTypeDescriptor);
40  }
41 
43 
47  static DataType Int8BppUnsigned() noexcept
48  {
49  return DataType(8);
50  }
51 
53 
57  static DataType Int8BppSigned() noexcept
58  {
59  return DataType(8 | CExports::DT_Signed);
60  }
61 
63 
67  static DataType Int10BppUnsigned() noexcept
68  {
69  return DataType(10);
70  }
71 
73 
77  static DataType Int12BppUnsigned() noexcept
78  {
79  return DataType(12);
80  }
81 
83 
87  static DataType Int16BppUnsigned() noexcept
88  {
89  return DataType(16);
90  }
91 
93 
97  static DataType Int16BppSigned() noexcept
98  {
99  return DataType(16 | CExports::DT_Signed);
100  }
101 
103 
107  static DataType Int32BppUnsigned() noexcept
108  {
109  return DataType(32);
110  }
111 
113 
117  static DataType Int32BppSigned() noexcept
118  {
119  return DataType(32 | CExports::DT_Signed);
120  }
121 
123 
127  static DataType Int64BppUnsigned() noexcept
128  {
129  return DataType(64);
130  }
131 
133 
137  static DataType Int64BppSigned() noexcept
138  {
139  return DataType(64 | CExports::DT_Signed);
140  }
141 
143 
147  static DataType Float32Bpp() noexcept
148  {
149  return DataType(32 | CExports::DT_Float | CExports::DT_Signed);
150  }
151 
153 
157  static DataType Float64Bpp() noexcept
158  {
159  return DataType(64 | CExports::DT_Float | CExports::DT_Signed);
160  }
161 
162 
163 
165 
180  template<typename T>
181  static DataType FromNativeType() noexcept
182  {
184  "CVB: Unsupported image plane data type!");
185  static_assert((1 << 8) == CExports::DT_Signed,
186  "CVB: DT_Signed does not match!");
187  static_assert((1 << 9) == CExports::DT_Float,
188  "CVB: DT_Float does not match!");
189 
190 
191  CExports::cvbdatatype_t nativeDescriptor = sizeof(T) * 8 // bit size
192  | std::is_signed<T>::value << 8 // set signed bit if signed int or float
193  | std::is_floating_point<T>::value << 9; // set float bit if float
194 
195  return DataType(nativeDescriptor);
196  }
197 
199 
209  template <template<class> class T, class ACTION, class... CTORARGS>
210  auto CallWithInstanceOf(ACTION action, CTORARGS... args) const -> decltype(action(T<int>{std::forward<CTORARGS>(args)...}))
211  {
212  if(this->IsUnsignedInteger())
213  {
214  switch(this->BytesPerPixel())
215  {
216  case 1:
217  {
218  T<std::uint8_t> t{std::forward<CTORARGS>(args)...};
219  return action(t);
220  }
221  case 2:
222  {
223  T<std::uint16_t> t{std::forward<CTORARGS>(args)...};
224  return action(t);
225  }
226  case 4:
227  {
228  T<std::uint32_t> t{std::forward<CTORARGS>(args)...};
229  return action(t);
230  }
231  case 8:
232  {
233  T<std::uint64_t> t{std::forward<CTORARGS>(args)...};
234  return action(t);
235  }
236  default:
237  {
238  break;
239  }
240  }
241  }
242  else if(this->IsSignedInteger())
243  {
244  switch (this->BytesPerPixel())
245  {
246  case 1:
247  {
248  T<std::int8_t> t{std::forward<CTORARGS>(args)...};
249  return action(t);
250  }
251  case 2:
252  {
253  T<std::int16_t> t{std::forward<CTORARGS>(args)...};
254  return action(t);
255  }
256  case 4:
257  {
258  T<std::int32_t> t{std::forward<CTORARGS>(args)...};
259  return action(t);
260  }
261  case 8:
262  {
263  T<std::int64_t> t{std::forward<CTORARGS>(args)...};
264  return action(t);
265  }
266  default:
267  {
268  break;
269  }
270  }
271  }
272  else if(this->IsFloat())
273  {
274  switch (this->BytesPerPixel())
275  {
276  case 4:
277  {
278  T<float> t{std::forward<CTORARGS>(args)...};
279  return action(t);
280  }
281  case 8:
282  {
283  T<double> t{std::forward<CTORARGS>(args)...};
284  return action(t);
285  }
286  default:
287  {
288  break;
289  }
290  }
291  }
292 
293  throw std::runtime_error("Could not match native data type");
294  }
295 
297 
305  template <class T>
306  bool Matches() const noexcept
307  {
309  "CVB: T must be integer or floating point");
310 
311  // floats use specialization below
312  return this->BytesPerPixel() == sizeof(T)
314  && this->IsSigned() == std::is_signed<T>::value;
315  }
316 
318 
322  int NativeDescriptor() const noexcept
323  {
324  return dataTypeDescriptor_;
325  }
326 
328 
332  int BitsPerPixel() const noexcept
333  {
334  return dataTypeDescriptor_ & 0xFF;
335  }
336 
338 
342  int BytesPerPixel() const noexcept
343  {
344  // remember: 0x7 is equivalent to % 8
345  return BitsPerPixel() / 8 + (((BitsPerPixel() & 0x7) != 0) ? 1 : 0);
346  }
347 
349 
353  bool IsFloat() const noexcept
354  {
355  // as defined in iCVCImg.h...
356  return (dataTypeDescriptor_ & CExports::DT_Float) != 0;
357  }
358 
360 
364  bool IsSignedInteger() const noexcept
365  {
366  return (dataTypeDescriptor_ & CExports::DT_Signed) != 0 && !IsFloat();
367  }
368 
370 
374  bool IsUnsignedInteger() const noexcept
375  {
376  return (dataTypeDescriptor_ & 0xB00) == 0;
377  }
378 
380 
384  bool IsSigned() const noexcept
385  {
386  return (dataTypeDescriptor_ & CExports::DT_Signed) != 0;
387  }
388 
390 
394  bool HasOverlayBit() const noexcept
395  {
396  return (dataTypeDescriptor_ & CExports::DT_Overlay) != 0;
397  }
398 
400 
410  bool IsComplexPacked() const noexcept
411  {
412  return (dataTypeDescriptor_ & CExports::DT_ComplexPacked) != 0;
413  }
414 
416 
420  double MinVal() const noexcept
421  {
422  if (IsFloat())
423  {
424 #ifdef min
425 #undef min
426 #endif
427  if (BytesPerPixel() == 4)
428  return static_cast<double>(std::numeric_limits<float>::lowest());
429  else if (BytesPerPixel() == 8)
431  else
433  }
434  else
435  {
436  CExports::cvbval_t min = 0;
437  CExports::cvbval_t max = 0;
438  CVB_CALL_CAPI(GetDatatypeMinMaxVal(static_cast<CExports::cvbdatatype_t>(dataTypeDescriptor_), min, max));
439  return static_cast<double>(min);
440  }
441  }
442 
444 
448  double MaxVal() const noexcept
449  {
450 #ifdef max
451 #undef max
452 #endif
453  if (IsFloat())
454  {
455  if (BytesPerPixel() == 4)
456  return static_cast<double>(std::numeric_limits<float>::max());
457  else if (BytesPerPixel() == 8)
459  else
461  }
462  else
463  {
464  CExports::cvbval_t min = 0;
465  CExports::cvbval_t max = 0;
466  CVB_CALL_CAPI(GetDatatypeMinMaxVal(static_cast<CExports::cvbdatatype_t>(dataTypeDescriptor_), min, max));
467  return static_cast<double>(max);
468  }
469 
470  }
471 
473 
477  PixelDataType NumericType() const noexcept
478  {
479 
480  if ((IsComplexPacked()) && (IsFloat()))
482  else if (IsFloat())
483  return PixelDataType::Float;
484  else if (IsSignedInteger())
485  return PixelDataType::Int;
486  else if (IsUnsignedInteger())
487  return PixelDataType::UInt;
488  else
490 
491  }
492 
493 
495 
502  double UndefinedVal() const noexcept
503  {
504 
506  return round((MaxVal() - MinVal()) / 2.0);
507  else
508  return 0.0;
509 
510  }
511 
513 
518  bool operator==(const DataType& dataType) const noexcept
519  {
520  if (IsFloat() && dataType.IsFloat())
521  return BitsPerPixel() == dataType.BitsPerPixel(); // skip signed bit if float or double
522  return dataTypeDescriptor_ == dataType.dataTypeDescriptor_;
523  }
524 
526 
531  bool operator!=(const DataType& dataType) const noexcept
532  {
533  return !(*this == dataType);
534  }
535 
536 
537 
538  private:
539 
540  DataType(CExports::cvbdatatype_t dataTypeDescriptor) noexcept
541  : dataTypeDescriptor_(dataTypeDescriptor)
542  {
543  }
544 
545 
546  int dataTypeDescriptor_;
547 };
548 
549 
550 CVB_END_INLINE_NS
551 
552 }
553 
static DataType Int10BppUnsigned() noexcept
Represents 10-bit unsigned integer pixels.
Definition: data_type.hpp:67
double UndefinedVal() const noexcept
Get the undefined value for this data type.
Definition: data_type.hpp:502
static DataType FromNativeType() noexcept
Construct a data type descriptor from one of the native data type value equivalents.
Definition: data_type.hpp:181
int NativeDescriptor() const noexcept
Native data type descriptor.
Definition: data_type.hpp:322
static DataType Int16BppUnsigned() noexcept
Represents 16-bit unsigned integer pixels.
Definition: data_type.hpp:87
static DataType Int64BppSigned() noexcept
Represents 64-bit signed integer pixels.
Definition: data_type.hpp:137
bool operator!=(const DataType &dataType) const noexcept
Compares to an other data type.
Definition: data_type.hpp:531
static DataType Float32Bpp() noexcept
Represents single precision (32-bit) floating point pixels.
Definition: data_type.hpp:147
Root namespace for the Image Manager interface.
Definition: version.hpp:11
double MaxVal() const noexcept
Gets the maximum pixel value that fits this data type.
Definition: data_type.hpp:448
bool IsFloat() const noexcept
Gets whether the pixels of the plane have floating point values.
Definition: data_type.hpp:353
T lowest(T... args)
bool IsSigned() const noexcept
Gets whether the pixels of the plane have signed values.
Definition: data_type.hpp:384
auto CallWithInstanceOf(ACTION action, CTORARGS... args) const -> decltype(action(T< int >
Calls action with T instance of native data type this value represents.
Definition: data_type.hpp:210
bool IsComplexPacked() const noexcept
Indicates whether or not the plane contains a complex packed image format.
Definition: data_type.hpp:410
static DataType Int32BppUnsigned() noexcept
Represents 32-bit unsigned integer pixels.
Definition: data_type.hpp:107
bool Matches() const noexcept
Gets whether the type T matches this data type.
Definition: data_type.hpp:306
static DataType Int16BppSigned() noexcept
Represents 16-bit signed integer pixels.
Definition: data_type.hpp:97
static DataType Int8BppUnsigned() noexcept
Represents 8-bit unsigned integer pixels (bytes).
Definition: data_type.hpp:47
T max(T... args)
PixelDataType
Defines the numeric data type of one pixel.
Definition: global.hpp:123
static DataType Int12BppUnsigned() noexcept
Represents 12-bit unsigned integer pixels.
Definition: data_type.hpp:77
static DataType Int64BppUnsigned() noexcept
Represents 64-bit unsigned integer pixels.
Definition: data_type.hpp:127
bool HasOverlayBit() const noexcept
Gets whether bit 0 of the pixels of the plane are being used as an overlay indicator bit.
Definition: data_type.hpp:394
static DataType FromNativeDescriptor(int dataTypeDescriptor) noexcept
Construct a data type descriptor from one of the native library's descriptor values.
Definition: data_type.hpp:37
PixelDataType NumericType() const noexcept
Returns the basic numeric type of the pixels.
Definition: data_type.hpp:477
Data type description for an image plane.
Definition: data_type.hpp:27
static DataType Float64Bpp() noexcept
Represents double precision (64-bit) floating point pixels.
Definition: data_type.hpp:157
int BytesPerPixel() const noexcept
Number of bytes occupied by each pixel.
Definition: data_type.hpp:342
bool IsSignedInteger() const noexcept
Gets whether the pixels of the plane have signed integer values.
Definition: data_type.hpp:364
T quiet_NaN(T... args)
bool operator==(const DataType &dataType) const noexcept
Compares to an other data type.
Definition: data_type.hpp:518
static DataType Int8BppSigned() noexcept
Represents 8-bit signed integer pixels.
Definition: data_type.hpp:57
int BitsPerPixel() const noexcept
Number of actually valid bits per pixel.
Definition: data_type.hpp:332
static DataType Int32BppSigned() noexcept
Represents 32-bit signed integer pixels.
Definition: data_type.hpp:117
bool IsUnsignedInteger() const noexcept
Gets whether the pixels of the plane have unsigned integer values.
Definition: data_type.hpp:374
double MinVal() const noexcept
Gets the minimum pixel value that fits this data type.
Definition: data_type.hpp:420