BsPixelData.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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 "Private/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. void PixelData::setColors(const Color& color)
  191. {
  192. UINT32 depth = mExtents.getDepth();
  193. UINT32 height = mExtents.getHeight();
  194. UINT32 width = mExtents.getWidth();
  195. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  196. UINT32 packedColor[4];
  197. assert(pixelSize <= sizeof(packedColor));
  198. PixelUtil::packColor(color, mFormat, packedColor);
  199. UINT8* data = getData();
  200. for (UINT32 z = 0; z < depth; z++)
  201. {
  202. UINT32 zDataIdx = z * mSlicePitch * pixelSize;
  203. for (UINT32 y = 0; y < height; y++)
  204. {
  205. UINT32 yDataIdx = y * mRowPitch * pixelSize;
  206. for (UINT32 x = 0; x < width; x++)
  207. {
  208. UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
  209. UINT8* dest = data + dataIdx;
  210. memcpy(dest, packedColor, pixelSize);
  211. }
  212. }
  213. }
  214. }
  215. float PixelData::getDepthAt(UINT32 x, UINT32 y, UINT32 z) const
  216. {
  217. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  218. UINT32 pixelOffset = pixelSize * (z * mSlicePitch + y * mRowPitch + x);
  219. return PixelUtil::unpackDepth(mFormat, (unsigned char *)getData() + pixelOffset);;
  220. }
  221. Vector<float> PixelData::getDepths() const
  222. {
  223. UINT32 depth = mExtents.getDepth();
  224. UINT32 height = mExtents.getHeight();
  225. UINT32 width = mExtents.getWidth();
  226. UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
  227. UINT8* data = getData();
  228. Vector<float> depths(width * height * depth);
  229. for (UINT32 z = 0; z < depth; z++)
  230. {
  231. UINT32 zArrayIdx = z * width * height;
  232. UINT32 zDataIdx = z * mSlicePitch * pixelSize;
  233. for (UINT32 y = 0; y < height; y++)
  234. {
  235. UINT32 yArrayIdx = y * width;
  236. UINT32 yDataIdx = y * mRowPitch * pixelSize;
  237. for (UINT32 x = 0; x < width; x++)
  238. {
  239. UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
  240. UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
  241. UINT8* dest = data + dataIdx;
  242. depths[arrayIdx] = PixelUtil::unpackDepth(mFormat, dest);
  243. }
  244. }
  245. }
  246. return depths;
  247. }
  248. SPtr<PixelData> PixelData::create(const PixelVolume &extents, PixelFormat pixelFormat)
  249. {
  250. SPtr<PixelData> pixelData = bs_shared_ptr_new<PixelData>(extents, pixelFormat);
  251. pixelData->allocateInternalBuffer();
  252. return pixelData;
  253. }
  254. SPtr<PixelData> PixelData::create(UINT32 width, UINT32 height, UINT32 depth, PixelFormat pixelFormat)
  255. {
  256. SPtr<PixelData> pixelData = bs_shared_ptr_new<PixelData>(width, height, depth, pixelFormat);
  257. pixelData->allocateInternalBuffer();
  258. return pixelData;
  259. }
  260. UINT32 PixelData::getInternalBufferSize() const
  261. {
  262. return getSize();
  263. }
  264. /************************************************************************/
  265. /* SERIALIZATION */
  266. /************************************************************************/
  267. RTTITypeBase* PixelData::getRTTIStatic()
  268. {
  269. return PixelDataRTTI::instance();
  270. }
  271. RTTITypeBase* PixelData::getRTTI() const
  272. {
  273. return PixelData::getRTTIStatic();
  274. }
  275. }