BsPixelData.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Image/BsPixelData.h"
  4. #include "Image/BsPixelUtil.h"
  5. #include "RTTI/BsPixelDataRTTI.h"
  6. #include "Image/BsColor.h"
  7. #include "Math/BsVector2.h"
  8. #include "Math/BsMath.h"
  9. #include "Debug/BsDebug.h"
  10. namespace bs
  11. {
  12. PixelData::PixelData()
  13. :mExtents(0, 0, 0, 0), mFormat(PF_UNKNOWN), mRowPitch(0), mSlicePitch(0)
  14. { }
  15. PixelData::PixelData(const PixelVolume& extents, PixelFormat pixelFormat)
  16. :mExtents(extents), mFormat(pixelFormat)
  17. {
  18. PixelUtil::getPitch(extents.getWidth(), extents.getHeight(), extents.getDepth(), pixelFormat, mRowPitch,
  19. mSlicePitch);
  20. }
  21. PixelData::PixelData(UINT32 width, UINT32 height, UINT32 depth, PixelFormat pixelFormat)
  22. : mExtents(0, 0, 0, width, height, depth), mFormat(pixelFormat)
  23. {
  24. PixelUtil::getPitch(width, height, depth, pixelFormat, mRowPitch, mSlicePitch);
  25. }
  26. PixelData::PixelData(const PixelData& copy)
  27. :GpuResourceData(copy)
  28. {
  29. mFormat = copy.mFormat;
  30. mRowPitch = copy.mRowPitch;
  31. mSlicePitch = copy.mSlicePitch;
  32. mExtents = copy.mExtents;
  33. }
  34. PixelData& PixelData::operator=(const PixelData& rhs)
  35. {
  36. GpuResourceData::operator= (rhs);
  37. mFormat = rhs.mFormat;
  38. mRowPitch = rhs.mRowPitch;
  39. mSlicePitch = rhs.mSlicePitch;
  40. mExtents = rhs.mExtents;
  41. return *this;
  42. }
  43. UINT32 PixelData::getConsecutiveSize() const
  44. {
  45. return PixelUtil::getMemorySize(getWidth(), getHeight(), getDepth(), mFormat);
  46. }
  47. UINT32 PixelData::getSize() const
  48. {
  49. return PixelUtil::getMemorySize(mRowPitch, mSlicePitch / mRowPitch, getDepth(), getFormat());
  50. }
  51. PixelData PixelData::getSubVolume(const PixelVolume& volume) const
  52. {
  53. if (PixelUtil::isCompressed(mFormat))
  54. {
  55. if (volume.left == getLeft() && volume.top == getTop() && volume.front == getFront() &&
  56. volume.right == getRight() && volume.bottom == getBottom() && volume.back == getBack())
  57. {
  58. // Entire buffer is being queried
  59. return *this;
  60. }
  61. BS_EXCEPT(InvalidParametersException, "Cannot return subvolume of compressed PixelBuffer");
  62. }
  63. if (!mExtents.contains(volume))
  64. {
  65. BS_EXCEPT(InvalidParametersException, "Bounds out of range");
  66. }
  67. const size_t elemSize = PixelUtil::getNumElemBytes(mFormat);
  68. PixelData rval(volume.getWidth(), volume.getHeight(), volume.getDepth(), mFormat);
  69. rval.setExternalBuffer(((UINT8*)getData()) + ((volume.left - getLeft())*elemSize)
  70. + ((volume.top - getTop())*mRowPitch*elemSize)
  71. + ((volume.front - getFront())*mSlicePitch*elemSize));
  72. rval.mFormat = mFormat;
  73. PixelUtil::getPitch(volume.getWidth(), volume.getHeight(), volume.getDepth(), mFormat, rval.mRowPitch,
  74. rval.mSlicePitch);
  75. return rval;
  76. }
  77. Color PixelData::sampleColorAt(const Vector2& coords, TextureFilter filter) const
  78. {
  79. Vector2 pixelCoords = coords * Vector2((float)mExtents.getWidth(), (float)mExtents.getHeight());
  80. INT32 maxExtentX = std::max(0, (INT32)mExtents.getWidth() - 1);
  81. INT32 maxExtentY = std::max(0, (INT32)mExtents.getHeight() - 1);
  82. if(filter == TF_BILINEAR)
  83. {
  84. pixelCoords -= Vector2(0.5f, 0.5f);
  85. UINT32 x = (UINT32)Math::clamp(Math::floorToInt(pixelCoords.x), 0, maxExtentX);
  86. UINT32 y = (UINT32)Math::clamp(Math::floorToInt(pixelCoords.y), 0, maxExtentY);
  87. float fracX = pixelCoords.x - x;
  88. float fracY = pixelCoords.y - y;
  89. x = Math::clamp(x, 0U, (UINT32)maxExtentX);
  90. y = Math::clamp(y, 0U, (UINT32)maxExtentY);
  91. INT32 x1 = Math::clamp(x + 1, 0U, (UINT32)maxExtentX);
  92. INT32 y1 = Math::clamp(y + 1, 0U, (UINT32)maxExtentY);
  93. Color color = Color::ZERO;
  94. color += (1.0f - fracX) * (1.0f - fracY) * getColorAt(x, y);
  95. color += fracX * (1.0f - fracY) * getColorAt(x1, y);
  96. color += (1.0f - fracX) * fracY * getColorAt(x, y1);
  97. color += fracX * fracY * getColorAt(x1, y1);
  98. return color;
  99. }
  100. else
  101. {
  102. UINT32 x = (UINT32)Math::clamp(Math::floorToInt(pixelCoords.x), 0, maxExtentX);
  103. UINT32 y = (UINT32)Math::clamp(Math::floorToInt(pixelCoords.y), 0, maxExtentY);
  104. return getColorAt(x, y);
  105. }
  106. }
  107. Color PixelData::getColorAt(UINT32 x, UINT32 y, UINT32 z) const
  108. {
  109. Color cv;
  110. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  111. UINT32 pixelOffset = pixelSize * (z * mSlicePitch + y * mRowPitch + x);
  112. PixelUtil::unpackColor(&cv, mFormat, (unsigned char *)getData() + pixelOffset);
  113. return cv;
  114. }
  115. void PixelData::setColorAt(const Color& color, UINT32 x, UINT32 y, UINT32 z)
  116. {
  117. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  118. UINT32 pixelOffset = pixelSize * (z * mSlicePitch + y * mRowPitch + x);
  119. PixelUtil::packColor(color, mFormat, (unsigned char *)getData() + pixelOffset);
  120. }
  121. Vector<Color> PixelData::getColors() const
  122. {
  123. UINT32 depth = mExtents.getDepth();
  124. UINT32 height = mExtents.getHeight();
  125. UINT32 width = mExtents.getWidth();
  126. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  127. UINT8* data = getData();
  128. Vector<Color> colors(width * height * depth);
  129. for (UINT32 z = 0; z < depth; z++)
  130. {
  131. UINT32 zArrayIdx = z * width * height;
  132. UINT32 zDataIdx = z * mSlicePitch * pixelSize;
  133. for (UINT32 y = 0; y < height; y++)
  134. {
  135. UINT32 yArrayIdx = y * width;
  136. UINT32 yDataIdx = y * mRowPitch * pixelSize;
  137. for (UINT32 x = 0; x < width; x++)
  138. {
  139. UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
  140. UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
  141. UINT8* dest = data + dataIdx;
  142. PixelUtil::unpackColor(&colors[arrayIdx], mFormat, dest);
  143. }
  144. }
  145. }
  146. return colors;
  147. }
  148. template<class T>
  149. void PixelData::setColorsInternal(const T& colors, UINT32 numElements)
  150. {
  151. UINT32 depth = mExtents.getDepth();
  152. UINT32 height = mExtents.getHeight();
  153. UINT32 width = mExtents.getWidth();
  154. UINT32 totalNumElements = width * height * depth;
  155. if (numElements != totalNumElements)
  156. {
  157. LOGERR("Unable to set colors, invalid array size.");
  158. return;
  159. }
  160. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  161. UINT8* data = getData();
  162. for (UINT32 z = 0; z < depth; z++)
  163. {
  164. UINT32 zArrayIdx = z * width * height;
  165. UINT32 zDataIdx = z * mSlicePitch * pixelSize;
  166. for (UINT32 y = 0; y < height; y++)
  167. {
  168. UINT32 yArrayIdx = y * width;
  169. UINT32 yDataIdx = y * mRowPitch * pixelSize;
  170. for (UINT32 x = 0; x < width; x++)
  171. {
  172. UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
  173. UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
  174. UINT8* dest = data + dataIdx;
  175. PixelUtil::packColor(colors[arrayIdx], mFormat, dest);
  176. }
  177. }
  178. }
  179. }
  180. template BS_CORE_EXPORT void PixelData::setColorsInternal(Color* const &, UINT32);
  181. template BS_CORE_EXPORT void PixelData::setColorsInternal(const Vector<Color>&, UINT32);
  182. void PixelData::setColors(const Vector<Color>& colors)
  183. {
  184. setColorsInternal(colors, (UINT32)colors.size());
  185. }
  186. void PixelData::setColors(Color* colors, UINT32 numElements)
  187. {
  188. setColorsInternal(colors, numElements);
  189. }
  190. float PixelData::getDepthAt(UINT32 x, UINT32 y, UINT32 z) const
  191. {
  192. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  193. UINT32 pixelOffset = pixelSize * (z * mSlicePitch + y * mRowPitch + x);
  194. return PixelUtil::unpackDepth(mFormat, (unsigned char *)getData() + pixelOffset);;
  195. }
  196. Vector<float> PixelData::getDepths() const
  197. {
  198. UINT32 depth = mExtents.getDepth();
  199. UINT32 height = mExtents.getHeight();
  200. UINT32 width = mExtents.getWidth();
  201. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  202. UINT8* data = getData();
  203. Vector<float> depths(width * height * depth);
  204. for (UINT32 z = 0; z < depth; z++)
  205. {
  206. UINT32 zArrayIdx = z * width * height;
  207. UINT32 zDataIdx = z * mSlicePitch * pixelSize;
  208. for (UINT32 y = 0; y < height; y++)
  209. {
  210. UINT32 yArrayIdx = y * width;
  211. UINT32 yDataIdx = y * mRowPitch * pixelSize;
  212. for (UINT32 x = 0; x < width; x++)
  213. {
  214. UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
  215. UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
  216. UINT8* dest = data + dataIdx;
  217. depths[arrayIdx] = PixelUtil::unpackDepth(mFormat, dest);
  218. }
  219. }
  220. }
  221. return depths;
  222. }
  223. SPtr<PixelData> PixelData::create(const PixelVolume &extents, PixelFormat pixelFormat)
  224. {
  225. SPtr<PixelData> pixelData = bs_shared_ptr_new<PixelData>(extents, pixelFormat);
  226. pixelData->allocateInternalBuffer();
  227. return pixelData;
  228. }
  229. SPtr<PixelData> PixelData::create(UINT32 width, UINT32 height, UINT32 depth, PixelFormat pixelFormat)
  230. {
  231. SPtr<PixelData> pixelData = bs_shared_ptr_new<PixelData>(width, height, depth, pixelFormat);
  232. pixelData->allocateInternalBuffer();
  233. return pixelData;
  234. }
  235. UINT32 PixelData::getInternalBufferSize() const
  236. {
  237. return getSize();
  238. }
  239. /************************************************************************/
  240. /* SERIALIZATION */
  241. /************************************************************************/
  242. RTTITypeBase* PixelData::getRTTIStatic()
  243. {
  244. return PixelDataRTTI::instance();
  245. }
  246. RTTITypeBase* PixelData::getRTTI() const
  247. {
  248. return PixelData::getRTTIStatic();
  249. }
  250. }