2
0

PixelData.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System;
  4. using System.Runtime.CompilerServices;
  5. using System.Runtime.InteropServices;
  6. namespace BansheeEngine
  7. {
  8. /** @addtogroup Utility
  9. * @{
  10. */
  11. /// <summary>
  12. /// Pixel formats usable by images, textures and render surfaces.
  13. /// </summary>
  14. public enum PixelFormat // Note: Must match C++ enum PixelFormat
  15. {
  16. /// <summary>
  17. /// 8-bit pixel format, all bits red.
  18. /// </summary>
  19. R8 = 1,
  20. /// <summary>
  21. /// 2 byte pixel format, 1 byte red, 1 byte green.
  22. /// </summary>
  23. R8G8 = 2,
  24. /// <summary>
  25. /// 24-bit pixel format, 8 bits for red, green and blue.
  26. /// </summary>
  27. R8G8B8 = 3,
  28. /// <summary>
  29. /// 32-bit pixel format, 8 bits for red, green, blue and alpha.
  30. /// </summary>
  31. R8G8B8A8 = 8,
  32. /// <summary>
  33. /// DXT1/BC1 format containing opaque RGB or 1-bit alpha RGB. 4 bits per pixel.
  34. /// </summary>
  35. BC1 = 13,
  36. /// <summary>
  37. /// DXT3/BC2 format containing RGB with premultiplied alpha. 4 bits per pixel.
  38. /// </summary>
  39. BC1a = 14,
  40. /// <summary>
  41. /// DXT3/BC2 format containing RGB with explicit alpha. 8 bits per pixel.
  42. /// </summary>
  43. BC2 = 15,
  44. /// <summary>
  45. /// DXT5/BC2 format containing RGB with explicit alpha. 8 bits per pixel. Better alpha gradients than BC2.
  46. /// </summary>
  47. BC3 = 16,
  48. /// <summary>
  49. /// One channel compressed format. 4 bits per pixel.
  50. /// </summary>
  51. BC4 = 17,
  52. /// <summary>
  53. /// Two channel compressed format. 8 bits per pixel.
  54. /// </summary>
  55. BC5 = 18,
  56. /// <summary>
  57. /// Format storing RGB in half (16-bit) floating point format usable for HDR. 8 bits per pixel.
  58. /// </summary>
  59. BC6H = 19,
  60. /// <summary>
  61. /// Format storing RGB with optional alpha channel. Similar to BC1/BC2/BC3 formats but with higher quality and
  62. /// higher decompress overhead. 8 bits per pixel.
  63. /// </summary>
  64. BC7 = 20,
  65. /// <summary>
  66. /// 16-bit 1-channel s10e5 floating point pixel format, 16 bits (float) for red.
  67. /// </summary>
  68. Float16_R = 21,
  69. /// <summary>
  70. /// 32-bit, 2-channel s10e5 floating point pixel format, 16-bits (float) for red, 16-bits (float) for green.
  71. /// </summary>
  72. Float16_RG = 22,
  73. /// <summary>
  74. /// 48-bit, 3-channel s10e5 floating point pixel format,, 16 bits (float) for red, 16 bits (float) for green,
  75. /// 16 bits (float) for blue.
  76. /// </summary>
  77. Float16_RGB = 23,
  78. /// <summary>
  79. /// 64-bit, 4-channel s10e5 floating point pixel format, 16 bits (float) for red, 16 bits (float) for green,
  80. /// 16 bits (float) for blue, 16 bits (float) for alpha.
  81. /// </summary>
  82. Float16_RGBA = 24,
  83. /// <summary>
  84. /// 32-bit pixel format, 32 bits (float) for red.
  85. /// </summary>
  86. Float32_R = 25,
  87. /// <summary>
  88. /// 64-bit, pixel format, 32-bits (float) for red, 32-bits (float) for green.
  89. /// </summary>
  90. Float32_RG = 26,
  91. /// <summary>
  92. /// 96-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue.
  93. /// </summary>
  94. Float32_RGB = 27,
  95. /// <summary>
  96. /// 128-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue,
  97. /// 32 bits (float) for alpha.
  98. /// </summary>
  99. Float32_RGBA = 28,
  100. /// <summary>
  101. /// Depth stencil format, 32bit depth, 8bit stencil + 24 unused.
  102. /// </summary>
  103. D32_S8X24 = 29,
  104. /// <summary>
  105. /// Depth stencil format, 24bit depth + 8bit stencil.
  106. /// </summary>
  107. D24S8 = 30,
  108. /// <summary>
  109. /// Depth format, 32bits.
  110. /// </summary>
  111. D32 = 31,
  112. /// <summary>
  113. /// Depth format, 16bits.
  114. /// </summary>
  115. D16 = 32
  116. };
  117. /// <summary>
  118. /// A buffer describing a volume (3D), image (2D) or line (1D) of pixels in memory. Pixels are stored as a succession
  119. /// of "depth" slices, each containing "height" rows of "width" pixels.
  120. /// </summary>
  121. public sealed class PixelData : ScriptObject
  122. {
  123. /// <summary>
  124. /// Width, height and depth of the pixels this object is capable of holding.
  125. /// </summary>
  126. public PixelVolume Extents
  127. {
  128. get
  129. {
  130. PixelVolume volume;
  131. Internal_GetExtents(mCachedPtr, out volume);
  132. return volume;
  133. }
  134. }
  135. /// <summary>
  136. /// Format of the pixels in the buffer.
  137. /// </summary>
  138. public PixelFormat Format
  139. {
  140. get
  141. {
  142. PixelFormat format;
  143. Internal_GetFormat(mCachedPtr, out format);
  144. return format;
  145. }
  146. }
  147. /// <summary>
  148. /// Returns number of bytes per a row of pixels.
  149. /// </summary>
  150. public int RawRowPitch
  151. {
  152. get
  153. {
  154. int rowPitch;
  155. Internal_GetRowPitch(mCachedPtr, out rowPitch);
  156. return rowPitch;
  157. }
  158. }
  159. /// <summary>
  160. /// Returns number of bytes per a 2D slice/plane of pixels.
  161. /// </summary>
  162. public int RawSlicePitch
  163. {
  164. get
  165. {
  166. int slicePitch;
  167. Internal_GetSlicePitch(mCachedPtr, out slicePitch);
  168. return slicePitch;
  169. }
  170. }
  171. /// <summary>
  172. /// Returns total number of bytes used by all the pixels.
  173. /// </summary>
  174. public int RawSize
  175. {
  176. get
  177. {
  178. int size;
  179. Internal_GetSize(mCachedPtr, out size);
  180. return size;
  181. }
  182. }
  183. /// <summary>
  184. /// Checks are the pixels in the buffer consecutive. If this is false then the buffer has padding and you should
  185. /// check <see cref="RawRowPitch"/> and <see cref="RawSlicePitch"/> when accessing it directly.
  186. /// </summary>
  187. public bool RawIsConsecutive
  188. {
  189. get
  190. {
  191. bool isConsecutive;
  192. Internal_GetIsConsecutive(mCachedPtr, out isConsecutive);
  193. return isConsecutive;
  194. }
  195. }
  196. /// <summary>
  197. /// Constructor for internal use by the runtime.
  198. /// </summary>
  199. private PixelData()
  200. { }
  201. /// <summary>
  202. /// Creates a new pixel data buffer capable of storing the specified amount of pixels.
  203. /// </summary>
  204. /// <param name="volume">Width, height and depth determining number of pixels to store.</param>
  205. /// <param name="format">Format of individual pixels.</param>
  206. public PixelData(PixelVolume volume, PixelFormat format = PixelFormat.R8G8B8A8)
  207. {
  208. Internal_CreateInstance(this, ref volume, format);
  209. }
  210. /// <summary>
  211. /// Creates a new 2D pixel data buffer capable of storing the specified amount of pixels.
  212. /// </summary>
  213. /// <param name="width">Number of pixels in each row.</param>
  214. /// <param name="height">Number of pixels in each column.</param>
  215. /// <param name="format">Format of individual pixels.</param>
  216. public PixelData(int width, int height, PixelFormat format = PixelFormat.R8G8B8A8)
  217. {
  218. PixelVolume volume = new PixelVolume(0, 0, width, height);
  219. Internal_CreateInstance(this, ref volume, format);
  220. }
  221. /// <summary>
  222. /// Creates a new 3D pixel data buffer capable of storing the specified amount of pixels.
  223. /// </summary>
  224. /// <param name="width">Number of pixels in each row.</param>
  225. /// <param name="height">Number of pixels in each column.</param>
  226. /// <param name="depth">Number of 2D slices.</param>
  227. /// <param name="format">Format of individual pixels.</param>
  228. public PixelData(int width, int height, int depth, PixelFormat format = PixelFormat.R8G8B8A8)
  229. {
  230. PixelVolume volume = new PixelVolume(0, 0, 0, width, height, depth);
  231. Internal_CreateInstance(this, ref volume, format);
  232. }
  233. /// <summary>
  234. /// Returns a pixel at the specified location in the buffer.
  235. /// </summary>
  236. /// <param name="x">X coordinate of the pixel.</param>
  237. /// <param name="y">Y coordinate of the pixel.</param>
  238. /// <param name="z">Z coordinate of the pixel.</param>
  239. /// <returns>Value of the pixel, or undefined value if coordinates are out of range.</returns>
  240. public Color GetPixel(int x, int y, int z = 0)
  241. {
  242. Color pixel;
  243. Internal_GetPixel(mCachedPtr, x, y, z, out pixel);
  244. return pixel;
  245. }
  246. /// <summary>
  247. /// Sets a pixel at the specified location in the buffer.
  248. /// </summary>
  249. /// <param name="color">Color of the pixel to set.</param>
  250. /// <param name="x">X coordinate of the pixel.</param>
  251. /// <param name="y">Y coordinate of the pixel.</param>
  252. /// <param name="z">Z coordinate of the pixel.</param>
  253. public void SetPixel(Color color, int x, int y, int z = 0)
  254. {
  255. Internal_SetPixel(mCachedPtr, x, y, z, ref color);
  256. }
  257. /// <summary>
  258. /// Returns values of all pixels.
  259. /// </summary>
  260. /// <returns>All pixels in the buffer ordered consecutively. Pixels are stored as a succession of "depth" slices,
  261. /// each containing "height" rows of "width" pixels.</returns>
  262. public Color[] GetPixels()
  263. {
  264. Color[] pixels;
  265. Internal_GetPixels(mCachedPtr, out pixels);
  266. return pixels;
  267. }
  268. /// <summary>
  269. /// Sets all pixels in the buffer. Caller must ensure that number of pixels match the extends of the buffer.
  270. /// </summary>
  271. /// <param name="pixels">All pixels to set ordered consecutively. Pixels are stored as a succession of "depth"
  272. /// slices, each containing "height" rows of "width" pixels.</param>
  273. public void SetPixels(Color[] pixels)
  274. {
  275. Internal_SetPixels(mCachedPtr, pixels);
  276. }
  277. /// <summary>
  278. /// Returns all pixels in the buffer as raw bytes.
  279. /// </summary>
  280. /// <returns>Raw pixel bytes. It is up to the caller to interpret the pixel format and account for potential
  281. /// row and slice pitch values.</returns>
  282. public byte[] GetRawPixels()
  283. {
  284. byte[] pixels;
  285. Internal_GetRawPixels(mCachedPtr, out pixels);
  286. return pixels;
  287. }
  288. /// <summary>
  289. /// Sets all pixels in the buffer as raw bytes.
  290. /// </summary>
  291. /// <param name="pixels">Raw pixel bytes. It is up to the caller to set the proper pixel format and account for
  292. /// potential row and slice pitch values.</param>
  293. public void SetRawPixels(byte[] pixels)
  294. {
  295. Internal_SetRawPixels(mCachedPtr, pixels);
  296. }
  297. [MethodImpl(MethodImplOptions.InternalCall)]
  298. private static extern void Internal_CreateInstance(PixelData instance, ref PixelVolume volume, PixelFormat format);
  299. [MethodImpl(MethodImplOptions.InternalCall)]
  300. private static extern void Internal_GetPixel(IntPtr thisPtr, int x, int y, int z, out Color value);
  301. [MethodImpl(MethodImplOptions.InternalCall)]
  302. private static extern void Internal_SetPixel(IntPtr thisPtr, int x, int y, int z, ref Color value);
  303. [MethodImpl(MethodImplOptions.InternalCall)]
  304. private static extern void Internal_GetPixels(IntPtr thisPtr, out Color[] value);
  305. [MethodImpl(MethodImplOptions.InternalCall)]
  306. private static extern void Internal_SetPixels(IntPtr thisPtr, Color[] value);
  307. [MethodImpl(MethodImplOptions.InternalCall)]
  308. private static extern void Internal_GetRawPixels(IntPtr thisPtr, out byte[] value);
  309. [MethodImpl(MethodImplOptions.InternalCall)]
  310. private static extern void Internal_SetRawPixels(IntPtr thisPtr, byte[] value);
  311. [MethodImpl(MethodImplOptions.InternalCall)]
  312. private static extern void Internal_GetExtents(IntPtr thisPtr, out PixelVolume value);
  313. [MethodImpl(MethodImplOptions.InternalCall)]
  314. private static extern void Internal_GetFormat(IntPtr thisPtr, out PixelFormat value);
  315. [MethodImpl(MethodImplOptions.InternalCall)]
  316. private static extern void Internal_GetRowPitch(IntPtr thisPtr, out int value);
  317. [MethodImpl(MethodImplOptions.InternalCall)]
  318. private static extern void Internal_GetSlicePitch(IntPtr thisPtr, out int value);
  319. [MethodImpl(MethodImplOptions.InternalCall)]
  320. private static extern void Internal_GetSize(IntPtr thisPtr, out int value);
  321. [MethodImpl(MethodImplOptions.InternalCall)]
  322. private static extern void Internal_GetIsConsecutive(IntPtr thisPtr, out bool value);
  323. }
  324. /// <summary>
  325. /// Represents a 3D region of pixels used for referencing pixel data.
  326. /// </summary>
  327. [StructLayout(LayoutKind.Sequential)]
  328. public struct PixelVolume // Note: Must match C++ class PixelVolume
  329. {
  330. private int left, top, right, bottom, front, back;
  331. /// <summary>
  332. /// Returns the left border of the pixel region (minimal X).
  333. /// </summary>
  334. public int Left { get { return left; } }
  335. /// <summary>
  336. /// Returns the right border of the pixel region (maximal X).
  337. /// </summary>
  338. public int Right { get { return right; } }
  339. /// <summary>
  340. /// Returns the top border of the pixel region (minimal Y).
  341. /// </summary>
  342. public int Top { get { return top; } }
  343. /// <summary>
  344. /// Returns the bottom border of the pixel region (maximal Y).
  345. /// </summary>
  346. public int Bottom { get { return bottom; } }
  347. /// <summary>
  348. /// Returns the front border of the pixel region (minimal Z).
  349. /// </summary>
  350. public int Front { get { return front; } }
  351. /// <summary>
  352. /// Returns the back border of the pixel region (maximal Z).
  353. /// </summary>
  354. public int Back { get { return back; } }
  355. /// <summary>
  356. /// Returns the number of pixels between right and left borders of the volume.
  357. /// </summary>
  358. public int Width { get { return right - left; } }
  359. /// <summary>
  360. /// Returns the number of pixels between bottom and top borders of the volume.
  361. /// </summary>
  362. public int Height { get { return bottom - top; } }
  363. /// <summary>
  364. /// Returns the number of pixels between back and front borders of the volume.
  365. /// </summary>
  366. public int Depth { get { return back - front; } }
  367. /// <summary>
  368. /// Creates a new 2D region.
  369. /// </summary>
  370. /// <param name="left">Left border of the region.</param>
  371. /// <param name="top">Top border of the region.</param>
  372. /// <param name="right">Right border of the region. Must be larger than left border.</param>
  373. /// <param name="bottom">Bottom border of the region. Must be larger than top border.</param>
  374. public PixelVolume(int left, int top, int right, int bottom)
  375. {
  376. this.left = left;
  377. this.right = right;
  378. this.top = top;
  379. this.bottom = bottom;
  380. this.front = 0;
  381. this.back = 1;
  382. }
  383. /// <summary>
  384. /// Creates a new 3D region.
  385. /// </summary>
  386. /// <param name="left">Left border of the region.</param>
  387. /// <param name="top">Top border of the region.</param>
  388. /// <param name="front">Front border of the region.</param>
  389. /// <param name="right">Right border of the region. Must be larger than left border.</param>
  390. /// <param name="bottom">Bottom border of the region. Must be larger than top border.</param>
  391. /// <param name="back">Back border of the region. Must be larger than back border.</param>
  392. public PixelVolume(int left, int top, int front, int right, int bottom, int back)
  393. {
  394. this.left = left;
  395. this.right = right;
  396. this.top = top;
  397. this.bottom = bottom;
  398. this.front = front;
  399. this.back = back;
  400. }
  401. };
  402. /** @} */
  403. }