ImageData.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #pragma once
  2. // STL includes
  3. #include <vector>
  4. #include <cstdint>
  5. #include <cstring>
  6. #include <algorithm>
  7. #include <cassert>
  8. #include <type_traits>
  9. #include <utils/ColorRgb.h>
  10. // QT includes
  11. #include <QSharedData>
  12. // https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types#ssize-t
  13. #if defined(_MSC_VER)
  14. #include <BaseTsd.h>
  15. typedef SSIZE_T ssize_t;
  16. #endif
  17. template <typename Pixel_T>
  18. class ImageData : public QSharedData
  19. {
  20. public:
  21. typedef Pixel_T pixel_type;
  22. ImageData(unsigned width, unsigned height, const Pixel_T background) :
  23. _width(width),
  24. _height(height),
  25. _pixels(new Pixel_T[width * height + 1])
  26. {
  27. std::fill(_pixels, _pixels + width * height, background);
  28. }
  29. ImageData(const ImageData & other) :
  30. QSharedData(other),
  31. _width(other._width),
  32. _height(other._height),
  33. _pixels(new Pixel_T[other._width * other._height + 1])
  34. {
  35. memcpy(_pixels, other._pixels, static_cast<ulong>(other._width) * static_cast<ulong>(other._height) * sizeof(Pixel_T));
  36. }
  37. ImageData& operator=(ImageData rhs)
  38. {
  39. rhs.swap(*this);
  40. return *this;
  41. }
  42. void swap(ImageData& s) noexcept
  43. {
  44. using std::swap;
  45. swap(this->_width, s._width);
  46. swap(this->_height, s._height);
  47. swap(this->_pixels, s._pixels);
  48. }
  49. ImageData(ImageData&& src) noexcept
  50. : _width(0)
  51. , _height(0)
  52. , _pixels(NULL)
  53. {
  54. src.swap(*this);
  55. }
  56. ImageData& operator=(ImageData&& src) noexcept
  57. {
  58. src.swap(*this);
  59. return *this;
  60. }
  61. ~ImageData()
  62. {
  63. delete[] _pixels;
  64. }
  65. inline unsigned width() const
  66. {
  67. return _width;
  68. }
  69. inline unsigned height() const
  70. {
  71. return _height;
  72. }
  73. uint8_t red(unsigned pixel) const
  74. {
  75. return (_pixels + pixel)->red;
  76. }
  77. uint8_t green(unsigned pixel) const
  78. {
  79. return (_pixels + pixel)->green;
  80. }
  81. uint8_t blue(unsigned pixel) const
  82. {
  83. return (_pixels + pixel)->blue;
  84. }
  85. const Pixel_T& operator()(unsigned x, unsigned y) const
  86. {
  87. return _pixels[toIndex(x,y)];
  88. }
  89. Pixel_T& operator()(unsigned x, unsigned y)
  90. {
  91. return _pixels[toIndex(x,y)];
  92. }
  93. void resize(unsigned width, unsigned height)
  94. {
  95. if (width == _width && height == _height)
  96. return;
  97. if ((width * height) > unsigned((_width * _height)))
  98. {
  99. delete[] _pixels;
  100. _pixels = new Pixel_T[width*height + 1];
  101. }
  102. _width = width;
  103. _height = height;
  104. }
  105. Pixel_T* memptr()
  106. {
  107. return _pixels;
  108. }
  109. const Pixel_T* memptr() const
  110. {
  111. return _pixels;
  112. }
  113. void toRgb(ImageData<ColorRgb>& image) const
  114. {
  115. if (image.width() != _width || image.height() != _height)
  116. image.resize(_width, _height);
  117. const unsigned imageSize = _width * _height;
  118. for (unsigned idx = 0; idx < imageSize; idx++)
  119. {
  120. const Pixel_T & color = _pixels[idx];
  121. image.memptr()[idx] = ColorRgb{color.red, color.green, color.blue};
  122. }
  123. }
  124. ssize_t size() const
  125. {
  126. return static_cast<ssize_t>(_width) * static_cast<ssize_t>(_height) * sizeof(Pixel_T);
  127. }
  128. void clear()
  129. {
  130. if (_width != 1 || _height != 1)
  131. {
  132. _width = 1;
  133. _height = 1;
  134. delete[] _pixels;
  135. _pixels = new Pixel_T[2];
  136. }
  137. memset(_pixels, 0, static_cast<unsigned long>(_width) * static_cast<unsigned long>(_height) * sizeof(Pixel_T));
  138. }
  139. private:
  140. inline unsigned toIndex(unsigned x, unsigned y) const
  141. {
  142. return y * _width + x;
  143. }
  144. private:
  145. /// The width of the image
  146. unsigned _width;
  147. /// The height of the image
  148. unsigned _height;
  149. /// The pixels of the image
  150. Pixel_T* _pixels;
  151. };