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