1// tPixelFormat.cpp 
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, 2021-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#include <Foundation/tAssert.h> 
17#include <Foundation/tStandard.h> 
18#include <Foundation/tFundamentals.h> 
19#include "Image/tPixelFormat.h" 
20 
21 
22namespace tImage 
23
24 const char* PixelFormatNames[] = 
25
26 // Packed formats. 
27 "R8"
28 "R8G8"
29 "R8G8B8"
30 "R8G8B8A8"
31 "B8G8R8"
32 "B8G8R8A8"
33 "G3B5R5G3"
34 "G4B4A4R4"
35 "B4A4R4G4"
36 "G3B5A1R5G2"
37 "G2B5A1R5G3"
38 "L8A8"
39 "A8"
40 "L8"
41 "R16"
42 "R16G16"
43 "R16G16B16"
44 "R16G16B16A16"
45 "R32"
46 "R32G32"
47 "R32G32B32"
48 "R32G32B32A32"
49 "R16f"
50 "R16G16f"
51 "R16G16B16f"
52 "R16G16B16A16f"
53 "R32f"
54 "R32G32f"
55 "R32G32B32f"
56 "R32G32B32A32f"
57 "R11G11B10uf"
58 "B10G11R11uf"
59 "R9G9B9E5uf"
60 "E5B9G9R9uf"
61 "R8G8B8M8"
62 "R8G8B8D8"
63 
64 // Original BC (4x4 Block Compression) formats. 
65 "BC1DXT1"
66 "BC1DXT1A"
67 "BC2DXT2DXT3"
68 "BC3DXT4DXT5"
69 "BC4ATI1U"
70 "BC4ATI1S"
71 "BC5ATI2U"
72 "BC5ATI2S"
73 "BC6U"
74 "BC6S"
75 "BC7"
76 "ETC1"
77 "ETC2RGB"
78 "ETC2RGBA"
79 "ETC2RGBA1"
80 "EACR11U"
81 "EACR11S"
82 "EACRG11U"
83 "EACRG11S"
84 
85 // PVR (Power VR by Imagination) formats. 
86 "PVRBPP4"
87 "PVRBPP2"
88 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
89 "PVRHDRBPP8"
90 "PVRHDRBPP6"
91 "PVR2BPP4"
92 "PVR2BPP2"
93 "PVR2HDRBPP8"
94 "PVR2HDRBPP6"
95 #endif 
96 
97 // ASTC (Adaptive Scalable Texture Compression) formats. 
98 "ASTC4X4"
99 "ASTC5X4"
100 "ASTC5X5"
101 "ASTC6X5"
102 "ASTC6X6"
103 "ASTC8X5"
104 "ASTC8X6"
105 "ASTC8X8"
106 "ASTC10X5"
107 "ASTC10X6"
108 "ASTC10X8"
109 "ASTC10X10"
110 "ASTC12X10"
111 "ASTC12X12"
112  
113 // Vendor-specific formats. 
114 "RADIANCE"
115 "OPENEXR"
116 
117 // Palette formats. 
118 "PAL1BIT"
119 "PAL2BIT"
120 "PAL3BIT"
121 "PAL4BIT"
122 "PAL5BIT"
123 "PAL6BIT"
124 "PAL7BIT"
125 "PAL8BIT" 
126 }; 
127 tStaticAssert(int(tPixelFormat::NumPixelFormats) == tNumElements(PixelFormatNames)); 
128 const char** PixelFormatNames_Packed = &PixelFormatNames[int(tPixelFormat::FirstPacked)]; 
129 const char** PixelFormatNames_Block = &PixelFormatNames[int(tPixelFormat::FirstBC)]; 
130 const char** PixelFormatNames_PVR = &PixelFormatNames[int(tPixelFormat::FirstPVR)]; 
131 const char** PixelFormatNames_ASTC = &PixelFormatNames[int(tPixelFormat::FirstASTC)]; 
132 const char** PixelFormatNames_Vendor = &PixelFormatNames[int(tPixelFormat::FirstVendor)]; 
133 const char** PixelFormatNames_Palette = &PixelFormatNames[int(tPixelFormat::FirstPalette)]; 
134 
135 
136 const char* PixelFormatDescs[] = 
137
138 // Packed formats. 
139 "R8 : 8 bit. Unsigned representing red. Some file-types that\n" 
140 "don't support A8 or L8 (eg. ktx2) will use this instead."
141 
142 "R8G8 : 16 bit. Unsigned representing red and green.\n" 
143 "Vulkan has an analagous format."
144 
145 "R8G8B8 : 24 bit. Full colour. No alpha. Matches GL_RGB source\n" 
146 "ordering. Not efficient. Most drivers will swizzle to BGR."
147 
148 "R8G8B8A8 : 32 bit. Full alpha. Matches GL_RGBA source ordering.\n" 
149 "Not efficient. Most drivers will swizzle to ABGR."
150 
151 "B8G8R8 : 24 bit. Full colour. No alpha. Matches GL_BGR source\n" 
152 "ordering. Efficient. Most drivers do not need to swizzle."
153 
154 "B8G8R8A8 : 32 bit. Full alpha. Matches GL_BGRA source ordering.\n" 
155 "Most drivers do not need to swizzle."
156 
157 "G3B5R5G3 : 16 bit. No alpha. Also known as B5G6R5.\n" 
158 "G3B5R5G3 ."
159 
160 "G4B4A4R4 : 16 bit. 12 colour bits. 4 bit alpha.\n" 
161 "Also known as B4G4R4A4. G4B4A4R4 is the in-memory layout."
162 
163 "B4A4R4G4 : 16 bit. 12 colour bits. 4 bit alpha.\n" 
164 "Also known as R4G4B4A4. B4A4R4G4 is the in-memory layout."
165 
166 "G3B5A1R5G2 : 16 bit. 15 colour bits. Binary alpha.\n" 
167 "Also known as B5G5R5A1. G3B5A1R5G2 is the in-memory layout."
168 
169 "G2B5A1R5G3 : 16 bit. 15 colour bits. Binary alpha.\n" 
170 "Also known as R5G5B5A1. G2B5A1R5G3 is the in-memory layout."
171 
172 "L8A8 : 16 bit. Alpha and Luminance."
173 "A8 : 8 bit. Alpha only."
174 "L8 : 8 bit. Luminance only."
175 "R16 : 16 bit. Red channel only."
176 "R16G16 : 32 bit. 16 bit R. 16 bit G."
177 "R16G16B16 : 48 bit. 16 bit each RGB."
178 "R16G16B16A16 : 64 bit. 16 bit each RGBA."
179 
180 "R32 : 32 bit. Red channel only."
181 "R32G32 : 64 bit. 32 bit R. 32 bit G."
182 "R32G32B32 : 96 bit. 32 bit each RGB."
183 "R32G32B32A32 : 128 bit. 32 bit each RGBA."
184 
185 "R16f : 16 bit. Half-float red/luminance channel only.\n" 
186 "HDR linear space."
187 
188 "R16G16f : 32 bit. Two half-floats per pixel. RG.\n" 
189 "HDR linear space."
190 
191 "R16G16B16f : 48 bit. Three half-floats per pixel. RGB.\n" 
192 "HDR linear space."
193 
194 "R16G16B16A16f : 64 bit. Four half-floats per pixel. RGBA.\n" 
195 "HDR linear space."
196 
197 "R32f : 32 bit. Float red/luminance channel only.\n" 
198 "HDR linear space."
199 
200 "R32G32f : 64 bit. Two floats per pixel. RG.\n" 
201 "HDR linear space."
202 
203 "R32G32B32f : 96 bit. Three floats per pixel. RGB.\n" 
204 "HDR linear space."
205 
206 "R32G32B32A32f : 128 bit. Four floats per pixel. RGBA.\n" 
207 "HDR linear space."
208 
209 "R11G11B10uf : 32 bit. Unsigned 11-bit floats for RG, and\n" 
210 "a 10-bit float for B. All use a 5-bit exponent."
211 
212 "B10G11R11uf : 32 bit. Unsigned 10-bit floats for B, and 11-bit\n" 
213 "floats for GR. All use a 5-bit exponent."
214 
215 "R9G9B9E5uf : 32 bit. Unsigned 14-bit floats for RGB. Always\n" 
216 "denorm and each share the same 5-bit exponent."
217 
218 "E5B9G9R9uf : 32 bit. Unsigned 14-bit floats for RGB. Always\n" 
219 "denorm and each share the same 5-bit exponent."
220 
221 "R8G8B8M8 : 32 bit. Poor-man's HDR. RGB plus shared 8-bit\n" 
222 "multiplier. Must supply MaxRange when decoding."
223 
224 "R8G8B8D8 : 32 bit. Poor-man's HDR. RGB plus shared 8-bit\n" 
225 "divisor. Must supply MaxRange when decoding."
226 
227 // Original BC (4x4 Block Compression) formats. 
228 "BC1DXT1 : BC 1, DXT1. No alpha."
229 "BC1DXT1A :BC 1, DXT1. Binary alpha."
230 
231 "BC2DXT2DXT3 : BC 2. DXT2 (premult-alpha) and DXT3 share the same\n" 
232 "format. Large alpha gradients (alpha banding)."
233 
234 "BC3DXT4DXT5 : BC 3. DXT4 (premult-alpha) and DXT5 share the same\n" 
235 "format. Variable alpha (smooth)."
236 
237 "BC4ATI1U : BC 4. Unsigned. One colour channel only.\n" 
238 "May not be HW supported."
239 
240 "BC4ATI1S : BC 4. Signed. One colour channel only.\n" 
241 "May not be HW supported."
242 
243 "BC5ATI2U : BC 5. Unsigned. Two colour channels only.\n" 
244 "May not be HW supported."
245 
246 "BC5ATI2S : BC 5. Signed. Two colour channels only.\n" 
247 "May not be HW supported."
248 
249 "BC6U : BC 6 HDR. No alpha. 3 x 16bit unsigned half-floats per pixel."
250 "BC6S : BC 6 HDR. No alpha. 3 x 16bit signed half-floats per pixel."
251 "BC7 : BC 7. Full colour. Variable alpha 0 to 8 bits."
252 
253 "ETC1 : Ericsson Texture Compression. Similar to BC1. RGB-only. No alpha."
254 
255 "ETC2RGB : ETC2. Backwards compatible with ETC1.\n" 
256 "The pixels may be in the sRGB colour space."
257 
258 "ETC2RGBA : ETC2. RGBA.\n" 
259 "The pixels may be in the sRGB colour space."
260 
261 "ETC2RGBA1 : ETC2. RGB with binary alpha.\n" 
262 "The pixels may be in the sRGB colour space."
263  
264 "EACR11U : EAC R11. Ericsson. Single channel unsigned."
265 "EACR11S : EAC R11. Ericsson. Single channel signed."
266 "EACRG11U : EAC R11G11. Ericsson. Two channel unsigned."
267 "EACRG11S : EAC R11G11. Ericsson. Two channel signed."
268 
269 // PVR (Power VR by Imagination) formats. 
270 "PVRBPP4 : PVRTC Version 1. 4BPP representing RGB or RGBA channels. One block\n" 
271 "can encode 4x4 pixels but needs access to adjacent blocks during decompress."
272 
273 "PVRBPP2 : PVRTC Version 1. 2BPP representing RGB or RGBA channels. One block\n" 
274 "can encode 8x4 pixels but needs access to adjacent blocks during decompress."
275 
276 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
277 "PVRHDRBPP8 : PVRTC Version 1. 8BPP representing HDR RGB."
278 "PVRHDRBPP6 : PVRTC Version 1. 6BPP representing HDR RGB."
279 "PVR2BPP4 : PVRTC Version 2. 4BPP representing RGB or RGBA channels."
280 "PVR2BPP2 : PVRTC Version 2. 2BPP representing RGB or RGBA channels."
281 "PVR2HDRBPP8 : PVRTC Version 2. 8BPP representing HDR RGB."
282 "PVR2HDRBPP6 : PVRTC Version 2. 6BPP representing HDR RGB."
283 #endif 
284 
285 // ASTC (Adaptive Scalable Texture Compression) formats. 
286 "ASTC4X4 : Adaptive scalable. 128 bits per 16 pixels. 8.0 bpp."
287 "ASTC5X4 : Adaptive scalable. 128 bits per 20 pixels. 6.4 bpp."
288 "ASTC5X5 : Adaptive scalable. 128 bits per 25 pixels. 5.12 bpp."
289 "ASTC6X5 : Adaptive scalable. 128 bits per 30 pixels. 4.27 bpp."
290 "ASTC6X6 : Adaptive scalable. 128 bits per 36 pixels. 3.56 bpp."
291 "ASTC8X5 : Adaptive scalable. 128 bits per 40 pixels. 3.2 bpp."
292 "ASTC8X6 : Adaptive scalable. 128 bits per 48 pixels. 2.67 bpp."
293 "ASTC8X8 : Adaptive scalable. 128 bits per 64 pixels. 2.56 bpp."
294 "ASTC10X5 : Adaptive scalable. 128 bits per 50 pixels. 2.13 bpp."
295 "ASTC10X6 : Adaptive scalable. 128 bits per 60 pixels. 2.0 bpp."
296 "ASTC10X8 : Adaptive scalable. 128 bits per 80 pixels. 1.6 bpp."
297 "ASTC10X10 : Adaptive scalable. 128 bits per 100 pixels. 1.28 bpp."
298 "ASTC12X10 : Adaptive scalable. 128 bits per 120 pixels. 1.07 bpp."
299 "ASTC12X12 : Adaptive scalable. 128 bits per 144 pixels. 0.89 bpp."
300  
301 // Vendor-specific formats. 
302 "RADIANCE : Radiance HDR"
303 "OPENEXR : OpenEXR HDR"
304 
305 // Palette formats. 
306 "PAL1BIT : 1-bit indexes to a palette. 2 colour. 1 bpp. Often dithered B/W."
307 "PAL2BIT : 2-bit indexes to a palette. 4 colour. 2 bpp."
308 "PAL3BIT : 3-bit indexes to a palette. 8 colour. 3 bpp."
309 "PAL4BIT : 4-bit indexes to a palette. 16 colour. 4 bpp."
310 "PAL5BIT : 5-bit indexes to a palette. 32 colour. 5 bpp."
311 "PAL6BIT : 6-bit indexes to a palette. 64 colour. 6 bpp."
312 "PAL7BIT : 7-bit indexes to a palette. 128 colour. 7 bpp."
313 "PAL8BIT : 8-bit indexes to a palette. 256 colour. 8 bpp." 
314 }; 
315 tStaticAssert(int(tPixelFormat::NumPixelFormats) == tNumElements(PixelFormatDescs)); 
316 const char** PixelFormatDescs_Packed = &PixelFormatDescs[int(tPixelFormat::FirstPacked)]; 
317 const char** PixelFormatDescs_Block = &PixelFormatDescs[int(tPixelFormat::FirstBC)]; 
318 const char** PixelFormatDescs_PVR = &PixelFormatDescs[int(tPixelFormat::FirstPVR)]; 
319 const char** PixelFormatDescs_ASTC = &PixelFormatDescs[int(tPixelFormat::FirstASTC)]; 
320 const char** PixelFormatDescs_Vendor = &PixelFormatDescs[int(tPixelFormat::FirstVendor)]; 
321 const char** PixelFormatDescs_Palette = &PixelFormatDescs[int(tPixelFormat::FirstPalette)]; 
322 
323 int PackedFormat_BitsPerPixel[] = 
324
325 8, // R8 
326 16, // R8G8 
327 24, // R8G8B8 
328 32, // R8G8B8A8 
329 24, // B8G8R8 
330 32, // B8G8R8A8 
331 
332 16, // G3B5R5G3 
333 16, // G4B4A4R4 
334 16, // B4A4R4G4 
335 16, // G3B5A1R5G2 
336 16, // G2B5A1R5G3 
337 16, // A8L8 
338 8, // A8 
339 8, // L8 
340 16, // R16 
341 32, // R16G16 
342 48, // R16G16B16 
343 64, // R16G16B16A16 
344 32, // R32 
345 64, // R32G32 
346 96, // R32G32B32 
347 128, // R32G32B32A32 
348 16, // R16f 
349 32, // R16G16f 
350 48, // R16G16B16f 
351 64, // R16G16B16A16f 
352 32, // R32f 
353 64, // R32G32f 
354 96, // R32G32B32f 
355 128, // R32G32B32A32f 
356 32, // R11G11B10uf 
357 32, // B10G11R11uf 
358 32, // R9G9B9E5uf 
359 32, // E5B9G9R9uf 
360 32, // R8G8B8M8 
361 32 // R8G8B8D8 
362 }; 
363 tStaticAssert(tNumElements(PackedFormat_BitsPerPixel) == int(tPixelFormat::NumPackedFormats)); 
364 
365 int BCFormat_BytesPerBlock[] = 
366
367 8, // BC1DXT1 
368 8, // BC1DXT1A 
369 16, // BC2DXT2DXT3 
370 16, // BC3DXT4DXT5 
371 8, // BC4ATI1U 
372 8, // BC4ATI1S 
373 16, // BC5ATI2U 
374 16, // BC5ATI2S 
375 16, // BC6U 
376 16, // BC6S 
377 16, // BC7 
378 8, // ETC1 
379 8, // ETC2RGB 
380 16, // ETC2RGBA 
381 8, // ETC2RGBA1 
382 8, // EACR11U 
383 8, // EACR11S 
384 16, // EACRG11U 
385 16 // EACRG11S 
386 }; 
387 tStaticAssert(tNumElements(BCFormat_BytesPerBlock) == int(tPixelFormat::NumBCFormats)); 
388 
389 int PVRFormat_BlockWidth[] = 
390
391 4, // PVRBPP4 
392 8, // PVRBPP2 
393 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
394 0, // PVRHDRBPP8. Unknown block size. 
395 0, // PVRHDRBPP6. Unknown block size. 
396 4, // PVR2BPP4 
397 8, // PVR2BPP2 
398 0, // PVR2HDRBPP8. Unknown block size. 
399 0 // PVR2HDRBPP6. Unknown block size. 
400 #endif 
401 }; 
402 tStaticAssert(tNumElements(PVRFormat_BlockWidth) == int(tPixelFormat::NumPVRFormats)); 
403 
404 int PVRFormat_BlockHeight[] = 
405
406 4, // PVRBPP4 
407 4, // PVRBPP2 
408 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
409 0, // PVRHDRBPP8. Unknown block size. 
410 0, // PVRHDRBPP6. Unknown block size. 
411 4, // PVR2BPP4 
412 4, // PVR2BPP2 
413 0, // PVR2HDRBPP8. Unknown block size. 
414 0 // PVR2HDRBPP6. Unknown block size. 
415 #endif 
416 }; 
417 tStaticAssert(tNumElements(PVRFormat_BlockHeight) == int(tPixelFormat::NumPVRFormats)); 
418 
419 int ASTCFormat_BlockWidth[] = 
420
421 4, // ASTC4X4 
422 5, // ASTC5X4 
423 5, // ASTC5X5 
424 6, // ASTC6X5 
425 6, // ASTC6X6 
426 8, // ASTC8X5 
427 8, // ASTC8X6 
428 8, // ASTC8X8 
429 10, // ASTC10X5 
430 10, // ASTC10X6 
431 10, // ASTC10X8 
432 10, // ASTC10X10 
433 12, // ASTC12X10 
434 12 // ASTC12X12 
435 }; 
436 tStaticAssert(tNumElements(ASTCFormat_BlockWidth) == int(tPixelFormat::NumASTCFormats)); 
437 
438 int ASTCFormat_BlockHeight[] = 
439
440 4, // ASTC4X4 
441 4, // ASTC5X4 
442 5, // ASTC5X5 
443 5, // ASTC6X5 
444 6, // ASTC6X6 
445 5, // ASTC8X5 
446 6, // ASTC8X6 
447 8, // ASTC8X8 
448 5, // ASTC10X5 
449 6, // ASTC10X6 
450 8, // ASTC10X8 
451 10, // ASTC10X10 
452 10, // ASTC12X10 
453 12 // ASTC12X12 
454 }; 
455 tStaticAssert(tNumElements(ASTCFormat_BlockHeight) == int(tPixelFormat::NumASTCFormats)); 
456 
457 int PVRFormat_BitsPerPixel[] = 
458
459 4, // PVRBPP4 
460 2, // PVRBPP2 
461 #ifdef PIXEL_FORMAT_INCLUDE_NOT_IMPLEMENTED 
462 8, // PVRHDRBPP8 
463 6, // PVRHDRBPP6 
464 4, // PVR2BPP4 
465 2, // PVR2BPP2 
466 8, // PVR2HDRBPP8 
467 6, // PVR2HDRBPP6 
468 #endif 
469 }; 
470 tStaticAssert(tNumElements(PVRFormat_BitsPerPixel) == int(tPixelFormat::NumPVRFormats)); 
471 
472 int VendorFormat_BitsPerPixel[] = 
473
474 32, // Radiance. 3 bytes for each RGB. 1 byte shared exponent. 
475 128 // OpenEXR. @todo There are multiple exr pixel formats. We don't yet determine which one. 
476 }; 
477 tStaticAssert(tNumElements(VendorFormat_BitsPerPixel) == int(tPixelFormat::NumVendorFormats)); 
478 
479 int PaletteFormat_BitsPerPixel[] = 
480
481 1
482 2
483 3
484 4
485 5
486 6
487 7
488 8 
489 }; 
490 tStaticAssert(tNumElements(PaletteFormat_BitsPerPixel) == int(tPixelFormat::NumPaletteFormats)); 
491
492 
493 
494int tImage::tGetBlockWidth(tPixelFormat format
495
496 if (tIsPackedFormat(format) || tIsVendorFormat(format) || tIsPaletteFormat(format)) 
497 return 1
498 
499 if (tIsBCFormat(format)) 
500 return 4
501 
502 // ASTC and PVR formats have different widths depending on format. 
503 if (tIsPVRFormat(format)) 
504 return PVRFormat_BlockWidth[int(format) - int(tPixelFormat::FirstPVR)]; 
505 
506 if (tIsASTCFormat(format)) 
507 return ASTCFormat_BlockWidth[int(format) - int(tPixelFormat::FirstASTC)]; 
508 
509 return 0
510
511 
512 
513int tImage::tGetBlockHeight(tPixelFormat format
514
515 if (tIsPackedFormat(format) || tIsVendorFormat(format) || tIsPaletteFormat(format)) 
516 return 1
517 
518 if (tIsBCFormat(format)) 
519 return 4
520 
521 // ASTC and PVR formats have different heights depending on format. 
522 if (tIsPVRFormat(format)) 
523 return PVRFormat_BlockHeight[int(format) - int(tPixelFormat::FirstPVR)]; 
524 
525 if (tIsASTCFormat(format)) 
526 return ASTCFormat_BlockHeight[int(format) - int(tPixelFormat::FirstASTC)]; 
527 
528 return 0
529
530 
531 
532int tImage::tGetBitsPerPixel(tPixelFormat format
533
534 if (tIsPackedFormat(format)) 
535 return PackedFormat_BitsPerPixel[int(format) - int(tPixelFormat::FirstPacked)]; 
536 
537 if (tIsBCFormat(format)) 
538 return (8*tGetBytesPerBlock(format)) >> 4
539 
540 if (tIsPVRFormat(format)) 
541 return PVRFormat_BitsPerPixel[int(format) - int(tPixelFormat::FirstPVR)]; 
542 
543 if (tIsVendorFormat(format)) 
544 return VendorFormat_BitsPerPixel[int(format) - int(tPixelFormat::FirstVendor)]; 
545 
546 if (tIsPaletteFormat(format)) 
547 return PaletteFormat_BitsPerPixel[int(format) - int(tPixelFormat::FirstPalette)]; 
548  
549 return 0
550
551 
552 
553float tImage::tGetBitsPerPixelFloat(tPixelFormat format
554
555 int bitsPerPixel = tGetBitsPerPixel(format); 
556 if (bitsPerPixel
557 return float(bitsPerPixel); 
558 
559 int pixelsPerBlock = tGetBlockWidth(format) * tGetBlockHeight(format); 
560 int bitsPerBlock = tGetBytesPerBlock(format) * 8
561 return float(bitsPerBlock) / float(pixelsPerBlock); 
562
563 
564 
565int tImage::tGetBytesPerBlock(tPixelFormat format
566
567 if (tIsBCFormat(format)) 
568 return BCFormat_BytesPerBlock[int(format) - int(tPixelFormat::FirstBC)]; 
569 
570 if (tIsPVRFormat(format) && tIsLDRFormat(format)) 
571 return 8
572 
573 if (tIsASTCFormat(format)) 
574 return 16
575 
576 if (tIsPackedFormat(format)) 
577 return tGetBitsPerPixel(format) / 8
578 
579 return 0
580
581 
582 
583int tImage::tGetNumMipmapLevels(int width, int height
584
585 if ((width < 1) || (height < 1)) 
586 return 0
587 
588 int maxDim = tMath::tMax(a: width, b: height);  
589 return tMath::tLog2(x: maxDim) + 1
590
591 
592 
593int tImage::tGetNextMipmapLevelDim(int widthOrHeight
594
595 if (widthOrHeight <= 0
596 return 0
597 if (widthOrHeight == 1
598 return 1
599 return widthOrHeight >> 1
600
601 
602 
603void tImage::tGetNextMipmapLevelDims(int& width, int& height
604
605 width = tGetNextMipmapLevelDim(widthOrHeight: width); 
606 height = tGetNextMipmapLevelDim(widthOrHeight: height); 
607
608 
609 
610int tImage::tGetMipmapDim(int widthOrHeight, int level
611
612 if (widthOrHeight <= 0
613 return 0
614 if (level < 0
615 return widthOrHeight
616 int dim = widthOrHeight >> level
617 if (dim <= 0
618 dim = 1
619 return dim
620
621 
622 
623void tImage::tGetMipmapDims(int& width, int& height, int level
624
625 width = tGetMipmapDim(widthOrHeight: width, level); 
626 height = tGetMipmapDim(widthOrHeight: height, level); 
627
628 
629 
630void tImage::tGetMipmapDims(int& mipWidth, int& mipHeight, int width, int height, int level
631
632 mipWidth = tGetMipmapDim(widthOrHeight: width, level); 
633 mipHeight = tGetMipmapDim(widthOrHeight: height, level); 
634
635 
636 
637const char* tImage::tGetPixelFormatName(tPixelFormat fmt
638
639 if (!tIsValidFormat(format: fmt)) 
640 return "Unknown"
641 return PixelFormatNames[int(fmt)]; 
642
643 
644 
645const char* tImage::tGetPixelFormatDesc(tPixelFormat fmt
646
647 if (!tIsValidFormat(format: fmt)) 
648 return "Unknown"
649 return PixelFormatDescs[int(fmt)]; 
650
651 
652 
653tImage::tPixelFormat tImage::tGetPixelFormat(const char* name
654
655 if (!name || (name[0] == '\0')) 
656 return tPixelFormat::Invalid
657 
658 for (int p = 0; p < int(tPixelFormat::NumPixelFormats); p++) 
659 if (tStd::tStrcmp(a: PixelFormatNames[p], b: name) == 0
660 return tPixelFormat(p); 
661 
662 return tPixelFormat::Invalid
663
664 
665 
666const char* tImage::tAspectRatioNames[int(tAspectRatio::NumRatios)+1] = 
667
668 "Free"
669 
670 "3 : 1"
671 "2 : 1"
672 "16 : 9"
673 "5 : 3"
674 "16 : 10"
675 "8 : 5"
676 "3 : 2"
677 "16 : 11"
678 "7 : 5"
679 "4 : 3"
680 "22 : 17"
681 "14 : 11"
682 "5 : 4"
683 
684 "1 : 1"
685 
686 "4 : 5"
687 "11 : 14"
688 "17 : 22"
689 "3 : 4"
690 "5 : 7"
691 "11 : 16"
692 "2 : 3"
693 "5 : 8"
694 "10 : 16"
695 "3 : 5"
696 "9 : 16"
697 "1 : 2"
698 "1 : 3"
699 
700 "Print 2x3", "Print 2x3L"
701 "Print 3x5", "Print 3x5L"
702 "Print 4x4"
703 "Print 4x6", "Print 4x6L"
704 "Print 5x7", "Print 5x7L"
705 "Print 5x15", "Print 5x15L"
706 "Print 8x8"
707 "Print 8x10", "Print 8x10L"
708 "Print 8x24", "Print 8x24L"
709 "Print 8.5x11", "Print 8.5x11L"
710 "Print 9x16", "Print 9x16L"
711 "Print 11x14", "Print 11x14L"
712 "Print 11x16", "Print 11x16L"
713 "Print 12x12"
714 "Print 12x18", "Print 12x18L"
715 "Print 12x36", "Print 12x36L"
716 "Print 16x20", "Print 16x20L"
717 "Print 18x24", "Print 18x24L"
718 "Print 20x30", "Print 20x30L"
719 "Print 24x36", "Print 24x36L"
720 
721 "User" 
722}; 
723 
724 
725tImage::tAspectRatio tImage::tGetReducedAspectRatio(tAspectRatio aspect
726
727 switch (aspect
728
729 case tAspectRatio::Screen_16_10: return tAspectRatio::Screen_8_5
730 case tAspectRatio::Screen_10_16: return tAspectRatio::Screen_5_8
731 
732 case tAspectRatio::Print_2x3: return tAspectRatio::Screen_2_3
733 case tAspectRatio::Print_2x3_L: return tAspectRatio::Screen_3_2
734 case tAspectRatio::Print_3x5: return tAspectRatio::Screen_3_5
735 case tAspectRatio::Print_3x5_L: return tAspectRatio::Screen_5_3
736 case tAspectRatio::Print_4x4: return tAspectRatio::Screen_1_1
737 case tAspectRatio::Print_4x6: return tAspectRatio::Screen_2_3
738 case tAspectRatio::Print_4x6_L: return tAspectRatio::Screen_3_2
739 case tAspectRatio::Print_5x7: return tAspectRatio::Screen_5_7
740 case tAspectRatio::Print_5x7_L: return tAspectRatio::Screen_7_5
741 case tAspectRatio::Print_5x15: return tAspectRatio::Screen_1_3
742 case tAspectRatio::Print_5x15_L: return tAspectRatio::Screen_3_1
743 case tAspectRatio::Print_8x8: return tAspectRatio::Screen_1_1
744 case tAspectRatio::Print_8x10: return tAspectRatio::Screen_4_5
745 case tAspectRatio::Print_8x10_L: return tAspectRatio::Screen_5_4
746 case tAspectRatio::Print_8x24: return tAspectRatio::Screen_1_3
747 case tAspectRatio::Print_8x24_L: return tAspectRatio::Screen_3_1
748 case tAspectRatio::Print_8p5x11: return tAspectRatio::Screen_17_22
749 case tAspectRatio::Print_8p5x11_L: return tAspectRatio::Screen_22_17
750 case tAspectRatio::Print_9x16: return tAspectRatio::Screen_9_16
751 case tAspectRatio::Print_9x16_L: return tAspectRatio::Screen_16_9
752 case tAspectRatio::Print_11x14: return tAspectRatio::Screen_11_14
753 case tAspectRatio::Print_11x14_L: return tAspectRatio::Screen_14_11
754 case tAspectRatio::Print_11x16: return tAspectRatio::Screen_11_16
755 case tAspectRatio::Print_11x16_L: return tAspectRatio::Screen_16_11
756 case tAspectRatio::Print_12x12: return tAspectRatio::Screen_1_1
757 case tAspectRatio::Print_12x18: return tAspectRatio::Screen_2_3
758 case tAspectRatio::Print_12x18_L: return tAspectRatio::Screen_3_2
759 case tAspectRatio::Print_12x36: return tAspectRatio::Screen_1_3
760 case tAspectRatio::Print_12x36_L: return tAspectRatio::Screen_3_1
761 case tAspectRatio::Print_16x20: return tAspectRatio::Screen_4_5
762 case tAspectRatio::Print_16x20_L: return tAspectRatio::Screen_5_4
763 case tAspectRatio::Print_18x24: return tAspectRatio::Screen_3_4
764 case tAspectRatio::Print_18x24_L: return tAspectRatio::Screen_4_3
765 case tAspectRatio::Print_20x30: return tAspectRatio::Screen_2_3
766 case tAspectRatio::Print_20x30_L: return tAspectRatio::Screen_3_2
767 case tAspectRatio::Print_24x36: return tAspectRatio::Screen_2_3
768 case tAspectRatio::Print_24x36_L: return tAspectRatio::Screen_3_2
769 
770 // Handles no reduction, Invalid, and User. 
771 default: return aspect
772
773 
774 // We'll never get here. 
775 return tAspectRatio::Invalid
776
777 
778 
779namespace tImage 
780
781 struct tAspectFrac { int Num; int Den; }; 
782 static tAspectFrac tAspectRatioTable[int(tAspectRatio::NumScreenRatios)] = 
783
784 { .Num: 3, .Den: 1 }, 
785 { .Num: 2, .Den: 1 }, 
786 { .Num: 16, .Den: 9 }, 
787 { .Num: 5, .Den: 3 }, 
788 { .Num: 8, .Den: 5 }, // Unused. 
789 { .Num: 8, .Den: 5 }, 
790 { .Num: 3, .Den: 2 }, 
791 { .Num: 16, .Den: 11 }, 
792 { .Num: 7, .Den: 5 }, 
793 { .Num: 4, .Den: 3 }, 
794 { .Num: 22, .Den: 17 }, 
795 { .Num: 14, .Den: 11 }, 
796 { .Num: 5, .Den: 4 }, 
797 
798 { .Num: 1, .Den: 1 }, 
799 
800 { .Num: 4, .Den: 5 }, 
801 { .Num: 11, .Den: 14 }, 
802 { .Num: 17, .Den: 22 }, 
803 { .Num: 3, .Den: 4 }, 
804 { .Num: 5, .Den: 7 }, 
805 { .Num: 11, .Den: 16 }, 
806 { .Num: 2, .Den: 3 }, 
807 { .Num: 5, .Den: 8 }, 
808 { .Num: 5, .Den: 8 }, // Unused. 
809 { .Num: 3, .Den: 5 }, 
810 { .Num: 9, .Den: 16 }, 
811 { .Num: 1, .Den: 2 }, 
812 { .Num: 1, .Den: 3
813 }; 
814
815 
816 
817bool tImage::tGetAspectRatioFrac(int& numerator, int& denominator, tAspectRatio aspect
818
819 switch (aspect
820
821 case tAspectRatio::Invalid
822 case tAspectRatio::User
823 numerator = 0
824 denominator = 0
825 return false
826
827 tReduceAspectRatio(aspect); 
828 
829 tAspectFrac& frac = tAspectRatioTable[int(aspect)-1]; 
830 numerator = frac.Num
831 denominator = frac.Den
832 return true
833
834 
835 
836tImage::tAspectRatio tImage::tGetAspectRatio(int numerator, int denominator
837
838 if ((numerator <= 0) || (denominator <= 0)) 
839 return tAspectRatio::Invalid
840 
841 // Next we need to reduce the fraction. 
842 int gcd = tMath::tGreatestCommonDivisor(a: numerator, b: denominator); 
843 numerator /= gcd
844 denominator /= gcd
845 
846 // Now we look for it. 
847 int foundIndex = -1
848 for (int i = 0; i < int(tAspectRatio::NumScreenRatios); i++) 
849
850 tAspectFrac& frac = tAspectRatioTable[i]; 
851 if ((frac.Num == numerator) && (frac.Den == denominator)) 
852
853 foundIndex = i
854 break
855
856
857 
858 if (foundIndex == -1)  
859 return tAspectRatio::User
860 
861 return tAspectRatio(foundIndex + 1); 
862
863