meta_data.hpp
1 #pragma once
2 
3 #include <memory>
4 
5 #include "../global.hpp"
6 #include "../_cexports/c_img.h"
7 #include "../string.hpp"
8 #include "../_cexports/c_spectral.h"
9 #include "spectral.hpp"
10 #include "../exception.hpp"
11 #include <cctype>
12 #include <algorithm>
13 
14 
15 namespace Cvb
16 {
17  CVB_BEGIN_INLINE_NS
18 
19  template <>
20  inline HandleGuard<Spectral::MetaData>::HandleGuard(void * handle) noexcept
21  : HandleGuard<Spectral::MetaData>(handle, [](void* handle) { CVB_CALL_CAPI(ReleaseObject(handle)); })
22  {
23  }
24 
25  namespace Spectral
26  {
27 
28 
30 
32  class MetaData final
33  {
34  public:
35 
37 
53  template<class T>
54  T ReadField(const FieldID& fieldId) const
55  {
56  T val;
57  GetField(fieldId, val);
58  return val;
59  }
60 
61 
63 
78  template<class T>
79  void WriteField(FieldID fieldId, const T& value)
80  {
81  WriteFieldTyped(fieldId, value);
82  }
83 
84 
86 
93  {
94  size_t sz = 0;
95  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetFieldnameAsStringTyped(handle_.Handle(),
96  static_cast<CExports::CVSField>(fieldId),
97  reinterpret_cast<Char*>(NULL), sz));
98  std::vector<Char> cvbVal(sz);
99  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetFieldnameAsStringTyped(handle_.Handle(),
100  static_cast<CExports::CVSField>(fieldId),
101  cvbVal.data(), sz));
102  return String(cvbVal.data());
103  }
104 
106 
113  {
114  auto fieldType = CFieldType(fieldId);
115  return static_cast<Spectral::FieldType>(fieldType);
116  }
117 
119 
124  int NumberOfFields() const
125  {
126  auto valOut = Internal::DoResCallValueOut<size_t>([&](size_t& val)
127  {
128  return CVB_CALL_CAPI(CVSMetaDataGetNumberOfFields(handle_.Handle(), val));
129  });
130  return static_cast<int>(valOut);
131  }
132 
134 
139  void ClearField(FieldID fieldId)
140  {
141  Internal::DoResCall([&]()
142  {
143  return CVB_CALL_CAPI(CVSMetaDataClearField(handle_.Handle(),
144  static_cast<CExports::CVSField>(fieldId)));
145  });
146  }
147 
149 
155  bool IsFieldDefined(FieldID fieldId)
156  {
157  auto valOut = Internal::DoResCallValueOut<CExports::cvbbool_t>([&](CExports::cvbbool_t& isDefined)
158  {
159  return CVB_CALL_CAPI(CVSMetaDataIsFieldDefined(handle_.Handle(),
160  static_cast<CExports::CVSField>(fieldId),
161  isDefined));
162  });
163  return valOut ? true : false;
164  }
165 
167 
172  int Samples() const
173  {
174  return ReadField<int>(FieldID::Samples);
175  }
176 
178 
183  int Lines() const
184  {
185  return ReadField<int>(FieldID::Lines);
186  }
187 
189 
194  int Bands() const
195  {
196  return ReadField<int>(FieldID::Bands);
197  }
198 
200 
206  {
207  auto interleaveStr = ReadField<String>(FieldID::Interleave);
208  std::transform(interleaveStr.begin(), interleaveStr.end(), interleaveStr.begin(), [](String::value_type ch)
209  {
210  return static_cast<String::value_type>(std::toupper(ch));
211  });
212  if (interleaveStr == CVB_LIT("BIL"))
214  if (interleaveStr == CVB_LIT("BSQ"))
216  if (interleaveStr == CVB_LIT("BIP"))
218 
219  throw Cvb::CvbException::FromCvbResult(CExports::CVC_E_NOTSUPPORTED, "Unknown interleaved type");
220  }
221 
223 
229  {
230  return ReadField<std::vector<double>>(FieldID::Wavelength);
231  }
232 
233 
235 
241  {
242  return Internal::DoResCallObjectOut<MetaData>([&](void* & metaDataOut)
243  {
244  return CVB_CALL_CAPI(CVSCreateMetaData(metaDataOut));
245  });
246  }
247 
249 
253  void* Handle() const noexcept
254  {
255  return handle_.Handle();
256  }
257 
259 
267  static std::unique_ptr<MetaData> FromHandle(HandleGuard<MetaData>&& guard)
268  {
269  if (!guard.Handle())
270  throw std::runtime_error("handle must not be null");
271  return std::unique_ptr<MetaData>(new MetaData(std::move(guard)));
272  }
273 
274 
275  private:
276  MetaData(HandleGuard<MetaData>&& guard) noexcept
277  : handle_(std::move(guard))
278  {
279  }
280 
281  MetaData(MetaData && other) noexcept
282  : handle_(std::move(other.handle_))
283  {
284  }
285 
286  MetaData & operator=(MetaData && other) = default;
287 
288 
289  void GetField(FieldID fieldId, int& valueOut) const
290  {
291  CExports::cvbint64_t cvbVal = 0;
292  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsInteger(handle_.Handle(),
293  static_cast<CExports::CVSField>(fieldId), cvbVal));
294  valueOut = static_cast<int>(cvbVal);
295  }
296 
297 
298  void GetField(FieldID fieldId, double& valueOut) const
299  {
300  double cvbVal = 0;
301  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsFloat(handle_.Handle(),
302  static_cast<CExports::CVSField>(fieldId), cvbVal));
303  valueOut = std::move(cvbVal);
304  }
305 
306 
307  void GetField(FieldID fieldId, String& valueOut) const
308  {
309  size_t sz = 0;
310  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsStringTyped(handle_.Handle(),
311  static_cast<CExports::CVSField>(fieldId), reinterpret_cast<char*>(NULL), sz));
312  std::vector<char> cvbVal(sz);
313  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsStringTyped(handle_.Handle(),
314  static_cast<CExports::CVSField>(fieldId), cvbVal.data(), sz));
315  std::string str(cvbVal.data());
316  valueOut = String(str.begin(), str.end());
317  }
318 
319 
320  void GetField(FieldID fieldId, std::vector<int>& valueOut) const
321  {
322  size_t sz = 0;
323  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetArraySize(handle_.Handle(),
324  static_cast<CExports::CVSField>(fieldId), sz));
325  std::vector<int> cvbVal(sz);
326  for (CExports::cvbval_t i = 0; i < static_cast<CExports::cvbval_t>(sz); ++i)
327  {
328  CExports::cvbint64_t cvbElement = 0;
329  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsIntegerArray(handle_.Handle(),
330  static_cast<CExports::CVSField>(fieldId), i, cvbElement));
331  cvbVal.at(i) = static_cast<int>(cvbElement);
332  }
333  valueOut = std::move(cvbVal);
334  }
335 
336 
337  void GetField(FieldID fieldId, std::vector<double>& valueOut) const
338  {
339  size_t sz = 0;
340  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetArraySize(handle_.Handle(),
341  static_cast<CExports::CVSField>(fieldId), sz));
342  std::vector<double> cvbVal(sz);
343  for (CExports::cvbval_t i = 0; i < static_cast<CExports::cvbval_t>(sz); ++i)
344  {
345  double cvbElement = 0;
346  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsFloatArray(handle_.Handle(),
347  static_cast<CExports::CVSField>(fieldId), i, cvbElement));
348  cvbVal.at(i) = static_cast<double>(cvbElement);
349  }
350  valueOut = std::move(cvbVal);
351  }
352 
353 
354  void GetField(FieldID fieldId, std::vector<String>& valueOut) const
355  {
356  size_t sz = 0;
357  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetArraySize(handle_.Handle(),
358  static_cast<CExports::CVSField>(fieldId), sz));
359  std::vector<String> cvbVal(sz);
360 
361  for (CExports::cvbval_t i = 0; i < static_cast<CExports::cvbval_t>(sz); ++i)
362  {
363  size_t szString = 0;
364  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsStringArrayTyped(handle_.Handle(),
365  static_cast<CExports::CVSField>(fieldId), i, reinterpret_cast<char*>(NULL), szString));
366  std::vector<char> cvbElement(szString);
367  CVB_CALL_CAPI_CHECKED(CVSMetaDataGetAsStringArrayTyped(handle_.Handle(),
368  static_cast<CExports::CVSField>(fieldId), i, cvbElement.data(), szString));
369  std::string tmpStr(cvbElement.data());
370  cvbVal.at(i) = String(tmpStr.begin(), tmpStr.end());
371  }
372 
373  valueOut = std::move(cvbVal);
374  }
375 
376 
377  void WriteFieldTyped(FieldID fieldId, const int& value)
378  {
379  CVB_CALL_CAPI_CHECKED(CVSMetaDataSetAsInteger(handle_.Handle(),
380  static_cast<CExports::CVSField>(fieldId),
381  static_cast<CExports::cvbint64_t>(value)));
382  }
383 
384 
385  void WriteFieldTyped(FieldID fieldId, const double& value)
386  {
387  CVB_CALL_CAPI_CHECKED(CVSMetaDataSetAsFloat(handle_.Handle(),
388  static_cast<CExports::CVSField>(fieldId),
389  value));
390  }
391 
392 
393  void WriteFieldTyped(FieldID fieldId, const String& value)
394  {
395  CVB_CALL_CAPI_CHECKED(CVSMetaDataSetAsStringTyped(handle_.Handle(),
396  static_cast<CExports::CVSField>(fieldId),
397  value.c_str()));
398  }
399 
400 
401  void WriteFieldTyped(FieldID fieldId, const std::vector<int>& value)
402  {
403  CVB_CALL_CAPI_CHECKED(CVSMetaDataClearField(handle_.Handle(),
404  static_cast<CExports::CVSField>(fieldId)));
405  for (auto e : value)
406  CVB_CALL_CAPI_CHECKED(CVSMetaDataAddToIntegerArray(handle_.Handle(),
407  static_cast<CExports::CVSField>(fieldId),
408  static_cast<CExports::cvbint64_t>(e)));
409  }
410 
411 
412  void WriteFieldTyped(FieldID fieldId, const std::vector<double>& value)
413  {
414  CVB_CALL_CAPI_CHECKED(CVSMetaDataClearField(handle_.Handle(),
415  static_cast<CExports::CVSField>(fieldId)));
416  for (auto e : value)
417  CVB_CALL_CAPI_CHECKED(CVSMetaDataAddToFloatArray(handle_.Handle(),
418  static_cast<CExports::CVSField>(fieldId),
419  static_cast<double>(e)));
420  }
421 
422 
423  void WriteFieldTyped(FieldID fieldId, const std::vector<String>& value)
424  {
425  CVB_CALL_CAPI_CHECKED(CVSMetaDataClearField(handle_.Handle(),
426  static_cast<CExports::CVSField>(fieldId)));
427  for (auto e : value)
428  CVB_CALL_CAPI_CHECKED(CVSMetaDataAddToStringArrayTyped(handle_.Handle(),
429  static_cast<CExports::CVSField>(fieldId),
430  e.c_str()));
431  }
432 
433 
435 
440  CExports::CVSFieldType CFieldType(FieldID fieldId) const
441  {
442  return Internal::DoResCallValueOut<CExports::CVSFieldType>([&](CExports::CVSFieldType& val)
443  {
444  return CVB_CALL_CAPI(CVSMetaDataGetFieldType(handle_.Handle(),
445  static_cast<CExports::CVSField>(fieldId), val));
446  });
447  }
448 
449  private:
450 
451  HandleGuard<MetaData> handle_;
452 
453 
454  };
455  }
456 
457 using Spectral::MetaData;
458 
459 CVB_END_INLINE_NS
460 
461 }
462 
CubeEncoding InterleavedType() const
Convenience function to access the value of field FieldID::Interleave.
Definition: meta_data.hpp:205
CubeEncoding
View Perspective: Defines how the mapping between a typical x-y image and samples-lines-bands is done...
Definition: spectral.hpp:210
int Lines() const
Convenience function to access the value of field FieldID::Lines.
Definition: meta_data.hpp:183
The number of bands.
The number of lines.
The number of samples.
FieldID
FieldID enum class to access fields in the MetaData object.
Definition: spectral.hpp:120
Spectral MetaData object.
Definition: meta_data.hpp:32
FieldType
Data type of a field.
Definition: spectral.hpp:179
Array of wavelengths with the unit given in FieldID::WavelengthUnit.
STL class.
Root namespace for the Image Manager interface.
Definition: version.hpp:11
static std::unique_ptr< MetaData > Create()
Creates an empty metadata object.
Definition: meta_data.hpp:240
String FieldNameAsString(FieldID fieldId) const
Gets the field name as Cvb::String.
Definition: meta_data.hpp:92
Field contains string value.
static std::unique_ptr< MetaData > FromHandle(HandleGuard< MetaData > &&guard)
Creates metadata from a classic API handle.
Definition: meta_data.hpp:267
void ClearField(FieldID fieldId)
Clears the given field and sets the FieldType to FieldType::Invalid.
Definition: meta_data.hpp:139
void * Handle() const noexcept
Returns C-API style handle to the metadata.
Definition: meta_data.hpp:253
void WriteField(FieldID fieldId, const T &value)
Template function to set the value of a given field.
Definition: meta_data.hpp:79
STL class.
STL class.
Spectral::FieldType FieldType(FieldID fieldId) const
Gets the type of the given field.
Definition: meta_data.hpp:112
T ReadField(const FieldID &fieldId) const
Template function to get the value of the field.
Definition: meta_data.hpp:54
int Bands() const
Convenience function to access the value of field FieldID::Bands.
Definition: meta_data.hpp:194
Defines the way the spectral data of the buffer is ordered (CubeEncoding)
int Samples() const
Convenience function to access the value of field FieldID::Samples.
Definition: meta_data.hpp:172
std::vector< double > Wavelengths() const
Convenience function to access the value of field FieldID::Wavelength.
Definition: meta_data.hpp:228
bool IsFieldDefined(FieldID fieldId)
Checks if the given field is already defined.
Definition: meta_data.hpp:155
int NumberOfFields() const
Gets the total number of all fields.
Definition: meta_data.hpp:124