BsPixelUtil.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "Image/BsPixelData.h"
  6. namespace bs
  7. {
  8. // Undefine conflicting defines from other libs
  9. #undef None
  10. /** @addtogroup Utility-Core
  11. * @{
  12. */
  13. /** Types of texture compression quality. */
  14. enum class CompressionQuality
  15. {
  16. Fastest,
  17. Normal,
  18. Production,
  19. Highest
  20. };
  21. /** Mode of the alpha channel in a texture. */
  22. enum class AlphaMode
  23. {
  24. None, /*< Texture has no alpha values. */
  25. Transparency, /*< Alpha is in the separate transparency channel. */
  26. Premultiplied /*< Alpha values have been pre-multiplied with the color values. */
  27. };
  28. /** Wrap mode to use when generating mip maps. */
  29. enum class MipMapWrapMode
  30. {
  31. Mirror,
  32. Repeat,
  33. Clamp
  34. };
  35. /** Filter to use when generating mip maps. */
  36. enum class MipMapFilter
  37. {
  38. Box,
  39. Triangle,
  40. Kaiser
  41. };
  42. /** Determines on which axes to mirror an image. */
  43. enum class MirrorModeBits
  44. {
  45. X = 1 << 0,
  46. Y = 1 << 1,
  47. Z = 1 << 2
  48. };
  49. typedef Flags<MirrorModeBits> MirrorMode;
  50. BS_FLAGS_OPERATORS(MirrorModeBits);
  51. /** Options used to control texture compression. */
  52. struct CompressionOptions
  53. {
  54. PixelFormat format = PF_BC1; /*< Format to compress to. Must be a format containing compressed data. */
  55. AlphaMode alphaMode = AlphaMode::None; /*< Controls how to (and if) to compress the alpha channel. */
  56. bool isNormalMap = false; /*< Determines does the input data represent a normal map. */
  57. bool isSRGB = false; /*< Determines has the input data been gamma corrected. */
  58. CompressionQuality quality = CompressionQuality::Normal; /*< Compressed image quality. Better compression might take longer to execute but will generate better results. */
  59. };
  60. /** Options used to control texture mip map generation. */
  61. struct MipMapGenOptions
  62. {
  63. MipMapFilter filter = MipMapFilter::Box; /*< Filter to use when downsamping input data. */
  64. MipMapWrapMode wrapMode = MipMapWrapMode::Mirror; /*< Determines how to downsample pixels on borders. */
  65. bool isNormalMap = false; /*< Determines does the input data represent a normal map. */
  66. bool normalizeMipmaps = false; /*< Should the downsampled values be re-normalized. Only relevant for mip-maps representing normal maps. */
  67. bool isSRGB = false; /*< Determines has the input data been gamma corrected. */
  68. };
  69. /** Utility methods for converting and managing pixel data and formats. */
  70. class BS_CORE_EXPORT PixelUtil
  71. {
  72. public:
  73. /** Filtering types to use when scaling images. */
  74. enum Filter
  75. {
  76. FILTER_NEAREST, /*< No filtering is performed and nearest existing value is used. */
  77. FILTER_LINEAR /*< Box filter is applied, averaging nearby pixels. */
  78. };
  79. /** Returns the size of a single pixel of the provided pixel format, in bytes. */
  80. static UINT32 getNumElemBytes(PixelFormat format);
  81. /** Returns the size of a single pixel of the provided pixel format, in bits. */
  82. static UINT32 getNumElemBits(PixelFormat format);
  83. /** Returns the size of the memory region required to hold pixels of the provided size ana format. */
  84. static UINT32 getMemorySize(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format);
  85. /** Calculates the size of a mip level of a texture with the provided size. */
  86. static void getSizeForMipLevel(UINT32 width, UINT32 height, UINT32 depth, UINT32 mipLevel,
  87. UINT32& mipWidth, UINT32& mipHeight, UINT32& mipDepth);
  88. /**
  89. * Calculates row and depth pitch for a texture surface of the specified size and format. For most this will be
  90. * equal to their width & height, respectively. But some texture formats (especially compressed ones) might
  91. * require extra padding.
  92. */
  93. static void getPitch(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format,
  94. UINT32& rowPitch, UINT32& depthPitch);
  95. /**
  96. * Returns property flags for this pixel format.
  97. *
  98. * @see PixelFormatFlags
  99. */
  100. static UINT32 getFlags(PixelFormat format);
  101. /** Checks if the provided pixel format has an alpha channel. */
  102. static bool hasAlpha(PixelFormat format);
  103. /** Checks is the provided pixel format a floating point format. */
  104. static bool isFloatingPoint(PixelFormat format);
  105. /** Checks is the provided pixel format compressed. */
  106. static bool isCompressed(PixelFormat format);
  107. /** Checks is the provided pixel format a depth/stencil buffer format. */
  108. static bool isDepth(PixelFormat format);
  109. /** Checks does the provided format store data in normalized range. */
  110. static bool isNormalized(PixelFormat format);
  111. /**
  112. * Checks is the provided format valid for the texture type and usage.
  113. *
  114. * @param[in, out] format Format to check. If format is not valid the method will update this with the closest
  115. * relevant format.
  116. * @param[in] texType Type of the texture the format will be used for.
  117. * @param[in] usage A set of TextureUsage flags that define how will a texture be used.
  118. * @return True if the format is valid, false if not.
  119. *
  120. * @note This method checks only for obvious format mismatches:
  121. * - Using depth format for anything but a depth-stencil buffer
  122. * - Using anything but a depth format for a depth-stencil-buffer
  123. * - Using compressed format for anything but normal textures
  124. * - Using compressed format for 1D textures
  125. *
  126. * Caller should still check for platform-specific unsupported formats.
  127. */
  128. static bool checkFormat(PixelFormat& format, TextureType texType, int usage);
  129. /**
  130. * Checks are the provided dimensions valid for the specified pixel format. Some formats (like BC) require
  131. * width/height to be multiples of four and some formats dont allow depth larger than 1.
  132. */
  133. static bool isValidExtent(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format);
  134. /**
  135. * Returns the number of bits per each element in the provided pixel format. This will return all zero for
  136. * compressed and depth/stencil formats.
  137. */
  138. static void getBitDepths(PixelFormat format, int(&rgba)[4]);
  139. /**
  140. * Returns bit masks that determine in what bit range is each channel stored.
  141. *
  142. * @note
  143. * For example if your color is stored in an UINT32 and you want to extract the red channel you should AND the color
  144. * UINT32 with the bit-mask for the red channel and then right shift it by the red channel bit shift amount.
  145. */
  146. static void getBitMasks(PixelFormat format, UINT32(&rgba)[4]);
  147. /**
  148. * Returns number of bits you need to shift a pixel element in order to move it to the start of the data type.
  149. *
  150. * @note
  151. * For example if your color is stored in an UINT32 and you want to extract the red channel you should AND the color
  152. * UINT32 with the bit-mask for the red channel and then right shift it by the red channel bit shift amount.
  153. */
  154. static void getBitShifts(PixelFormat format, UINT8 (&rgba)[4]);
  155. /** Returns the name of the pixel format. */
  156. static String getFormatName(PixelFormat srcformat);
  157. /**
  158. * Returns true if the pixel data in the format can be directly accessed and read. This is generally not true
  159. * for compressed formats.
  160. */
  161. static bool isAccessible(PixelFormat srcformat);
  162. /** Returns the type of an individual pixel element in the provided format. */
  163. static PixelComponentType getElementType(PixelFormat format);
  164. /** Returns the number of pixel elements in the provided format. */
  165. static UINT32 getNumElements(PixelFormat format);
  166. /**
  167. * Returns the maximum number of mip maps that can be generated until we reach the minimum size possible. This
  168. * does not count the base level.
  169. */
  170. static UINT32 getMaxMipmaps(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format);
  171. /** Writes the color to the provided memory location. */
  172. static void packColor(const Color& color, PixelFormat format, void* dest);
  173. /**
  174. * Writes the color to the provided memory location. If the destination format is floating point, the byte values
  175. * will be converted into [0.0, 1.0] range.
  176. */
  177. static void packColor(UINT8 r, UINT8 g, UINT8 b, UINT8 a, PixelFormat format, void* dest);
  178. /**
  179. * Writes the color to the provided memory location. If the destination format in non-floating point, the float
  180. * values will be assumed to be in [0.0, 1.0] which will be converted to integer range. ([0, 255] in the case of bytes)
  181. */
  182. static void packColor(float r, float g, float b, float a, const PixelFormat format, void* dest);
  183. /** Reads the color from the provided memory location and stores it into the provided color object. */
  184. static void unpackColor(Color* color, PixelFormat format, const void* src);
  185. /**
  186. * Reads the color from the provided memory location and stores it into the provided color elements, as bytes
  187. * clamped to [0, 255] range.
  188. */
  189. static void unpackColor(UINT8* r, UINT8* g, UINT8* b, UINT8* a, PixelFormat format, const void* src);
  190. /**
  191. * Reads the color from the provided memory location and stores it into the provided color elements. If the format
  192. * is not natively floating point a conversion is done in such a way that returned values range [0.0, 1.0].
  193. */
  194. static void unpackColor(float* r, float* g, float* b, float* a, PixelFormat format, const void* src);
  195. /** Writes a depth value to the provided memory location. Depth should be in range [0, 1]. */
  196. static void packDepth(float depth, const PixelFormat format, void* dest);
  197. /** Reads the depth from the provided memory location. Value ranges in [0, 1]. */
  198. static float unpackDepth(PixelFormat format, void* src);
  199. /**
  200. * Converts pixels from one format to another. Provided pixel data objects must have previously allocated buffers
  201. * of adequate size and their sizes must match.
  202. */
  203. static void bulkPixelConversion(const PixelData& src, PixelData& dst);
  204. /** Flips the order of components in each individual pixel. For example RGBA -> ABGR. */
  205. static void flipComponentOrder(PixelData& data);
  206. /** Compresses the provided data using the specified compression options. */
  207. static void compress(const PixelData& src, PixelData& dst, const CompressionOptions& options);
  208. /**
  209. * Generates mip-maps from the provided source data using the specified compression options. Returned list includes
  210. * the base level.
  211. *
  212. * @return A list of calculated mip-map data. First entry is the largest mip and other follow in order from
  213. * largest to smallest.
  214. */
  215. static Vector<SPtr<PixelData>> genMipmaps(const PixelData& src, const MipMapGenOptions& options);
  216. /**
  217. * Scales pixel data in the source buffer and stores the scaled data in the destination buffer. Provided pixel data
  218. * objects must have previously allocated buffers of adequate size. You may also provided a filtering method to use
  219. * when scaling.
  220. */
  221. static void scale(const PixelData& src, PixelData& dst, Filter filter = FILTER_LINEAR);
  222. /**
  223. * Mirrors the contents of the provided object along the X, Y and/or Z axes. */
  224. static void mirror(PixelData& pixelData, MirrorMode mode);
  225. /**
  226. * Copies the contents of the @p src buffer into the @p dst buffer. The size of the copied contents is determined
  227. * by the size of the @p dst buffer. First pixel copied from @p src is determined by offset provided in
  228. * @p offsetX, @p offsetY and @p offsetZ parameters.
  229. */
  230. static void copy(const PixelData& src, PixelData& dst, UINT32 offsetX = 0, UINT32 offsetY = 0, UINT32 offsetZ = 0);
  231. /**
  232. * Applies gamma correction to the pixels in the provided buffer.
  233. *
  234. * @param[in] buffer Pointer to the buffer containing the pixels.
  235. * @param[in] gamma Gamma value to apply.
  236. * @param[in] size Size of the buffer in bytes.
  237. * @param[in] bpp Number of bits per pixel of the pixels in the buffer.
  238. */
  239. static void applyGamma(UINT8* buffer, float gamma, UINT32 size, UINT8 bpp);
  240. };
  241. /** @} */
  242. }