1// tPixelFormat.h 
2// 
3// Pixel formats in Tacent. Not all formats are fully supported. Certainly BC 4, 5, and 7 may not have extensive HW 
4// support at this time. 
5// 
6// Copyright (c) 2004-2006, 2017, 2019, 2022-2024 Tristan Grimmer. 
7// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
8// granted, provided that the above copyright notice and this permission notice appear in all copies. 
9// 
10// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
11// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
12// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
13// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
14// PERFORMANCE OF THIS SOFTWARE. 
15 
16#pragma once 
17namespace tImage 
18
19 
20 
21// Unlike DirectX, which assumes all machines are little-endian, the enumeration below specifies the components in the 
22// order they appear _in memory_. This means formats commonly called things like B5G6R5 are actually G3R5B5G3. The 
23// latter is what they are referred to in Tacent, This inconsistent naming gets worse since when things are byte-aligned 
24// most vendor pixel formats are actually correct for the mempry representation. In any case, in Tacent, it's always the 
25// in-memory representation that gets named. BC stands for Block Compression. 
26// 
27// A note regarding sRGB. We are _not_ indicating via the pixel format what space/profilr the colour encoded by the 
28// format is in. Tacent separates the encoding (the pixel format) from how the encoded data is to be interpreted. This 
29// is in contrast to all the MS DXGI formats where they effectively at least double the number of formats unnecessarily. 
30// 
31// A way to think of it is as follows -- You have some input data (Din) that gets encoded using a pixel format (Epf) 
32// resulting in some output data (Dout). Din -> Epf -> Dout. Without changing Din, if changing Epf would result in 
33// different Dout, it is correct to have separate formats (eg. BCH6_S vs BCH6_U. DXT1 vs DXT1BA). If changing Epf would 
34// not result in different Dout then the formats are not different and satellite info should be used if what's stored in 
35// Din (and Dout) has certain properties (eg. sRGB space vs Linear, premultiplied vs not, DXT2 and DXT3 are the same). 
36// 
37// This is also why we don't distinguish between UNORM and UINT for example, as this is just a runtime distinction, not 
38// an encoding difference (For example, UNORM gets converted to a float in [0.0, 1.0] in shaders, UINT doesn't). 
39// 
40// The only exception to this rule is the Tacent pixel format _does_ make distinctions between formats based on the 
41// colour components being represented. It's not ideal, but pixel formats do generally specify R, G, B, A, L etc and 
42// what order they appear in. In a perfect world (in my perfect world anyways), R8G8B8 would just be C8C8C8 (C8X3) and 
43// satellite info would describe what the data represented (RGB in this case). Anyway, that's too much of a divergence. 
44// This exception is why there is a tPixelFormat R8 (Vulkan has one of these), A8, and L8, all 3 with the same internal 
45// representation. 
46// 
47// Summary of Satellite and Pixel-Format information: 
48// 
49// Colour Profile (Satellite) 
50// A colour profile basically specifies the colour space for the various components. Sometimes 
51// the same space is not used for all components. It is common for RGB to be sRGB but alpha to be linear -- there is 
52// a profile for that. See tColourProfile and tColourSpace enum in tColour.h. 
53// 
54// Component Format (Pixel-Format) 
55// The encoding is different for unsigned int, int, unsigned float, and float. Since the encoding is different, 
56// this information IS specified by the pixel format. In particular a lower-case suffix is used for the packed 
57// pixel-formats if it is not unsigned int: 
58// no suffix -> unsigned int. 
59// s -> signed int (2's complimemt). 
60// uf -> unsigned float (always >= 0.0). No sign bit. 
61// f -> signed float. 
62// 
63// Some non-packed pixel-formats like BC and EAC distinguich between the encoding of signed vs unsigned data. In 
64// these cases we use a single capital letter suffix. If a non-packed encoding does not distinguish, no suffix. 
65// No Suffix -> Format does not distinguish. 
66// S -> Signed Variant. 
67// U -> Unsigned Variant. 
68// 
69// Channel Type (Satellite) 
70// Sometimes it is intended that the data stored with each component is further modified before being used. In 
71// particular it may be normalized. ChannelType is additional satellite information that is not entirely specified 
72// by the pixel format so it belongs as satellite information here. In particular the part that isn't specified is 
73// whether the component data of each colour channel should be normalized or not afterwards. It gets a little tricky 
74// here because Vulkan, OpenGL, and DirectX have all decided on variant pixel-format names with channel-type 
75// information like UNORM, SNORM, UINT, SINT, and FLOAT. This naming _includes_ both information about how the data 
76// is encoded (integer or float, signed or unsigned) as well as whether to normalize after decoding or not. We have a 
77// choice here, either ONLY make this satellite info contain whether to normalize of not afterwards, or have a litte 
78// redundant information in order to keep the naming as close as possible to UNORM, UINT, etc. I have decided on the 
79// latter. 
80// 
81// The reason it is not part of the pixel format is it is quite common for the data to be encoded as, say, an 
82// unsigned integer, but 'converted' to a float when it is passed off the video memory by the graphics API so it is 
83// available as a float in the fragment/pixel shader. In short the ChannelType indicates intent for what should 
84// happen to the value AFTER decoding. For example, UNORM means the data is stored (or decoded for compressed 
85// formats) as an unsigned integer (which is already known by looking at the pixel-format) -- it is then converted to 
86// a normalized value in [0.0, 1.0]. SNORM means it's stored as a signed integer and then normalized to the 
87// [0.0, 1.0] range. The actual number of bits used is NOT specified here -- that is also specified by the 
88// pixel-format itself (either explicitly or implicitly by inspecting the compression method used). I bring this up 
89// because, for example, the PVR3 filetype 'channel type' field does contain size information, but it doesn't need to 
90// (and probably shouldn't). 
91// 
92// Example 1. PixelFormat: G3B5R5G3 ChanelType: UNORM 
93// We know the R and B are stored as 5-bit unsigned ints and the G with six bits. We know this from the PixelFormat 
94// alone because it does not contain a 's', 'f', or 'uf'. We further know the intent is to 'normalize' it after 
95// decoding. R would be in [0, 31] and converted to [0.0, 1.0]. The 'U' part of 'UNORM' is redundant because the 
96// pixel-format already told us it was an unsigned integer. 
97// 
98// Example 2. PixelFormat: R11G11B10uf ChanelType: UFLOAT 
99// RG stored as 11-bit unsigned floats (5 exponent, 6 mantissa, no sign bit). B stored as a 10-bit (5,5) float. In 
100// this case the ChannelType is completely redundant because we already know we're using unsigned floats from the 'uf'. 
101// 
102// Example 3. PixelFormat: R8G8 ChanelType: UINT 
103// RG stored as 8-bit unsigned ints (from pixel-format). In this case the ChannelType indicates _not_ to normalize so 
104// each component should be read as an unsigned integer in [0, 255]. 
105// 
106 
107 
108enum class tPixelFormat 
109
110 Invalid = -1
111 Auto = Invalid
112 Unspecified = Invalid
113 
114 FirstValid
115 FirstContiguous = FirstValid
116 FirstPacked = FirstContiguous
117 R8 = FirstPacked, // 8 bit. Unsigned representing red. Some file-types not supporting A8 or L8 (eg ktx2) will export to this. 
118 R8G8, // 16 bit. Unsigned representing red and green. Vulkan has an analagous format. 
119 R8G8B8, // 24 bit. Full colour. No alpha. Matches GL_RGB source ordering. Not efficient. Most drivers will swizzle to BGR. 
120 R8G8B8A8, // 32 bit. Full alpha. Matches GL_RGBA source ordering. Not efficient. Most drivers will swizzle to ABGR. 
121 B8G8R8, // 24 bit. Full colour. No alpha. Matches GL_BGR source ordering. Efficient. Most drivers do not need to swizzle. 
122 B8G8R8A8, // 32 bit. Full alpha. Matches GL_BGRA source ordering. Most drivers do not need to swizzle. 
123 
124 G3B5R5G3, // 16 bit. No alpha. Incorrectly AKA B5G6R5. The truth is in memory it is GGGBBBBB RRRRRGGG -> this is G3B5R5G3. 
125 G4B4A4R4, // 16 bit. 12 colour bits. 4 bit alpha. Incorrectly AKA B4G4R4A4. 
126 B4A4R4G4, // 16 bit. 12 colour bits. 4 bit alpha. Incorrectly AKA R4G4B4A4. 
127 G3B5A1R5G2, // 16 bit. 15 colour bits. Binary alpha. Incorrectly AKA B5G5R5A1. 
128 G2B5A1R5G3, // 16 bit. 15 colour bits. Binary alpha. Incorrectly AKA R5G5B5A1. 
129 A8L8, // 16 bit. Alpha and Luminance. 
130 A8, // 8 bit. Alpha only. 
131 L8, // 8 bit. Luminance only. 
132 R16, // 16 bit. 16 bit Red. 
133 R16G16, // 32 bit. 16 bit R. 16 bit G. 
134 R16G16B16, // 48 bit. 16 bit each RGB. 
135 R16G16B16A16, // 64 bit. 16 bit each RGBA. 
136 R32, // 32 bit. Red. 
137 R32G32, // 64 bit. Red Green. 
138 R32G32B32, // 96 bit. 32 bit each RGB. 
139 R32G32B32A32, // 128 bit. 32 bit each RGBA. 
140 R16f, // 16 bit. Half-float red/luminance channel only. HDR linear space. 
141 R16G16f, // 32 bit. Two half-floats per pixel. RG. HDR linear space. 
142 R16G16B16f, // 48 bit. Three half-floats per pixel. RGB. HDR linear space. 
143 R16G16B16A16f, // 64 bit. Four half-floats per pixel. RGBA. HDR linear space. 
144 R32f, // 32 bit. Float red/luminance channel only. HDR linear space. 
145 R32G32f, // 64 bit. Two floats per pixel. RG. HDR linear space. 
146 R32G32B32f, // 96 bit. Three floats per pixel. RGB. HDR linear space. 
147 R32G32B32A32f, // 128 bit. Four floats per pixel. RGBA. HDR linear space. 
148 R11G11B10uf, // 32 bit. Unsigned 11-bit floats for RG, and a 10-bit float for B. All use a 5-bit exponent. 
149 B10G11R11uf, // 32 bit. Unsigned 10-bit floats for B, and 11-bit floats for GR. All use a 5-bit exponent. 
150 R9G9B9E5uf, // 32 bit. Unsigned 14-bit floats for RGB. Always denorm and each share the same 5-bit exponent. 
151 E5B9G9R9uf, // 32 bit. Unsigned 14-bit floats for RGB. Always denorm and each share the same 5-bit exponent. 
152 R8G8B8M8, // 32 bit. Poor-man's HDR. RGB plus shared 8-bit multiplier. Must supply MaxRange when decoding. 
153 R8G8B8D8, // 32 bit. Poor-man's HDR. RGB plus shared 8-bit divisor. Must supply MaxRange when decoding. 
154 LastPacked = R8G8B8D8
155 
156 FirstBC
157 BC1DXT1 = FirstBC, // BC 1, DXT1. No alpha. 
158 BC1DXT1A, // BC 1, DXT1. Binary alpha. 
159 BC2DXT2DXT3, // BC 2, DXT2 (premult-alpha) and DXT3 share the same format. Large alpha gradients (alpha banding). 
160 BC3DXT4DXT5, // BC 3, DXT4 (premult-alpha) and DXT5 share the same format. Variable alpha (smooth). 
161 BC4ATI1U, // BC 4. Unsigned. One colour channel only. May not be HW supported. 
162 BC4ATI1S, // BC 4. Signed. One colour channel only. May not be HW supported. 
163 BC5ATI2U, // BC 5. Unsigned. Two colour channels only. May not be HW supported. 
164 BC5ATI2S, // BC 5. Signed. Two colour channels only. May not be HW supported. 
165 BC6U, // BC 6 HDR. No alpha. 3 x 16bit unsigned half-floats per pixel. 
166 BC6S, // BC 6 HDR. No alpha. 3 x 16bit signed half-floats per pixel. 
167 BC7, // BC 7. Full colour. Variable alpha 0 to 8 bits. 
168 
169 FirstETC
170 ETC1 = FirstETC, // ETC1. Ericsson Texture Compression. Similar to BC1. RGB-only. No alpha. 
171 ETC2RGB, // ETC2. Backwards compatible with ETC1. The sRGB version is the same pixel format. 
172 ETC2RGBA, // ETC2. RGBA. sRGB uses the same pixel format. 
173 ETC2RGBA1, // ETC2. RGB with binary alpha. sRGB uses the same pixel format. 
174 LastETC = ETC2RGBA1
175 
176 FirstEAC
177 EACR11U = FirstEAC, // EAC R11. Ericsson. Single channel. 
178 EACR11S, // EAC R11. Signed. 
179 EACRG11U, // EAC RG11. Ericsson. Two channels. 
180 EACRG11S, // EAC RG11. Signed. 
181 LastEAC = EACRG11S
182 LastBC = LastEAC
183 
184 FirstPVR, // PowerVR. Imagination. 8-byte blocks. We do not consider the PVRTC formats to be BC formats because 4 blocks need to be accessed. i.e. The pixels are not 'confined' to the block they are in. 
185 PVRBPP4 = FirstPVR, // PVRTC Version 1. 4BPP representing RGB or RGBA channels. One block can encode 4x4 pixels (but needs access to adjacent blocks during decompress). 
186 PVRBPP2, // PVRTC Version 1. 2BPP representing RGB or RGBA channels. One block can encode 8x4 pixels. 
187 
188 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
189 PVRHDRBPP8, // PVRTC Version 1. 8BPP representing HDR RGB. 
190 PVRHDRBPP6, // PVRTC Version 1. 6BPP representing HDR RGB. 
191 PVR2BPP4, // PVRTC Version 2. 4BPP representing RGB or RGBA channels. 
192 PVR2BPP2, // PVRTC Version 2. 2BPP representing RGB or RGBA channels. 
193 PVR2HDRBPP8, // PVRTC Version 2. 8BPP representing HDR RGB. 
194 PVR2HDRBPP6, // PVRTC Version 2. 6BPP representing HDR RGB. 
195 LastPVR = PVR2HDRBPP6, 
196 #else 
197 LastPVR = PVRBPP2
198 #endif 
199 
200 FirstASTC
201 ASTC4X4 = FirstASTC, // 128 bits per 16 pixels. 8 bpp. LDR UNORM. 
202 ASTC5X4, // 128 bits per 20 pixels. 6.4 bpp. LDR UNORM. 
203 ASTC5X5, // 128 bits per 25 pixels. 5.12 bpp. LDR UNORM. 
204 ASTC6X5, // 128 bits per 30 pixels. 4.27 bpp. LDR UNORM. 
205 ASTC6X6, // 128 bits per 36 pixels. 3.56 bpp. LDR UNORM. 
206 ASTC8X5, // 128 bits per 40 pixels. 3.2 bpp. LDR UNORM. 
207 ASTC8X6, // 128 bits per 48 pixels. 2.67 bpp. LDR UNORM. 
208 ASTC8X8, // 128 bits per 64 pixels. 2.56 bpp. LDR UNORM. 
209 ASTC10X5, // 128 bits per 50 pixels. 2.13 bpp. LDR UNORM. 
210 ASTC10X6, // 128 bits per 60 pixels. 2 bpp. LDR UNORM. 
211 ASTC10X8, // 128 bits per 80 pixels. 1.6 bpp. LDR UNORM. 
212 ASTC10X10, // 128 bits per 100 pixels. 1.28 bpp. LDR UNORM. 
213 ASTC12X10, // 128 bits per 120 pixels. 1.07 bpp. LDR UNORM. 
214 ASTC12X12, // 128 bits per 144 pixels. 0.89 bpp. LDR UNORM. 
215 LastASTC = ASTC12X12
216 LastContiguous = LastASTC
217 
218 FirstVendor
219 RADIANCE = FirstVendor, // Radiance HDR. 
220 OPENEXR, // OpenEXR HDR. 
221 LastVendor = OPENEXR
222 
223 FirstPalette
224 PAL1BIT = FirstPalette, // 1-bit indexes to a palette. 2 colour. 1 bpp. Often dithered B/W. 
225 PAL2BIT, // 2-bit indexes to a palette. 4 colour. 2 bpp. 
226 PAL3BIT, // 3-bit indexes to a palette. 8 colour. 3 bpp. 
227 PAL4BIT, // 4-bit indexes to a palette. 16 colour. 4 bpp. 
228 PAL5BIT, // 5-bit indexes to a palette. 32 colour. 5 bpp. 
229 PAL6BIT, // 6-bit indexes to a palette. 64 colour. 6 bpp. 
230 PAL7BIT, // 7-bit indexes to a palette. 128 colour. 7 bpp. 
231 PAL8BIT, // 8-bit indexes to a palette. 256 colour. 8 bpp. 
232 LastPalette = PAL8BIT
233 
234 LastValid = LastPalette
235 NumPixelFormats
236 NumContiguousFormats = LastContiguous - FirstContiguous + 1
237 NumPackedFormats = LastPacked - FirstPacked + 1
238 NumBCFormats = LastBC - FirstBC + 1
239 NumPVRFormats = LastPVR - FirstPVR + 1
240 NumASTCFormats = LastASTC - FirstASTC + 1
241 NumVendorFormats = LastVendor - FirstVendor + 1
242 NumPaletteFormats = LastPalette - FirstPalette + 1 
243}; 
244 
245// Returns true if the supplied pixel format is a valid format and not an out of range marker. 
246bool tIsValidFormat (tPixelFormat); 
247 
248// Is the supplied format one in which the pixels are stored as a contiguous chunk of data. 
249bool tIsContiguousFormat(tPixelFormat); 
250 
251// Simple RGB and RGBA formats with different numbers of bits per component and different orderings. 
252bool tIsPackedFormat (tPixelFormat); 
253 
254// Is the format a 4x4 BC (Block Compression) format. This includes ETC and EAC formats. These 4x4 
255// blocks use various numbers of bits per block. 
256bool tIsBCFormat (tPixelFormat); 
257 
258// Returns true if the format is an ETC BC format. EAC is not considered part of ETC for this function. 
259// ETC formats are a subset of tIsBCFormat. 
260bool tIsETCFormat (tPixelFormat); 
261 
262// Returns true if the format is an EAC BC format. EAC formats are a subset of tIsBCFormat. 
263bool tIsEACFormat (tPixelFormat); 
264 
265// Is it one of the PVR formats. 
266bool tIsPVRFormat (tPixelFormat); 
267 
268// Is it one of the ASTC (Adaptive Scalable Texture Compression) block formats. Block sizes are avail from 4x4 up 
269// to 12x12. The 4x4 ASTC variant is not considered a BC format by tIsBCFormat. 
270bool tIsASTCFormat (tPixelFormat); 
271 
272bool tIsVendorFormat (tPixelFormat); 
273bool tIsPaletteFormat (tPixelFormat); 
274bool tIsAlphaFormat (tPixelFormat); 
275bool tIsOpaqueFormat (tPixelFormat); 
276bool tIsHDRFormat (tPixelFormat); 
277bool tIsLDRFormat (tPixelFormat); 
278bool tIsLuminanceFormat (tPixelFormat); // Single-channel luminance formats. Includes red-only formats. Does not include alpha only. 
279 
280// Gets the width/height in pixels of a block in the specified pixel-format. BC blocks are all 4x4. PVR blocks are 
281// either 4x4 or 8x4. ASTC blocks have varying width/height depending on specific ASTC format -- they vary from 4x4 to 
282// 12x12. Packed, Vendor, and Palette formats return 1 for width and height. Invalid pixel-formats return 0. 
283int tGetBlockWidth (tPixelFormat); 
284int tGetBlockHeight (tPixelFormat); 
285 
286// Given a block-width or block-height and how may pixels you need to store (image-width or image-height), returns the 
287// number of blocks you will need in that dimension. 
288int tGetNumBlocks (int blockWH, int imageWH); 
289 
290// Only applies to formats that can guarantee an integer number of bits per pixel. In particular does not apply to ASTC 
291// formats (even if the particular ASTC format has an integer number of bits-per-pixel). We report in bits (not bytes) 
292// because some formats (i.e. BC1) are only half a byte per pixel. Palette formats do not consider the palette entry, 
293// size, but rather the size of the index as there is one index per pixel. Returns 0 for non-integral bpp formats and 
294// all ASTC formats. 
295int tGetBitsPerPixel(tPixelFormat); 
296 
297// Works for any pixel format, even if a non-integral number of bits per pixel. In particular does work for ASTC 
298// formats. Returns 0.0f if pixel format is invalid. 
299float tGetBitsPerPixelFloat(tPixelFormat); 
300 
301// This function must be given a BC format, a PVR format, an ASTC format, or a packed format. 
302// BC formats : 4x4 with different number of bytes per block. 
303// PVR formats : 4x4 or 8x4 for the LDR PVR formats but always 8 bytes. Unknown for the HDR variants. 
304// ASTC formats : Varying MxN but always 16 bytes. 
305// Packed Formats : Considered 1x1 with varying number of bytes per pixel. 
306// Returns 0 otherwise. 
307int tGetBytesPerBlock(tPixelFormat); 
308 
309// Since there are numerous size functions already in the pixel-format header it makes sense to also add functions to 
310// query how many mipmaps would be needs for variously sized images. Note that due to various block sizes, you cannot 
311// compite the total pixel-area. Each mimpap will need its own set of blocks in either direction. The highest mip level 
312// (which will represent the smallest mipmap image of 1x1) will still use a single block. The lowest level (0) is the 
313// image at full (highest) dimensions. 
314 
315// Width and height should be >= 1. Returns 0 otherwise. 
316int tGetNumMipmapLevels(int width, int height); 
317 
318// Given a supplied width or height this function will return the next higher mip level dimension. Once the dimension 
319// reaches 1 it stays there. The width or height should be >= 1. If it is <= 0, 0 is returned. 
320int tGetNextMipmapLevelDim(int widthOrHeight); 
321 
322// Given a supplied width and height this function will return the next higher mip level dimensions. Once a dimension 
323// reaches 1 it stays there. This function reads and writes width and height. Both width and height should be >= 1. If 
324// one of them is <= 0, 0 is returned for that dimension. 
325void tGetNextMipmapLevelDims(int& width, int& height); 
326 
327// Given a base width or height at level 0 this function computes the corresponding dimension at the supplied level. 
328// The width or height should be >= 1. If it is <= 0, 0 is returned regardless of level. 
329// Level should be E [0, NumMipmapLevels). Below this range widthOrHeight is returned. Above this range 1 is returned. 
330int tGetMipmapDim(int widthOrHeight, int level); 
331 
332// Given level 0 width and height this function returns the width and height at the supplied level. This function 
333// reads and writes width and height. The input width and height should be >= 1. If one is <= 0, 0 is returned for that 
334// dimension regardless of level. Level should be E [0, NumMipmapLevels). Below this range width and height are 
335// left unmodified. Above this range width and height are both set to 1. 
336void tGetMipmapDims(int& width, int& height, int level); 
337 
338// Same as above but writes to mipWidth and mipHeight and reads from width and height. 
339void tGetMipmapDims(int& mipWidth, int& mipHeight, int width, int height, int level); 
340 
341extern const char* PixelFormatNames[]; 
342extern const char** PixelFormatNames_Packed
343extern const char** PixelFormatNames_Block
344extern const char** PixelFormatNames_PVR
345extern const char** PixelFormatNames_ASTC
346extern const char** PixelFormatNames_Vendor
347extern const char** PixelFormatNames_Palette
348const char* tGetPixelFormatName(tPixelFormat); 
349 
350extern const char* PixelFormatDescs[]; 
351extern const char** PixelFormatDescs_Packed
352extern const char** PixelFormatDescs_Block
353extern const char** PixelFormatDescs_PVR
354extern const char** PixelFormatDescs_ASTC
355extern const char** PixelFormatDescs_Vendor
356extern const char** PixelFormatDescs_Palette
357const char* tGetPixelFormatDesc(tPixelFormat); 
358 
359// Gets the pixel format from its name. Case sensitive. Slow. Use for testing/unit-tests only. 
360tPixelFormat tGetPixelFormat(const char* name); 
361 
362 
363// I've decided to put generic aspect ratio stuff in here as well. It doesn't really warrant its own header. This enum 
364// is for commonly encountered aspect ratios on-screen and in print. The name array may be indexed by the enum values. 
365// They are ordered from largest to smallest. 
366enum class tAspectRatio 
367
368 Invalid, // Must be 0. 
369 Free = Invalid
370 First_Valid
371 First_Screen = First_Valid
372 Screen_3_1 = First_Screen, // 3.0 
373 Screen_2_1, // 2.0 
374 Screen_16_9, // 1.7777777 
375 Screen_5_3, // 1.6666666 
376 Screen_16_10, // 1.6 Reduces to 8_5 
377 Screen_8_5, // 1.6 
378 Screen_3_2, // 1.5 
379 Screen_16_11, // 1.4545454 
380 Screen_7_5, // 1.4 
381 Screen_4_3, // 1.3333333 
382 Screen_22_17, // 1.2941176 
383 Screen_14_11, // 1.2727272 
384 Screen_5_4, // 1.25 
385 Screen_1_1, // 1.0 
386 Screen_4_5, // 0.8 
387 Screen_11_14, // 0.7857142 
388 Screen_17_22, // 0.7727272 
389 Screen_3_4, // 0.75 
390 Screen_5_7, // 0.7142857 
391 Screen_11_16, // 0.6875 
392 Screen_2_3, // 0.6666666 
393 Screen_5_8, // 0.625 
394 Screen_10_16, // 0.625 Reduces to 5_8 
395 Screen_3_5, // 0.6 
396 Screen_9_16, // 0.5625 
397 Screen_1_2, // 0.5 
398 Screen_1_3, // 0.3333333 
399 Last_Screen = Screen_1_3
400 NumScreenRatios = Last_Screen
401 
402 // Print sizes listed by lower of the two dimensions and ordered by the lower size. 
403 // L means landscape. 
404 First_Print
405 Print_2x3 = First_Print, // 0.6666666 Same as 2_3. Wallet size. 
406 Print_2x3_L, // 1.5 Same as 3_2. Wallet size. 
407 Print_3x5, // 0.6 Same as 3_5. 
408 Print_3x5_L, // 1.6666666 Same as 5_3. 
409 Print_4x4, // 1.0 Same as 1_1. 
410 Print_4x6, // 0.6666666 Same as 2_3. 
411 Print_4x6_L, // 1.5 Same as 3_2. 
412 Print_5x7, // 0.7142857 Same as 5_7. 
413 Print_5x7_L, // 1.4 Same as 7_5. 
414 Print_5x15, // 0.3333333 Same as 1_3. 
415 Print_5x15_L, // 3.0 Same as 3_1. 
416 Print_8x8, // 1.0 Same as 1_1. 
417 Print_8x10, // 0.8 Same as 4_5. 
418 Print_8x10_L, // 1.25 Same as 5_4. 
419 Print_8x24, // 0.3333333 Same as 1_3. 
420 Print_8x24_L, // 3.0 Same as 3_1. 
421 Print_8p5x11, // 0.7727272 Same as 17_22. 
422 Print_8p5x11_L, // 1.2941176 Same as 22_17. 
423 Print_9x16, // 0.5625 Same as 9_16. 
424 Print_9x16_L, // 1.7777777 Same as 16_9. 
425 Print_11x14, // 0.7857142 Same as 11_14. 
426 Print_11x14_L, // 1.2727272 Same as 14_11. 
427 Print_11x16, // 0.6875 Same as 11_16. 
428 Print_11x16_L, // 1.4545454 Same as 16_11. 
429 Print_12x12, // 1.0 Same as 1_1. 
430 Print_12x18, // 0.6666666 Same as 2_3. 
431 Print_12x18_L, // 1.5 Same as 3_2. 
432 Print_12x36, // 0.3333333 Same as 1_3. 
433 Print_12x36_L, // 3.0 Same as 3_1. 
434 Print_16x20, // 0.8 Same as 4_5. 
435 Print_16x20_L, // 1.25 Same as 5_4. 
436 Print_18x24, // 0.75 Same as 3_4. 
437 Print_18x24_L, // 1.3333333 Same as 4_3. 
438 Print_20x30, // 0.6666666 Same as 2_3. 
439 Print_20x30_L, // 1.5 Same as 3_2. 
440 Print_24x36, // 0.6666666 Same as 2_3. 
441 Print_24x36_L, // 1.5 Same as 3_2. 
442 Last_Print = Print_24x36_L
443 Last_Valid = Last_Print
444 NumRatios, // Including Invalid. 
445 User = NumRatios 
446}; 
447 
448// The 'User' aspect ratio name is included in this array as the last item. 
449extern const char* tAspectRatioNames[int(tAspectRatio::NumRatios)+1]; 
450 
451bool tIsScreenRatio(tAspectRatio); 
452bool tIsPrintRatio(tAspectRatio); 
453bool tisValidRatio(tAspectRatio); 
454 
455// Returns 0.0f for Invalid/Free. Returns -1.0f for User. 
456float tGetAspectRatioFloat(tAspectRatio); 
457 
458// If Invalid/Free/User is passed in, returns false and sets numerator and denominator to 0. 
459// Otherwise returns true and fills in numerator and denominator in reduced form (16:10 -> 8:5). 
460bool tGetAspectRatioFrac(int& numerator, int& denominator, tAspectRatio); 
461 
462// Returns the aspect ratio given numerator and denominator. Returns Invalid if either numerator or denominator 
463// are <= 0. Returns User if the ratio doesn't exist in the enum. Returns the most reduced Screen_ ratio 
464// otherwise. For example tGetAspectRatio(32,20) returns Screen_8_5 rather than Screen_16_10. Does not return 
465// any of the Print_ enumerants. 
466tAspectRatio tGetAspectRatio(int numerator, int denominator); 
467 
468// Gets the most reduced screen enumerant given a valid aspect ratio. Returns Invalid if Invalid passed in. 
469// Returns User if User passed in. The function tReduceAspectRatio does the same thing, just different syntax/calling. 
470tAspectRatio tGetReducedAspectRatio(tAspectRatio); 
471void tReduceAspectRatio(tAspectRatio&); 
472 
473
474 
475 
476// Implementation below this line. 
477 
478 
479inline bool tImage::tIsValidFormat(tPixelFormat format
480
481 return ((format >= tPixelFormat::FirstValid) && (format <= tPixelFormat::LastValid)); 
482
483 
484 
485inline bool tImage::tIsContiguousFormat(tPixelFormat format
486
487 return ((format >= tPixelFormat::FirstContiguous) && (format <= tPixelFormat::LastContiguous)); 
488
489 
490 
491inline bool tImage::tIsPackedFormat(tPixelFormat format
492
493 return ((format >= tPixelFormat::FirstPacked) && (format <= tPixelFormat::LastPacked)); 
494
495 
496 
497inline bool tImage::tIsBCFormat(tPixelFormat format
498
499 return ((format >= tPixelFormat::FirstBC) && (format <= tPixelFormat::LastBC)); 
500
501 
502 
503inline bool tImage::tIsETCFormat(tPixelFormat format
504
505 return ((format >= tPixelFormat::FirstETC) && (format <= tPixelFormat::LastETC)); 
506
507 
508 
509inline bool tImage::tIsEACFormat(tPixelFormat format
510
511 return ((format >= tPixelFormat::FirstEAC) && (format <= tPixelFormat::LastEAC)); 
512
513 
514 
515inline bool tImage::tIsPVRFormat(tPixelFormat format
516
517 return ((format >= tPixelFormat::FirstPVR) && (format <= tPixelFormat::LastPVR)); 
518
519 
520 
521inline bool tImage::tIsASTCFormat(tPixelFormat format
522
523 return ((format >= tPixelFormat::FirstASTC) && (format <= tPixelFormat::LastASTC)); 
524
525 
526 
527inline bool tImage::tIsVendorFormat(tPixelFormat format
528
529 return ((format >= tPixelFormat::FirstVendor) && (format <= tPixelFormat::LastVendor)); 
530
531 
532 
533inline bool tImage::tIsPaletteFormat(tPixelFormat format
534
535 return ((format >= tPixelFormat::FirstPalette) && (format <= tPixelFormat::LastPalette)); 
536
537 
538 
539inline bool tImage::tIsAlphaFormat(tPixelFormat format
540
541 switch (format
542
543 case tPixelFormat::R8G8B8A8
544 case tPixelFormat::B8G8R8A8
545 case tPixelFormat::G4B4A4R4
546 case tPixelFormat::B4A4R4G4
547 case tPixelFormat::G3B5A1R5G2
548 case tPixelFormat::G2B5A1R5G3
549 case tPixelFormat::A8L8
550 case tPixelFormat::R16G16B16A16f
551 case tPixelFormat::R32G32B32A32f
552 case tPixelFormat::R16G16B16A16
553 case tPixelFormat::R32G32B32A32
554 case tPixelFormat::BC1DXT1A
555 case tPixelFormat::BC2DXT2DXT3
556 case tPixelFormat::BC3DXT4DXT5
557 case tPixelFormat::BC7
558 case tPixelFormat::OPENEXR
559 
560 // For palettized the palette may have an entry that can be considered alpha. However for only 1-bit 
561 // palettes we consider it dithered (ColourA/ColourB) and not to have an alpha. 
562 case tPixelFormat::PAL2BIT
563 case tPixelFormat::PAL3BIT
564 case tPixelFormat::PAL4BIT
565 case tPixelFormat::PAL5BIT
566 case tPixelFormat::PAL6BIT
567 case tPixelFormat::PAL7BIT
568 case tPixelFormat::PAL8BIT
569 return true
570
571 
572 // Not quite sure how to handle ASTC formats, but they usually contain an alpha. 
573 if (tIsASTCFormat(format)) 
574 return true
575 
576 // PVR non-HDR formats all support alpha. 
577 if (tIsPVRFormat(format) && tIsLDRFormat(format)) 
578 return true
579 
580 return false
581
582 
583 
584inline bool tImage::tIsOpaqueFormat(tPixelFormat format
585
586 return !tImage::tIsAlphaFormat(format); 
587
588 
589 
590inline bool tImage::tIsHDRFormat(tPixelFormat format
591
592 switch (format
593
594 case tPixelFormat::R16f
595 case tPixelFormat::R16G16f
596 case tPixelFormat::R16G16B16f
597 case tPixelFormat::R16G16B16A16f
598 case tPixelFormat::R32f
599 case tPixelFormat::R32G32f
600 case tPixelFormat::R32G32B32f
601 case tPixelFormat::R32G32B32A32f
602 case tPixelFormat::R11G11B10uf
603 case tPixelFormat::B10G11R11uf
604 case tPixelFormat::R9G9B9E5uf
605 case tPixelFormat::E5B9G9R9uf
606 case tPixelFormat::BC6U
607 case tPixelFormat::BC6S
608 case tPixelFormat::RADIANCE
609 case tPixelFormat::OPENEXR
610 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
611 case tPixelFormat::PVRHDRBPP8: 
612 case tPixelFormat::PVRHDRBPP6: 
613 case tPixelFormat::PVR2HDRBPP8: 
614 case tPixelFormat::PVR2HDRBPP6: 
615 #endif 
616 case tPixelFormat::R8G8B8M8
617 case tPixelFormat::R8G8B8D8
618 return true
619
620 
621 // ASTCNxM can be LDR or HDR, but since they are not guaranteed to be HDR we return false for them. 
622 return false
623
624 
625 
626inline bool tImage::tIsLDRFormat(tPixelFormat format
627
628 return !tImage::tIsHDRFormat(format); 
629
630 
631 
632inline bool tImage::tIsLuminanceFormat(tPixelFormat format
633
634 switch (format
635
636 case tPixelFormat::L8
637 case tPixelFormat::R8
638 case tPixelFormat::R16
639 case tPixelFormat::R32
640 case tPixelFormat::R16f
641 case tPixelFormat::R32f
642 case tPixelFormat::BC4ATI1U
643 case tPixelFormat::BC4ATI1S
644 case tPixelFormat::EACR11U
645 case tPixelFormat::EACR11S
646 return true
647
648 
649 return false
650
651 
652 
653inline int tImage::tGetNumBlocks(int blockWH, int imageWH
654
655 tAssert(blockWH > 0); 
656 return (imageWH + blockWH - 1) / blockWH
657
658 
659 
660inline bool tImage::tIsScreenRatio(tAspectRatio ratio
661
662 return (int(ratio) >= int(tAspectRatio::First_Screen)) && (int(ratio) <= int(tAspectRatio::Last_Screen)); 
663
664 
665 
666inline bool tImage::tIsPrintRatio(tAspectRatio ratio
667
668 return (int(ratio) >= int(tAspectRatio::First_Print)) && (int(ratio) <= int(tAspectRatio::Last_Print)); 
669
670 
671 
672inline bool tImage::tisValidRatio(tAspectRatio ratio
673
674 return (int(ratio) >= int(tAspectRatio::First_Valid)) && (int(ratio) <= int(tAspectRatio::Last_Valid)); 
675
676 
677 
678inline void tImage::tReduceAspectRatio(tAspectRatio& aspect
679
680 aspect = tGetReducedAspectRatio(aspect); 
681
682 
683 
684inline float tImage::tGetAspectRatioFloat(tAspectRatio aspect
685
686 tReduceAspectRatio(aspect); 
687 switch (aspect
688
689 case tAspectRatio::Invalid: return 0.0f
690 case tAspectRatio::User: return -1.0f
691
692 
693 int numerator, denominator
694 bool ok = tGetAspectRatioFrac(numerator, denominator, aspect); 
695 if (!ok
696 return 0.0f
697 
698 return float(numerator) / float(denominator); 
699
700