image.h
Go to the documentation of this file.
1 /*
2 * ECVL - European Computer Vision Library
3 * Version: 1.0.3
4 * copyright (c) 2021, Università degli Studi di Modena e Reggio Emilia (UNIMORE), AImageLab
5 * Authors:
6 * Costantino Grana (costantino.grana@unimore.it)
7 * Federico Bolelli (federico.bolelli@unimore.it)
8 * Michele Cancilla (michele.cancilla@unimore.it)
9 * Laura Canalini (laura.canalini@unimore.it)
10 * Stefano Allegretti (stefano.allegretti@unimore.it)
11 * All rights reserved.
12 */
13 
14 #ifndef ECVL_IMAGE_H_
15 #define ECVL_IMAGE_H_
16 
17 #include <algorithm>
18 #include <numeric>
19 #include <stdexcept>
20 #include <vector>
21 
22 #include <opencv2/core.hpp>
23 
24 #include "datatype.h"
25 #include "hal.h"
26 #include "iterators.h"
27 #include "datatype_matrix.h"
28 #include "metadata.h"
29 #include "type_promotion.h"
30 #include "standard_errors.h"
31 
32 namespace ecvl
33 {
34 template<typename T>
35 int vsize(const std::vector<T>& v)
36 {
37  return static_cast<int>(v.size());
38 }
39 
44 enum class ColorType
45 {
46  none,
47  GRAY,
48  RGB,
49  RGBA,
50  BGR,
51  HSV,
52  YCbCr,
53 };
54 
55 class Image;
56 
57 template <DataType DT>
58 class View;
59 
60 template <DataType DT>
61 class ConstView;
62 
66 class Image
67 {
68 protected:
80  {
81  // Compute strides
82  strides_ = { elemsize_ };
83  int dsize = vsize(dims_);
84  for (int i = 0; i < dsize - 1; ++i) {
85  strides_.push_back(strides_[i] * dims_[i]);
86  }
87  }
88 
96  {
97  return std::accumulate(std::begin(dims_), std::end(dims_), size_t(elemsize_), std::multiplies<size_t>());
98  }
99 
107  {
109  }
110 
112 
113 public:
116  uint8_t elemsize_;
117  std::vector<int> dims_;
119  std::vector<int> strides_;
124  std::string channels_;
157  std::vector<float> spacings_;
162  uint8_t* data_;
169  size_t datasize_;
170  bool contiguous_;
172  std::unordered_map<std::string, MetaData> meta_;
181  Device dev_;
192  template<typename T>
193  Iterator<T> Begin() { return Iterator<T>(*this); }
194 
200  template<typename T>
201  Iterator<T> End() { return Iterator<T>(*this, dims_); }
202 
209  template<typename T>
210  ConstIterator<T> Begin() const { return ConstIterator<T>(*this); }
211 
217  template<typename T>
218  ConstIterator<T> End() const { return ConstIterator<T>(*this, dims_); }
219 
226  template<typename T>
228 
234  template<typename T>
236 
243  template<typename T>
245 
250  template<typename T>
252 
257  Image() :
260  dims_{},
261  spacings_{},
262  strides_{},
263  channels_{},
265  data_{ nullptr },
266  datasize_{ 0 },
267  contiguous_{ true },
268  meta_{},
269  hal_{ nullptr },
270  dev_{ Device::NONE }
271  {
272  }
273 
278  Image(const std::vector<int>& dims, DataType elemtype, std::string channels, ColorType colortype,
279  const std::vector<float>& spacings = std::vector<float>(), Device dev = Device::CPU, const std::unordered_map<std::string, MetaData>& meta = {}) :
280  elemtype_{ elemtype },
282  dims_{ dims },
283  spacings_{ spacings },
284  strides_{},
285  channels_{ move(channels) },
286  colortype_{ colortype },
287  data_{ nullptr },
288  datasize_{ 0 },
289  contiguous_{ true },
290  meta_{ meta },
291  hal_{ HardwareAbstractionLayer::Factory(dev) },
292  dev_{ dev }
293  {
294  if (dims_.size() != channels_.size()) {
295  throw std::runtime_error("Number of dimensions must match number of channels.");
296  }
297  hal_->Create(*this);
298  }
299 
306  Image(const Image& img) :
307  elemtype_{ img.elemtype_ },
308  elemsize_{ img.elemsize_ },
309  dims_{ img.dims_ },
310  spacings_{ img.spacings_ },
311  strides_{ img.strides_ },
312  channels_{ img.channels_ },
313  colortype_{ img.colortype_ },
314  data_{},
315  datasize_{ img.datasize_ },
316  contiguous_{ img.contiguous_ },
317  meta_{ img.meta_ },
318  hal_{ img.hal_ },
319  dev_{ img.dev_ }
320  {
321  hal_->Copy(img, *this);
322  }
323 
328  Image(Image&& img)
329  {
330  elemtype_ = img.elemtype_;
331  elemsize_ = img.elemsize_;
332  dims_ = img.dims_;
333  spacings_ = img.spacings_;
334  strides_ = img.strides_;
335  channels_ = img.channels_;
336  colortype_ = img.colortype_;
337  data_ = img.data_;
338  datasize_ = img.datasize_;
339  contiguous_ = img.contiguous_;
340  meta_ = img.meta_;
341  hal_ = img.hal_;
342  dev_ = img.dev_;
343  img.hal_ = nullptr; // This disables destruction of rhs.data_
344  }
345 
346  friend void swap(Image& lhs, Image& rhs)
347  {
348  using std::swap;
349  swap(lhs.elemtype_, rhs.elemtype_);
350  swap(lhs.elemsize_, rhs.elemsize_);
351  swap(lhs.dims_, rhs.dims_);
352  swap(lhs.spacings_, rhs.spacings_);
353  swap(lhs.strides_, rhs.strides_);
354  swap(lhs.channels_, rhs.channels_);
355  swap(lhs.colortype_, rhs.colortype_);
356  swap(lhs.data_, rhs.data_);
357  swap(lhs.datasize_, rhs.datasize_);
358  swap(lhs.contiguous_, rhs.contiguous_);
359  swap(lhs.meta_, rhs.meta_);
360  swap(lhs.hal_, rhs.hal_);
361  swap(lhs.dev_, rhs.dev_);
362  }
363 
364  Image& operator=(const Image& rhs)
365  {
366  // Self-assignment detection
367  if (this != &rhs) {
368  Image tmp = rhs; // Copy and swap because I'm lazy, but still want super cheap self assignment
369  swap(*this, tmp);
370  }
371  return *this;
372  }
373 
375  {
376  assert(this != &rhs);
377  elemtype_ = rhs.elemtype_;
378  elemsize_ = rhs.elemsize_;
379  dims_ = rhs.dims_;
380  spacings_ = rhs.spacings_;
381  strides_ = rhs.strides_;
382  channels_ = rhs.channels_;
383  colortype_ = rhs.colortype_;
384  // Release any resource we are holding
385  if (hal_) {
386  hal_->MemDeallocate(data_);
387  }
388  data_ = rhs.data_;
389  datasize_ = rhs.datasize_;
390  contiguous_ = rhs.contiguous_;
391  meta_ = rhs.meta_;
392  hal_ = rhs.hal_;
393  dev_ = rhs.dev_;
394  rhs.hal_ = nullptr; // This disables destruction of rhs.data_
395  return *this;
396  }
397 
398  void To(Device dev)
399  {
400  if (dev_ == dev) {
401  return;
402  }
403  if (dev_ == Device::NONE || dev == Device::NONE) {
404  throw std::runtime_error(ECVL_ERROR_MSG "Source or dest device is NONE");
405  }
406 
407  if (dev_ == Device::CPU) { // Move from CPU to other device
408  auto dst_hal_ = HardwareAbstractionLayer::Factory(dev);
409  dst_hal_->FromCpu(*this);
410  }
411  else if (dev == Device::CPU) { // Move from other device to CPU
412  hal_->ToCpu(*this);
413  }
414  else {
415  throw std::runtime_error(ECVL_ERROR_MSG "Source or dest device must be CPU");
416  }
417  }
418 
434  void Create(const std::vector<int>& dims, DataType elemtype, std::string channels, ColorType colortype,
435  const std::vector<float>& spacings = std::vector<float>(), Device dev = Device::CPU, const std::unordered_map<std::string, MetaData>& meta = {});
436 
442  {
443  if (hal_) {
444  hal_->MemDeallocate(data_);
445  }
446  }
447 
449  bool IsEmpty() const { return data_ == nullptr; }
450 
456  bool IsOwner() const { return hal_->IsOwner(); }
457 
459  int Channels() const
460  {
461  size_t c = channels_.find('c');
462  if (c != std::string::npos) {
463  return dims_[c];
464  }
465  c = channels_.find('z');
466  if (c != std::string::npos) {
467  return dims_[c];
468  }
469  c = channels_.find('o');
470  if (c != std::string::npos) {
471  return dims_[c];
472  }
473  return 0;
474  }
475 
477  int Width() const
478  {
479  size_t x = channels_.find('x');
480  if (x != std::string::npos) {
481  return dims_[x];
482  }
483  return 0;
484  }
485 
487  int Height() const
488  {
489  size_t y = channels_.find('y');
490  if (y != std::string::npos) {
491  return dims_[y];
492  }
493  return 0;
494  }
495 
497  uint8_t* Ptr(const std::vector<int>& coords)
498  {
499  assert(coords.size() == strides_.size());
500  return std::inner_product(std::begin(coords), std::end(coords), std::begin(strides_), data_);
501  }
503  const uint8_t* Ptr(const std::vector<int>& coords) const
504  {
505  assert(coords.size() == strides_.size());
506  return std::inner_product(std::begin(coords), std::end(coords), std::begin(strides_), data_);
507  }
508 
510  void Neg()
511  {
512  hal_->Neg(*this, *this, elemtype_, false);
513  }
514 
516  template<typename T>
517  void Add(const T& rhs, bool saturate = true)
518  {
519  hal_->Add(*this, rhs, *this, elemtype_, saturate);
520  }
521 
523  template<typename T>
524  void Sub(const T& rhs, bool saturate = true)
525  {
526  hal_->Sub(*this, rhs, *this, elemtype_, saturate);
527  }
528 
530  template<typename T>
531  void Mul(const T& rhs, bool saturate = true)
532  {
533  hal_->Mul(*this, rhs, *this, elemtype_, saturate);
534  }
535 
537  template<typename T>
538  void Div(const T& rhs, bool saturate = true)
539  {
540  hal_->Div(*this, rhs, *this, elemtype_, saturate);
541  }
542 
544  template<typename T>
545  void SetTo(T value)
546  {
547  hal_->SetTo(*this, value);
548  }
549 
551  void ConvertTo(DataType dtype, bool saturate = true)
552  {
553  hal_->ConvertTo(*this, *this, dtype, saturate);
554  }
555 
557  MetaData GetMeta(const std::string& key) const
558  {
559  return this->meta_.at(key);
560  }
561 
563  bool SetMeta(const std::string& key, const std::any& value)
564  {
565  return this->meta_.insert_or_assign(key, MetaData(value, 0)).second;
566  }
567 
568  Image operator-() const;
569 
570  Image& operator+=(const Image& rhs);
571 
572  Image& operator-=(const Image& rhs);
573 
574  Image& operator*=(const Image& rhs);
575 
576  Image& operator/=(const Image& rhs);
577 
578  friend Image operator+(Image lhs, const Image& rhs);
579 
580  friend Image operator-(Image lhs, const Image& rhs);
581 
582  friend Image operator*(Image lhs, const Image& rhs);
583 
584  friend Image operator/(Image lhs, const Image& rhs);
585 };
586 
587 template <typename ViewType>
588 static void CropViewInternal(ViewType& view, const std::vector<int>& start, const std::vector<int>& size)
589 {
590  std::vector<int> new_dims;
591  int ssize = vsize(size);
592  for (int i = 0; i < ssize; ++i) {
593  if (start[i] < 0 || start[i] >= view.dims_[i])
594  throw std::runtime_error("Start of crop outside image limits");
595  new_dims.push_back(view.dims_[i] - start[i]);
596  if (size[i] > new_dims[i]) {
597  throw std::runtime_error("Crop outside image limits");
598  }
599  if (size[i] >= 0) {
600  new_dims[i] = size[i];
601  }
602  }
603 
604  // Check if image has a color dimension
605  auto cpos = view.channels_.find('c');
606  if (cpos != std::string::npos) {
607  // If we are cropping the color channel, we fix the color information
608  if (new_dims[cpos] != view.dims_[cpos]) {
609  if (new_dims[cpos] == 1) {
610  view.colortype_ = ColorType::GRAY;
611  }
612  else {
613  view.channels_[cpos] = 'o';
614  view.colortype_ = ColorType::none;
615  }
616  }
617  }
618 
619  view.data_ = view.Ptr(start);
620 
621  if (view.contiguous_) {
622  for (int i = 0; i < view.dims_.size() - 1; ++i) {
623  if (new_dims[i] != view.dims_[i]) {
624  view.contiguous_ = false;
625  }
626  }
627  }
628  if (view.contiguous_) {
629  view.datasize_ = std::accumulate(std::begin(new_dims), std::end(new_dims), size_t(view.elemsize_), std::multiplies<size_t>());
630  }
631  else {
632  view.datasize_ = 0; // This is set to zero, because when the View is not contiguous, it's useless to relay on this information
633  }
634 
635  view.dims_ = std::move(new_dims);
636 }
637 
638 #include "iterators_impl.inc.h"
639 template <DataType DT>
640 class View : public Image
641 {
642 public:
644 
645  View() {}
646 
647  View(Image& img)
648  {
649  if (DT != img.elemtype_)
650  throw std::runtime_error("View type is different from Image type");
651  elemtype_ = img.elemtype_;
652  elemsize_ = img.elemsize_;
653  dims_ = img.dims_;
654  spacings_ = img.spacings_;
655  strides_ = img.strides_;
656  channels_ = img.channels_;
657  colortype_ = img.colortype_;
658  data_ = img.data_;
659  datasize_ = img.datasize_;
660  contiguous_ = img.contiguous_;
661  meta_ = img.meta_;
662  hal_ = HardwareAbstractionLayer::Factory(img.dev_, true);
663  dev_ = img.dev_;
664  }
665 
666  View(Image& img, const std::vector<int>& start, const std::vector<int>& size) : View(img)
667  {
668  CropViewInternal(*this, start, size);
669  }
670 
671  basetype& operator()(const std::vector<int>& coords)
672  {
673  return *reinterpret_cast<basetype*>(Ptr(coords));
674  }
675 
676  void Create(std::vector<int> dims, std::string channels, ColorType colortype, uint8_t* ptr,
677  const std::vector<float>& spacings = std::vector<float>(), Device dev = Device::CPU, const std::unordered_map<std::string, MetaData>& meta = {})
678  {
679  elemtype_ = DT;
681  dims_ = std::move(dims);
682  spacings_ = spacings;
683  channels_ = std::move(channels);
684  colortype_ = colortype;
685 
688 
689  data_ = ptr;
690  hal_ = HardwareAbstractionLayer::Factory(dev, true);
691  dev_ = dev;
692  meta_ = meta;
693  return;
694  }
695 
698 };
699 
700 template <DataType DT>
701 class ConstView : public Image
702 {
703 public:
705 
707 
708  ConstView(const Image& img)
709  {
710  elemtype_ = img.elemtype_;
711  elemsize_ = img.elemsize_;
712  dims_ = img.dims_;
713  spacings_ = img.spacings_;
714  strides_ = img.strides_;
715  channels_ = img.channels_;
716  colortype_ = img.colortype_;
717  data_ = img.data_;
718  datasize_ = img.datasize_;
719  contiguous_ = img.contiguous_;
720  meta_ = img.meta_;
721  hal_ = HardwareAbstractionLayer::Factory(img.dev_, true);
722  dev_ = img.dev_;
723  }
724 
725  ConstView(const Image& img, const std::vector<int>& start, const std::vector<int>& size) : ConstView(img)
726  {
727  CropViewInternal(*this, start, size);
728  }
729 
730  const basetype& operator()(const std::vector<int>& coords)
731  {
732  return *reinterpret_cast<const basetype*>(Ptr(coords));
733  }
734 
737 };
738 
739 template <DataType DT>
740 class ContiguousView : public Image
741 {
742 public:
744 
746 
748  {
749  elemtype_ = img.elemtype_;
750  elemsize_ = img.elemsize_;
751  dims_ = img.dims_;
752  spacings_ = img.spacings_;
753  strides_ = img.strides_;
754  channels_ = img.channels_;
755  colortype_ = img.colortype_;
756  data_ = img.data_;
757  datasize_ = img.datasize_;
758  contiguous_ = img.contiguous_;
759  meta_ = img.meta_;
760  hal_ = HardwareAbstractionLayer::Factory(img.dev_, true);
761  dev_ = img.dev_;
762  }
763 
764  basetype& operator()(const std::vector<int>& coords)
765  {
766  return *reinterpret_cast<basetype*>(Ptr(coords));
767  }
768 
771 };
772 
773 template <DataType DT>
775 {
776 public:
778 
780 
782  {
783  elemtype_ = img.elemtype_;
784  elemsize_ = img.elemsize_;
785  dims_ = img.dims_;
786  spacings_ = img.spacings_;
787  strides_ = img.strides_;
788  channels_ = img.channels_;
789  colortype_ = img.colortype_;
790  data_ = img.data_;
791  datasize_ = img.datasize_;
792  contiguous_ = img.contiguous_;
793  meta_ = img.meta_;
794  hal_ = HardwareAbstractionLayer::Factory(img.dev_, true);
795  dev_ = img.dev_;
796  }
797 
798  const basetype& operator()(const std::vector<int>& coords)
799  {
800  return *reinterpret_cast<const basetype*>(Ptr(coords));
801  }
802 
805 };
806 
807 template <DataType DT>
808 class ContiguousViewXYC : public Image
809 {
810 public:
812 
814  {
815  if (img.channels_ != "xyc")
816  throw std::runtime_error("ContiguousView2D can be built only from \"xyc\" images");
817  if (!img.contiguous_)
818  throw std::runtime_error("ContiguousView2D can be built only from images with contiguous data");
819  elemtype_ = img.elemtype_;
820  elemsize_ = img.elemsize_;
821  dims_ = img.dims_;
822  spacings_ = img.spacings_;
823  strides_ = img.strides_;
824  channels_ = img.channels_;
825  colortype_ = img.colortype_;
826  data_ = img.data_;
827  datasize_ = img.datasize_;
828  contiguous_ = img.contiguous_;
829  meta_ = img.meta_;
830  hal_ = HardwareAbstractionLayer::Factory(img.dev_, true);
831  dev_ = img.dev_;
832  }
833 
834  int width() const { return dims_[0]; }
835  int height() const { return dims_[1]; }
836  int channels() const { return dims_[2]; }
837 
838  basetype& operator()(int x, int y, int c)
839  {
840  return *reinterpret_cast<basetype*>(data_ + c * strides_[2] + y * strides_[1] + x * strides_[0]);
841  }
842 
845 };
846 
847 template <DataType DT>
849 {
850 public:
852 
854  {
855  if (img.channels_ != "xyc")
856  throw std::runtime_error("ContiguousView2D can be built only from \"xyc\" images");
857  if (!img.contiguous_)
858  throw std::runtime_error("ContiguousView2D can be built only from images with contiguous data");
859  elemtype_ = img.elemtype_;
860  elemsize_ = img.elemsize_;
861  dims_ = img.dims_;
862  spacings_ = img.spacings_;
863  strides_ = img.strides_;
864  channels_ = img.channels_;
865  colortype_ = img.colortype_;
866  data_ = img.data_;
867  datasize_ = img.datasize_;
868  contiguous_ = img.contiguous_;
869  meta_ = img.meta_;
870  hal_ = HardwareAbstractionLayer::Factory(img.dev_, true);
871  dev_ = img.dev_;
872  }
873 
874  int width() const { return dims_[0]; }
875  int height() const { return dims_[1]; }
876  int channels() const { return dims_[2]; }
877 
878  const basetype& operator()(int x, int y, int c) const
879  {
880  return *reinterpret_cast<basetype*>(data_ + c * strides_[2] + y * strides_[1] + x * strides_[0]);
881  }
882 
885 };
886 
900 void RearrangeChannels(const Image& src, Image& dst, const std::string& channels);
901 
912 void RearrangeChannels(const Image& src, Image& dst, const std::string& channels, DataType new_type);
913 
949 void CopyImage(const Image& src, Image& dst, DataType new_type = DataType::none);
950 
960 void CopyImage(const Image& src, Image& dst, DataType new_type, const std::string& channels);
961 
975 void ShallowCopyImage(const Image& src, Image& dst);
976 
986 void ConvertTo(const Image& src, Image& dst, DataType dtype, bool saturate = true);
987 
988 
992 } // namespace ecvl
993 
994 #endif // !ECVL_IMAGE_H_
ContiguousIterator< basetype > End()
Definition: image.h:844
Image class.
Definition: image.h:66
ConstContiguousIterator< T > ContiguousEnd() const
Contiguous const End Iterator.
Definition: image.h:251
ContiguousIterator< basetype > Begin()
Definition: image.h:769
Image & operator/=(const Image &rhs)
ConstContiguousView(const Image &img)
Definition: image.h:781
typename TypeInfo< DT >::basetype basetype
Definition: image.h:643
int Width() const
Returns the width of Image.
Definition: image.h:477
uint8_t * data_
Pointer to Image data.
Definition: image.h:162
void Neg()
In-place negation.
Definition: image.h:510
ConstView(const Image &img, const std::vector< int > &start, const std::vector< int > &size)
Definition: image.h:725
basetype & operator()(const std::vector< int > &coords)
Definition: image.h:671
HardwareAbstractionLayer * hal_
Pointer to the HardwareAbstractionLayer employed by the Image.
Definition: image.h:173
basetype & operator()(int x, int y, int c)
Definition: image.h:838
std::string channels_
String which describes how Image planes are organized.
Definition: image.h:124
size_t datasize_
Size of Image data in bytes.
Definition: image.h:169
Image & operator *=(const Image &rhs)
const basetype & operator()(const std::vector< int > &coords)
Definition: image.h:730
friend Image operator+(Image lhs, const Image &rhs)
ContiguousViewXYC(Image &img)
Definition: image.h:813
int vsize(const std::vector< T > &v)
Definition: image.h:35
void SetDefaultStrides()
Sets default strides for contiguous memory layouts.
Definition: image.h:79
typename TypeInfo< DT >::basetype basetype
Definition: image.h:811
const basetype & operator()(const std::vector< int > &coords)
Definition: image.h:798
DataType
DataType is an enum class which defines data types allowed for images.
Definition: datatype.h:43
DataType elemtype_
Type of Image pixels, must be one of the values available in DataType.
Definition: image.h:114
ColorType
Enum class representing the ECVL supported color spaces.
Definition: image.h:44
basetype & operator()(const std::vector< int > &coords)
Definition: image.h:764
ColorType colortype_
Image ColorType.
Definition: image.h:147
ConstContiguousIterator< T > ContiguousBegin() const
Contiguous const Begin Iterator.
Definition: image.h:244
Image & operator=(const Image &rhs)
Definition: image.h:364
View(Image &img)
Definition: image.h:647
ContiguousView(Image &img)
Definition: image.h:747
Iterator< basetype > End()
Definition: image.h:697
size_t GetDefaultDatasize()
Gets the default datasize for contiguous images.
Definition: image.h:95
int Height() const
Returns the height of Image.
Definition: image.h:487
ContiguousIterator< basetype > Begin()
Definition: image.h:843
std::vector< int > strides_
Vector of Image strides.
Definition: image.h:119
uint8_t * Ptr(const std::vector< int > &coords)
Returns a non-const pointer to data at given coordinates.
Definition: image.h:497
void Create(std::vector< int > dims, std::string channels, ColorType colortype, uint8_t *ptr, const std::vector< float > &spacings=std::vector< float >(), Device dev=Device::CPU, const std::unordered_map< std::string, MetaData > &meta={})
Definition: image.h:676
Image & operator+=(const Image &rhs)
ConstContiguousViewXYC(const Image &img)
Definition: image.h:853
Image & operator=(Image &&rhs)
Definition: image.h:374
uint8_t elemsize_
Size (in bytes) of Image pixels.
Definition: image.h:116
ContiguousIterator< T > ContiguousBegin()
Contiguous non-const Begin Iterator.
Definition: image.h:227
ConstContiguousIterator< basetype > End()
Definition: image.h:804
void Create(const std::vector< int > &dims, DataType elemtype, std::string channels, ColorType colortype, const std::vector< float > &spacings=std::vector< float >(), Device dev=Device::CPU, const std::unordered_map< std::string, MetaData > &meta={})
Allocates new contiguous data if needed.
Image(const Image &img)
Copy constructor.
Definition: image.h:306
ConstContiguousIterator< basetype > End()
Definition: image.h:884
void ConvertTo(DataType dtype, bool saturate=true)
Convert Image to another DataType.
Definition: image.h:551
View(Image &img, const std::vector< int > &start, const std::vector< int > &size)
Definition: image.h:666
Definition: any.h:69
void SetTo(T value)
Set Image value to rhs.
Definition: image.h:545
bool contiguous_
Whether the image is stored contiguously or not in memory.
Definition: image.h:170
std::unordered_map< std::string, MetaData > meta_
Pointer to Image MetaData.
Definition: image.h:172
void ShallowCopyImage(const Image &src, Image &dst)
Performs a shallow copy of the source Image into the destination.
typename TypeInfo< DT >::basetype basetype
Definition: image.h:777
int channels() const
Definition: image.h:836
int height() const
Definition: image.h:835
void basetype
Definition: datatype.h:61
ConstView(const Image &img)
Definition: image.h:708
friend void swap(Image &lhs, Image &rhs)
Definition: image.h:346
ConstContiguousIterator< basetype > Begin()
Definition: image.h:803
bool IsOwner() const
To check whether the Image is owner of the data.
Definition: image.h:456
std::vector< int > dims_
Definition: image.h:117
void Div(const T &rhs, bool saturate=true)
In-place division.
Definition: image.h:538
friend Image operator *(Image lhs, const Image &rhs)
#define ECVL_ERROR_MSG
void RearrangeChannels(const Image &src, Image &dst, const std::string &channels)
Changes the order of the Image dimensions.
ConstContiguousIterator< basetype > Begin()
Definition: image.h:883
Iterator< T > Begin()
Generic non-const Begin Iterator.
Definition: image.h:193
ContiguousIterator< T > ContiguousEnd()
Contiguous non-const End Iterator.
Definition: image.h:235
void Mul(const T &rhs, bool saturate=true)
In-place multiplication.
Definition: image.h:531
friend class HardwareAbstractionLayer
Definition: image.h:111
ContiguousIterator< basetype > End()
Definition: image.h:770
typename TypeInfo< DT >::basetype basetype
Definition: image.h:743
bool SetMeta(const std::string &key, const std::any &value)
Update the metadata value if the key already exists (return false) or insert the pair if not found (r...
Definition: image.h:563
friend Image operator/(Image lhs, const Image &rhs)
std::experimental::any any
Definition: any.h:71
Image(const std::vector< int > &dims, DataType elemtype, std::string channels, ColorType colortype, const std::vector< float > &spacings=std::vector< float >(), Device dev=Device::CPU, const std::unordered_map< std::string, MetaData > &meta={})
Initializing constructor.
Definition: image.h:278
const basetype & operator()(int x, int y, int c) const
Definition: image.h:878
Image()
Default constructor.
Definition: image.h:257
const uint8_t * Ptr(const std::vector< int > &coords) const
Returns a const pointer to data at given coordinates.
Definition: image.h:503
int width() const
Definition: image.h:834
Device dev_
Identifier for the device on which the image data is.
Definition: image.h:181
Image(Image &&img)
Move constructor.
Definition: image.h:328
bool IsEmpty() const
To check whether the Image contains data or not, regardless of the owning status.
Definition: image.h:449
void ConvertTo(const Image &src, Image &dst, DataType dtype, bool saturate=true)
Convert Image to another DataType.
void To(Device dev)
Definition: image.h:398
typename TypeInfo< DT >::basetype basetype
Definition: image.h:851
void CopyImage(const Image &src, Image &dst, DataType new_type=DataType::none)
Copies the source Image into the destination Image.
MetaData GetMeta(const std::string &key) const
Return the metadata identified by key.
Definition: image.h:557
int Channels() const
Returns the number of channels.
Definition: image.h:459
ConstIterator< basetype > End()
Definition: image.h:736
uint8_t DataTypeSize(DataType dt)
Provides the size in bytes of a given DataType.
Iterator< basetype > Begin()
Definition: image.h:696
Image operator-() const
void SetDefaultDatasize()
Sets the default datasize for contiguous images.
Definition: image.h:106
typename TypeInfo< DT >::basetype basetype
Definition: image.h:704
ConstIterator< T > Begin() const
Generic const Begin Iterator.
Definition: image.h:210
ConstIterator< T > End() const
Generic const End Iterator.
Definition: image.h:218
void Sub(const T &rhs, bool saturate=true)
In-place subtraction.
Definition: image.h:524
~Image()
Destructor.
Definition: image.h:441
void Add(const T &rhs, bool saturate=true)
In-place addition.
Definition: image.h:517
View()
Definition: image.h:645
ConstIterator< basetype > Begin()
Definition: image.h:735
Iterator< T > End()
Generic non-const End Iterator.
Definition: image.h:201
Image & operator-=(const Image &rhs)
std::vector< float > spacings_
Space between pixels/voxels.
Definition: image.h:157