PixelData.cs 17 KB

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