Atlas - SDL_pixels.c

Home / ext / SDL / src / video Lines: 8 | Size: 50925 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23// General (mostly internal) pixel/color manipulation routines for SDL 24 25#include "SDL_sysvideo.h" 26#include "SDL_pixels_c.h" 27#include "SDL_RLEaccel_c.h" 28 29// Lookup tables to expand partial bytes to the full 0..255 range 30 31// This is the code used to generate the lookup tables below: 32#if 0 33#include <stdio.h> 34#include <SDL3/SDL.h> 35 36#define GENERATE_SHIFTS 37 38static Uint32 Calculate(int v, int bits, int vmax, int shift) 39{ 40#if defined(GENERATE_FLOOR) 41 return (Uint32)SDL_floor(v * 255.0f / vmax) << shift; 42#elif defined(GENERATE_ROUND) 43 return (Uint32)SDL_roundf(v * 255.0f / vmax) << shift; 44#elif defined(GENERATE_SHIFTS) 45 switch (bits) { 46 case 1: 47 v = (v << 7) | (v << 6) | (v << 5) | (v << 4) | (v << 3) | (v << 2) | (v << 1) | v; 48 break; 49 case 2: 50 v = (v << 6) | (v << 4) | (v << 2) | v; 51 break; 52 case 3: 53 v = (v << 5) | (v << 2) | (v >> 1); 54 break; 55 case 4: 56 v = (v << 4) | v; 57 break; 58 case 5: 59 v = (v << 3) | (v >> 2); 60 break; 61 case 6: 62 v = (v << 2) | (v >> 4); 63 break; 64 case 7: 65 v = (v << 1) | (v >> 6); 66 break; 67 case 8: 68 break; 69 } 70 return (Uint32)v << shift; 71#endif 72} 73 74int main(int argc, char *argv[]) 75{ 76 int i, b; 77 78 for (b = 1; b <= 8; ++b) { 79 printf("static const Uint8 lookup_%d[] = {\n ", b); 80 for (i = 0; i < (1 << b); ++i) { 81 if (i > 0) { 82 printf(", "); 83 } 84 printf("%d", Calculate(i, b, (1 << b) - 1, 0)); 85 } 86 printf("\n};\n\n"); 87 } 88 return 0; 89} 90#endif 91 92static const Uint8 lookup_0[] = { 93 255 94}; 95 96static const Uint8 lookup_1[] = { 97 0, 255 98}; 99 100static const Uint8 lookup_2[] = { 101 0, 85, 170, 255 102}; 103 104static const Uint8 lookup_3[] = { 105 0, 36, 73, 109, 146, 182, 219, 255 106}; 107 108static const Uint8 lookup_4[] = { 109 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 110}; 111 112static const Uint8 lookup_5[] = { 113 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255 114}; 115 116static const Uint8 lookup_6[] = { 117 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255 118}; 119 120static const Uint8 lookup_7[] = { 121 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 122}; 123 124static const Uint8 lookup_8[] = { 125 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 126}; 127 128const Uint8 *SDL_expand_byte[9] = { 129 lookup_0, 130 lookup_1, 131 lookup_2, 132 lookup_3, 133 lookup_4, 134 lookup_5, 135 lookup_6, 136 lookup_7, 137 lookup_8 138}; 139 140// Lookup tables to expand 8 bit to 10 bit range 141const Uint16 SDL_expand_byte_10[] = { 142 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 429, 433, 437, 441, 445, 449, 453, 457, 461, 465, 469, 473, 477, 481, 485, 489, 493, 497, 501, 505, 509, 514, 518, 522, 526, 530, 534, 538, 542, 546, 550, 554, 558, 562, 566, 570, 574, 578, 582, 586, 590, 594, 598, 602, 606, 610, 614, 618, 622, 626, 630, 634, 638, 642, 646, 650, 654, 658, 662, 666, 670, 674, 678, 682, 686, 690, 694, 698, 702, 706, 710, 714, 718, 722, 726, 730, 734, 738, 742, 746, 750, 754, 758, 762, 766, 770, 774, 778, 782, 786, 790, 794, 798, 802, 806, 810, 814, 818, 822, 826, 830, 834, 838, 842, 846, 850, 855, 859, 863, 867, 871, 875, 879, 883, 887, 891, 895, 899, 903, 907, 911, 915, 919, 923, 927, 931, 935, 939, 943, 947, 951, 955, 959, 963, 967, 971, 975, 979, 983, 987, 991, 995, 999, 1003, 1007, 1011, 1015, 1019, 1023 143}; 144SDL_COMPILE_TIME_ASSERT(SDL_expand_byte_10_size, SDL_arraysize(SDL_expand_byte_10) == (1 << 8)); 145 146 147// Helper functions 148 149#define CASE(X) \ 150 case X: \ 151 return #X; 152const char *SDL_GetPixelFormatName(SDL_PixelFormat format) 153{ 154 switch (format) { 155 156 CASE(SDL_PIXELFORMAT_INDEX1LSB) 157 CASE(SDL_PIXELFORMAT_INDEX1MSB) 158 CASE(SDL_PIXELFORMAT_INDEX2LSB) 159 CASE(SDL_PIXELFORMAT_INDEX2MSB) 160 CASE(SDL_PIXELFORMAT_INDEX4LSB) 161 CASE(SDL_PIXELFORMAT_INDEX4MSB) 162 CASE(SDL_PIXELFORMAT_INDEX8) 163 CASE(SDL_PIXELFORMAT_RGB332) 164 CASE(SDL_PIXELFORMAT_XRGB4444) 165 CASE(SDL_PIXELFORMAT_XBGR4444) 166 CASE(SDL_PIXELFORMAT_XRGB1555) 167 CASE(SDL_PIXELFORMAT_XBGR1555) 168 CASE(SDL_PIXELFORMAT_ARGB4444) 169 CASE(SDL_PIXELFORMAT_RGBA4444) 170 CASE(SDL_PIXELFORMAT_ABGR4444) 171 CASE(SDL_PIXELFORMAT_BGRA4444) 172 CASE(SDL_PIXELFORMAT_ARGB1555) 173 CASE(SDL_PIXELFORMAT_RGBA5551) 174 CASE(SDL_PIXELFORMAT_ABGR1555) 175 CASE(SDL_PIXELFORMAT_BGRA5551) 176 CASE(SDL_PIXELFORMAT_RGB565) 177 CASE(SDL_PIXELFORMAT_BGR565) 178 CASE(SDL_PIXELFORMAT_RGB24) 179 CASE(SDL_PIXELFORMAT_BGR24) 180 CASE(SDL_PIXELFORMAT_XRGB8888) 181 CASE(SDL_PIXELFORMAT_RGBX8888) 182 CASE(SDL_PIXELFORMAT_XBGR8888) 183 CASE(SDL_PIXELFORMAT_BGRX8888) 184 CASE(SDL_PIXELFORMAT_ARGB8888) 185 CASE(SDL_PIXELFORMAT_RGBA8888) 186 CASE(SDL_PIXELFORMAT_ABGR8888) 187 CASE(SDL_PIXELFORMAT_BGRA8888) 188 CASE(SDL_PIXELFORMAT_XRGB2101010) 189 CASE(SDL_PIXELFORMAT_XBGR2101010) 190 CASE(SDL_PIXELFORMAT_ARGB2101010) 191 CASE(SDL_PIXELFORMAT_ABGR2101010) 192 CASE(SDL_PIXELFORMAT_RGB48) 193 CASE(SDL_PIXELFORMAT_BGR48) 194 CASE(SDL_PIXELFORMAT_RGBA64) 195 CASE(SDL_PIXELFORMAT_ARGB64) 196 CASE(SDL_PIXELFORMAT_BGRA64) 197 CASE(SDL_PIXELFORMAT_ABGR64) 198 CASE(SDL_PIXELFORMAT_RGB48_FLOAT) 199 CASE(SDL_PIXELFORMAT_BGR48_FLOAT) 200 CASE(SDL_PIXELFORMAT_RGBA64_FLOAT) 201 CASE(SDL_PIXELFORMAT_ARGB64_FLOAT) 202 CASE(SDL_PIXELFORMAT_BGRA64_FLOAT) 203 CASE(SDL_PIXELFORMAT_ABGR64_FLOAT) 204 CASE(SDL_PIXELFORMAT_RGB96_FLOAT) 205 CASE(SDL_PIXELFORMAT_BGR96_FLOAT) 206 CASE(SDL_PIXELFORMAT_RGBA128_FLOAT) 207 CASE(SDL_PIXELFORMAT_ARGB128_FLOAT) 208 CASE(SDL_PIXELFORMAT_BGRA128_FLOAT) 209 CASE(SDL_PIXELFORMAT_ABGR128_FLOAT) 210 CASE(SDL_PIXELFORMAT_YV12) 211 CASE(SDL_PIXELFORMAT_IYUV) 212 CASE(SDL_PIXELFORMAT_YUY2) 213 CASE(SDL_PIXELFORMAT_UYVY) 214 CASE(SDL_PIXELFORMAT_YVYU) 215 CASE(SDL_PIXELFORMAT_NV12) 216 CASE(SDL_PIXELFORMAT_NV21) 217 CASE(SDL_PIXELFORMAT_P010) 218 CASE(SDL_PIXELFORMAT_EXTERNAL_OES) 219 CASE(SDL_PIXELFORMAT_MJPG) 220 221 default: 222 return "SDL_PIXELFORMAT_UNKNOWN"; 223 } 224} 225#undef CASE 226 227bool SDL_GetMasksForPixelFormat(SDL_PixelFormat format, int *bpp, Uint32 *Rmask, Uint32 *Gmask, Uint32 *Bmask, Uint32 *Amask) 228{ 229 Uint32 masks[4]; 230 231#ifdef SDL_HAVE_YUV 232 // Partial support for SDL_Surface with FOURCC 233 if (SDL_ISPIXELFORMAT_FOURCC(format)) { 234 // Not a format that uses masks 235 *Rmask = *Gmask = *Bmask = *Amask = 0; 236 // however, some of these are packed formats, and can legit declare bits-per-pixel! 237 switch (format) { 238 case SDL_PIXELFORMAT_YUY2: 239 case SDL_PIXELFORMAT_UYVY: 240 case SDL_PIXELFORMAT_YVYU: 241 *bpp = 32; 242 break; 243 default: 244 *bpp = 0; // oh well. 245 } 246 return true; 247 } 248#else 249 if (SDL_ISPIXELFORMAT_FOURCC(format)) { 250 return SDL_SetError("SDL not built with YUV support"); 251 } 252#endif 253 254 // Initialize the values here 255 if (SDL_BYTESPERPIXEL(format) <= 2) { 256 *bpp = SDL_BITSPERPIXEL(format); 257 } else { 258 *bpp = SDL_BYTESPERPIXEL(format) * 8; 259 } 260 *Rmask = *Gmask = *Bmask = *Amask = 0; 261 262 if (format == SDL_PIXELFORMAT_RGB24) { 263#if SDL_BYTEORDER == SDL_BIG_ENDIAN 264 *Rmask = 0x00FF0000; 265 *Gmask = 0x0000FF00; 266 *Bmask = 0x000000FF; 267#else 268 *Rmask = 0x000000FF; 269 *Gmask = 0x0000FF00; 270 *Bmask = 0x00FF0000; 271#endif 272 return true; 273 } 274 275 if (format == SDL_PIXELFORMAT_BGR24) { 276#if SDL_BYTEORDER == SDL_BIG_ENDIAN 277 *Rmask = 0x000000FF; 278 *Gmask = 0x0000FF00; 279 *Bmask = 0x00FF0000; 280#else 281 *Rmask = 0x00FF0000; 282 *Gmask = 0x0000FF00; 283 *Bmask = 0x000000FF; 284#endif 285 return true; 286 } 287 288 if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 && 289 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 && 290 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) { 291 // Not a format that uses masks 292 return true; 293 } 294 295 switch (SDL_PIXELLAYOUT(format)) { 296 case SDL_PACKEDLAYOUT_332: 297 masks[0] = 0x00000000; 298 masks[1] = 0x000000E0; 299 masks[2] = 0x0000001C; 300 masks[3] = 0x00000003; 301 break; 302 case SDL_PACKEDLAYOUT_4444: 303 masks[0] = 0x0000F000; 304 masks[1] = 0x00000F00; 305 masks[2] = 0x000000F0; 306 masks[3] = 0x0000000F; 307 break; 308 case SDL_PACKEDLAYOUT_1555: 309 masks[0] = 0x00008000; 310 masks[1] = 0x00007C00; 311 masks[2] = 0x000003E0; 312 masks[3] = 0x0000001F; 313 break; 314 case SDL_PACKEDLAYOUT_5551: 315 masks[0] = 0x0000F800; 316 masks[1] = 0x000007C0; 317 masks[2] = 0x0000003E; 318 masks[3] = 0x00000001; 319 break; 320 case SDL_PACKEDLAYOUT_565: 321 masks[0] = 0x00000000; 322 masks[1] = 0x0000F800; 323 masks[2] = 0x000007E0; 324 masks[3] = 0x0000001F; 325 break; 326 case SDL_PACKEDLAYOUT_8888: 327 masks[0] = 0xFF000000; 328 masks[1] = 0x00FF0000; 329 masks[2] = 0x0000FF00; 330 masks[3] = 0x000000FF; 331 break; 332 case SDL_PACKEDLAYOUT_2101010: 333 masks[0] = 0xC0000000; 334 masks[1] = 0x3FF00000; 335 masks[2] = 0x000FFC00; 336 masks[3] = 0x000003FF; 337 break; 338 case SDL_PACKEDLAYOUT_1010102: 339 masks[0] = 0xFFC00000; 340 masks[1] = 0x003FF000; 341 masks[2] = 0x00000FFC; 342 masks[3] = 0x00000003; 343 break; 344 default: 345 return SDL_SetError("Unknown pixel format"); 346 } 347 348 switch (SDL_PIXELORDER(format)) { 349 case SDL_PACKEDORDER_XRGB: 350 *Rmask = masks[1]; 351 *Gmask = masks[2]; 352 *Bmask = masks[3]; 353 break; 354 case SDL_PACKEDORDER_RGBX: 355 *Rmask = masks[0]; 356 *Gmask = masks[1]; 357 *Bmask = masks[2]; 358 break; 359 case SDL_PACKEDORDER_ARGB: 360 *Amask = masks[0]; 361 *Rmask = masks[1]; 362 *Gmask = masks[2]; 363 *Bmask = masks[3]; 364 break; 365 case SDL_PACKEDORDER_RGBA: 366 *Rmask = masks[0]; 367 *Gmask = masks[1]; 368 *Bmask = masks[2]; 369 *Amask = masks[3]; 370 break; 371 case SDL_PACKEDORDER_XBGR: 372 *Bmask = masks[1]; 373 *Gmask = masks[2]; 374 *Rmask = masks[3]; 375 break; 376 case SDL_PACKEDORDER_BGRX: 377 *Bmask = masks[0]; 378 *Gmask = masks[1]; 379 *Rmask = masks[2]; 380 break; 381 case SDL_PACKEDORDER_BGRA: 382 *Bmask = masks[0]; 383 *Gmask = masks[1]; 384 *Rmask = masks[2]; 385 *Amask = masks[3]; 386 break; 387 case SDL_PACKEDORDER_ABGR: 388 *Amask = masks[0]; 389 *Bmask = masks[1]; 390 *Gmask = masks[2]; 391 *Rmask = masks[3]; 392 break; 393 default: 394 return SDL_SetError("Unknown pixel format"); 395 } 396 return true; 397} 398 399SDL_PixelFormat SDL_GetPixelFormatForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) 400{ 401 switch (bpp) { 402 case 1: 403 // SDL defaults to MSB ordering 404 return SDL_PIXELFORMAT_INDEX1MSB; 405 case 2: 406 // SDL defaults to MSB ordering 407 return SDL_PIXELFORMAT_INDEX2MSB; 408 case 4: 409 // SDL defaults to MSB ordering 410 return SDL_PIXELFORMAT_INDEX4MSB; 411 case 8: 412 if (Rmask == 0xE0 && 413 Gmask == 0x1C && 414 Bmask == 0x03 && 415 Amask == 0x00) { 416 return SDL_PIXELFORMAT_RGB332; 417 } 418 return SDL_PIXELFORMAT_INDEX8; 419 case 12: 420 if (Rmask == 0) { 421 return SDL_PIXELFORMAT_XRGB4444; 422 } 423 if (Rmask == 0x0F00 && 424 Gmask == 0x00F0 && 425 Bmask == 0x000F && 426 Amask == 0x0000) { 427 return SDL_PIXELFORMAT_XRGB4444; 428 } 429 if (Rmask == 0x000F && 430 Gmask == 0x00F0 && 431 Bmask == 0x0F00 && 432 Amask == 0x0000) { 433 return SDL_PIXELFORMAT_XBGR4444; 434 } 435 break; 436 case 15: 437 if (Rmask == 0) { 438 return SDL_PIXELFORMAT_XRGB1555; 439 } 440 SDL_FALLTHROUGH; 441 case 16: 442 if (Rmask == 0) { 443 return SDL_PIXELFORMAT_RGB565; 444 } 445 if (Rmask == 0x7C00 && 446 Gmask == 0x03E0 && 447 Bmask == 0x001F && 448 Amask == 0x0000) { 449 return SDL_PIXELFORMAT_XRGB1555; 450 } 451 if (Rmask == 0x001F && 452 Gmask == 0x03E0 && 453 Bmask == 0x7C00 && 454 Amask == 0x0000) { 455 return SDL_PIXELFORMAT_XBGR1555; 456 } 457 if (Rmask == 0x0F00 && 458 Gmask == 0x00F0 && 459 Bmask == 0x000F && 460 Amask == 0xF000) { 461 return SDL_PIXELFORMAT_ARGB4444; 462 } 463 if (Rmask == 0xF000 && 464 Gmask == 0x0F00 && 465 Bmask == 0x00F0 && 466 Amask == 0x000F) { 467 return SDL_PIXELFORMAT_RGBA4444; 468 } 469 if (Rmask == 0x000F && 470 Gmask == 0x00F0 && 471 Bmask == 0x0F00 && 472 Amask == 0xF000) { 473 return SDL_PIXELFORMAT_ABGR4444; 474 } 475 if (Rmask == 0x00F0 && 476 Gmask == 0x0F00 && 477 Bmask == 0xF000 && 478 Amask == 0x000F) { 479 return SDL_PIXELFORMAT_BGRA4444; 480 } 481 if (Rmask == 0x7C00 && 482 Gmask == 0x03E0 && 483 Bmask == 0x001F && 484 Amask == 0x8000) { 485 return SDL_PIXELFORMAT_ARGB1555; 486 } 487 if (Rmask == 0xF800 && 488 Gmask == 0x07C0 && 489 Bmask == 0x003E && 490 Amask == 0x0001) { 491 return SDL_PIXELFORMAT_RGBA5551; 492 } 493 if (Rmask == 0x001F && 494 Gmask == 0x03E0 && 495 Bmask == 0x7C00 && 496 Amask == 0x8000) { 497 return SDL_PIXELFORMAT_ABGR1555; 498 } 499 if (Rmask == 0x003E && 500 Gmask == 0x07C0 && 501 Bmask == 0xF800 && 502 Amask == 0x0001) { 503 return SDL_PIXELFORMAT_BGRA5551; 504 } 505 if (Rmask == 0xF800 && 506 Gmask == 0x07E0 && 507 Bmask == 0x001F && 508 Amask == 0x0000) { 509 return SDL_PIXELFORMAT_RGB565; 510 } 511 if (Rmask == 0x001F && 512 Gmask == 0x07E0 && 513 Bmask == 0xF800 && 514 Amask == 0x0000) { 515 return SDL_PIXELFORMAT_BGR565; 516 } 517 if (Rmask == 0x003F && 518 Gmask == 0x07C0 && 519 Bmask == 0xF800 && 520 Amask == 0x0000) { 521 // Technically this would be BGR556, but Witek says this works in bug 3158 522 return SDL_PIXELFORMAT_RGB565; 523 } 524 break; 525 case 24: 526 switch (Rmask) { 527 case 0: 528 case 0x00FF0000: 529#if SDL_BYTEORDER == SDL_BIG_ENDIAN 530 return SDL_PIXELFORMAT_RGB24; 531#else 532 return SDL_PIXELFORMAT_BGR24; 533#endif 534 case 0x000000FF: 535#if SDL_BYTEORDER == SDL_BIG_ENDIAN 536 return SDL_PIXELFORMAT_BGR24; 537#else 538 return SDL_PIXELFORMAT_RGB24; 539#endif 540 } 541 break; 542 case 30: 543 if (Rmask == 0x3FF00000 && 544 Gmask == 0x000FFC00 && 545 Bmask == 0x000003FF && 546 Amask == 0x00000000) { 547 return SDL_PIXELFORMAT_XRGB2101010; 548 } 549 if (Rmask == 0x000003FF && 550 Gmask == 0x000FFC00 && 551 Bmask == 0x3FF00000 && 552 Amask == 0x00000000) { 553 return SDL_PIXELFORMAT_XBGR2101010; 554 } 555 break; 556 case 32: 557 if (Rmask == 0) { 558 return SDL_PIXELFORMAT_XRGB8888; 559 } 560 if (Rmask == 0x00FF0000 && 561 Gmask == 0x0000FF00 && 562 Bmask == 0x000000FF && 563 Amask == 0x00000000) { 564 return SDL_PIXELFORMAT_XRGB8888; 565 } 566 if (Rmask == 0xFF000000 && 567 Gmask == 0x00FF0000 && 568 Bmask == 0x0000FF00 && 569 Amask == 0x00000000) { 570 return SDL_PIXELFORMAT_RGBX8888; 571 } 572 if (Rmask == 0x000000FF && 573 Gmask == 0x0000FF00 && 574 Bmask == 0x00FF0000 && 575 Amask == 0x00000000) { 576 return SDL_PIXELFORMAT_XBGR8888; 577 } 578 if (Rmask == 0x0000FF00 && 579 Gmask == 0x00FF0000 && 580 Bmask == 0xFF000000 && 581 Amask == 0x00000000) { 582 return SDL_PIXELFORMAT_BGRX8888; 583 } 584 if (Rmask == 0x00FF0000 && 585 Gmask == 0x0000FF00 && 586 Bmask == 0x000000FF && 587 Amask == 0xFF000000) { 588 return SDL_PIXELFORMAT_ARGB8888; 589 } 590 if (Rmask == 0xFF000000 && 591 Gmask == 0x00FF0000 && 592 Bmask == 0x0000FF00 && 593 Amask == 0x000000FF) { 594 return SDL_PIXELFORMAT_RGBA8888; 595 } 596 if (Rmask == 0x000000FF && 597 Gmask == 0x0000FF00 && 598 Bmask == 0x00FF0000 && 599 Amask == 0xFF000000) { 600 return SDL_PIXELFORMAT_ABGR8888; 601 } 602 if (Rmask == 0x0000FF00 && 603 Gmask == 0x00FF0000 && 604 Bmask == 0xFF000000 && 605 Amask == 0x000000FF) { 606 return SDL_PIXELFORMAT_BGRA8888; 607 } 608 if (Rmask == 0x3FF00000 && 609 Gmask == 0x000FFC00 && 610 Bmask == 0x000003FF && 611 Amask == 0x00000000) { 612 return SDL_PIXELFORMAT_XRGB2101010; 613 } 614 if (Rmask == 0x000003FF && 615 Gmask == 0x000FFC00 && 616 Bmask == 0x3FF00000 && 617 Amask == 0x00000000) { 618 return SDL_PIXELFORMAT_XBGR2101010; 619 } 620 if (Rmask == 0x3FF00000 && 621 Gmask == 0x000FFC00 && 622 Bmask == 0x000003FF && 623 Amask == 0xC0000000) { 624 return SDL_PIXELFORMAT_ARGB2101010; 625 } 626 if (Rmask == 0x000003FF && 627 Gmask == 0x000FFC00 && 628 Bmask == 0x3FF00000 && 629 Amask == 0xC0000000) { 630 return SDL_PIXELFORMAT_ABGR2101010; 631 } 632 break; 633 } 634 return SDL_PIXELFORMAT_UNKNOWN; 635} 636 637static SDL_InitState SDL_format_details_init; 638static SDL_HashTable *SDL_format_details; 639 640static bool SDL_InitPixelFormatDetails(SDL_PixelFormatDetails *details, SDL_PixelFormat format) 641{ 642 int bpp; 643 Uint32 Rmask, Gmask, Bmask, Amask; 644 Uint32 mask; 645 646 if (!SDL_GetMasksForPixelFormat(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { 647 return false; 648 } 649 650 // Set up the format 651 SDL_zerop(details); 652 details->format = format; 653 details->bits_per_pixel = (Uint8)bpp; 654 details->bytes_per_pixel = (Uint8)((bpp + 7) / 8); 655 656 details->Rmask = Rmask; 657 details->Rshift = 0; 658 details->Rbits = 0; 659 if (Rmask) { 660 for (mask = Rmask; !(mask & 0x01); mask >>= 1) { 661 ++details->Rshift; 662 } 663 for (; (mask & 0x01); mask >>= 1) { 664 ++details->Rbits; 665 } 666 } 667 668 details->Gmask = Gmask; 669 details->Gshift = 0; 670 details->Gbits = 0; 671 if (Gmask) { 672 for (mask = Gmask; !(mask & 0x01); mask >>= 1) { 673 ++details->Gshift; 674 } 675 for (; (mask & 0x01); mask >>= 1) { 676 ++details->Gbits; 677 } 678 } 679 680 details->Bmask = Bmask; 681 details->Bshift = 0; 682 details->Bbits = 0; 683 if (Bmask) { 684 for (mask = Bmask; !(mask & 0x01); mask >>= 1) { 685 ++details->Bshift; 686 } 687 for (; (mask & 0x01); mask >>= 1) { 688 ++details->Bbits; 689 } 690 } 691 692 details->Amask = Amask; 693 details->Ashift = 0; 694 details->Abits = 0; 695 if (Amask) { 696 for (mask = Amask; !(mask & 0x01); mask >>= 1) { 697 ++details->Ashift; 698 } 699 for (; (mask & 0x01); mask >>= 1) { 700 ++details->Abits; 701 } 702 } 703 704 return true; 705} 706 707const SDL_PixelFormatDetails *SDL_GetPixelFormatDetails(SDL_PixelFormat format) 708{ 709 SDL_PixelFormatDetails *details; 710 711 if (SDL_ShouldInit(&SDL_format_details_init)) { 712 SDL_format_details = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL); 713 if (!SDL_format_details) { 714 SDL_SetInitialized(&SDL_format_details_init, false); 715 return NULL; 716 } 717 SDL_SetInitialized(&SDL_format_details_init, true); 718 } 719 720 if (SDL_FindInHashTable(SDL_format_details, (const void *)(uintptr_t)format, (const void **)&details)) { 721 return details; 722 } 723 724 // Allocate an empty pixel format structure, and initialize it 725 details = (SDL_PixelFormatDetails *)SDL_malloc(sizeof(*details)); 726 if (!details) { 727 return NULL; 728 } 729 730 if (!SDL_InitPixelFormatDetails(details, format)) { 731 SDL_free(details); 732 return NULL; 733 } 734 735 if (!SDL_InsertIntoHashTable(SDL_format_details, (const void *)(uintptr_t)format, (void *)details, false)) { 736 SDL_free(details); 737 // uh...did another thread beat us to inserting this? 738 if (SDL_FindInHashTable(SDL_format_details, (const void *)(uintptr_t)format, (const void **)&details)) { 739 return details; 740 } 741 return NULL; // oh well. 742 } 743 744 return details; 745} 746 747void SDL_QuitPixelFormatDetails(void) 748{ 749 if (SDL_ShouldQuit(&SDL_format_details_init)) { 750 SDL_DestroyHashTable(SDL_format_details); 751 SDL_format_details = NULL; 752 SDL_SetInitialized(&SDL_format_details_init, false); 753 } 754} 755 756void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift) 757{ 758 if (fmt->Amask) { 759 *mask = fmt->Amask; 760 *shift = fmt->Ashift; 761 } else { 762 *mask = ~(fmt->Rmask | fmt->Gmask | fmt->Bmask); 763 switch (*mask) { 764 case 0x000000FF: 765 *shift = 0; 766 break; 767 case 0x0000FF00: 768 *shift = 8; 769 break; 770 case 0x00FF0000: 771 *shift = 16; 772 break; 773 case 0xFF000000: 774 *shift = 24; 775 break; 776 default: 777 // Should never happen 778 *shift = 0; 779 break; 780 } 781 } 782} 783 784SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format) 785{ 786 if (SDL_ISPIXELFORMAT_FOURCC(format)) { 787 if (format == SDL_PIXELFORMAT_MJPG) { 788 return SDL_COLORSPACE_SRGB; 789 } else if (format == SDL_PIXELFORMAT_P010) { 790 return SDL_COLORSPACE_HDR10; 791 } else { 792 return SDL_COLORSPACE_YUV_DEFAULT; 793 } 794 } else if (SDL_ISPIXELFORMAT_FLOAT(format)) { 795 return SDL_COLORSPACE_SRGB_LINEAR; 796 } else if (SDL_ISPIXELFORMAT_10BIT(format)) { 797 return SDL_COLORSPACE_HDR10; 798 } else { 799 return SDL_COLORSPACE_RGB_DEFAULT; 800 } 801} 802 803float SDL_sRGBtoLinear(float v) 804{ 805 if (v <= 0.04045f) { 806 v = (v / 12.92f); 807 } else { 808 v = SDL_powf((v + 0.055f) / 1.055f, 2.4f); 809 } 810 return v; 811} 812 813float SDL_sRGBfromLinear(float v) 814{ 815 if (v <= 0.0031308f) { 816 v = (v * 12.92f); 817 } else { 818 v = (SDL_powf(v, 1.0f / 2.4f) * 1.055f - 0.055f); 819 } 820 return v; 821} 822 823float SDL_PQtoNits(float v) 824{ 825 const float c1 = 0.8359375f; 826 const float c2 = 18.8515625f; 827 const float c3 = 18.6875f; 828 const float oo_m1 = 1.0f / 0.1593017578125f; 829 const float oo_m2 = 1.0f / 78.84375f; 830 831 float num = SDL_max(SDL_powf(v, oo_m2) - c1, 0.0f); 832 float den = c2 - c3 * SDL_powf(v, oo_m2); 833 return 10000.0f * SDL_powf(num / den, oo_m1); 834} 835 836float SDL_PQfromNits(float v) 837{ 838 const float c1 = 0.8359375f; 839 const float c2 = 18.8515625f; 840 const float c3 = 18.6875f; 841 const float m1 = 0.1593017578125f; 842 const float m2 = 78.84375f; 843 844 float y = SDL_clamp(v / 10000.0f, 0.0f, 1.0f); 845 float num = c1 + c2 * SDL_powf(y, m1); 846 float den = 1.0f + c3 * SDL_powf(y, m1); 847 return SDL_powf(num / den, m2); 848} 849 850/* This is a helpful tool for deriving these: 851 * https://kdashg.github.io/misc/colors/from-coeffs.html 852 */ 853static const float mat_BT601_Limited_8bit[] = { 854 -0.0627451017f, -0.501960814f, -0.501960814f, 0.0f, // offset 855 1.1644f, 0.0000f, 1.5960f, 0.0f, // Rcoeff 856 1.1644f, -0.3918f, -0.8130f, 0.0f, // Gcoeff 857 1.1644f, 2.0172f, 0.0000f, 0.0f, // Bcoeff 858}; 859 860static const float mat_BT601_Full_8bit[] = { 861 0.0f, -0.501960814f, -0.501960814f, 0.0f, // offset 862 1.0000f, 0.0000f, 1.4075f, 0.0f, // Rcoeff 863 1.0000f, -0.3455f, -0.7169f, 0.0f, // Gcoeff 864 1.0000f, 1.7790f, 0.0000f, 0.0f, // Bcoeff 865}; 866 867static const float mat_BT709_Limited_8bit[] = { 868 -0.0627451017f, -0.501960814f, -0.501960814f, 0.0f, // offset 869 1.1644f, 0.0000f, 1.7927f, 0.0f, // Rcoeff 870 1.1644f, -0.2132f, -0.5329f, 0.0f, // Gcoeff 871 1.1644f, 2.1124f, 0.0000f, 0.0f, // Bcoeff 872}; 873 874static const float mat_BT709_Full_8bit[] = { 875 0.0f, -0.501960814f, -0.501960814f, 0.0f, // offset 876 1.0000f, 0.0000f, 1.5810f, 0.0f, // Rcoeff 877 1.0000f, -0.1881f, -0.4700f, 0.0f, // Gcoeff 878 1.0000f, 1.8629f, 0.0000f, 0.0f, // Bcoeff 879}; 880 881static const float mat_BT2020_Limited_10bit[] = { 882 -0.062561095f, -0.500488759f, -0.500488759f, 0.0f, // offset 883 1.1678f, 0.0000f, 1.6836f, 0.0f, // Rcoeff 884 1.1678f, -0.1879f, -0.6523f, 0.0f, // Gcoeff 885 1.1678f, 2.1481f, 0.0000f, 0.0f, // Bcoeff 886}; 887 888static const float mat_BT2020_Full_10bit[] = { 889 0.0f, -0.500488759f, -0.500488759f, 0.0f, // offset 890 1.0000f, 0.0000f, 1.4760f, 0.0f, // Rcoeff 891 1.0000f, -0.1647f, -0.5719f, 0.0f, // Gcoeff 892 1.0000f, 1.8832f, 0.0000f, 0.0f, // Bcoeff 893}; 894 895static const float *SDL_GetBT601ConversionMatrix( SDL_Colorspace colorspace ) 896{ 897 switch (SDL_COLORSPACERANGE(colorspace)) { 898 case SDL_COLOR_RANGE_LIMITED: 899 case SDL_COLOR_RANGE_UNKNOWN: 900 return mat_BT601_Limited_8bit; 901 case SDL_COLOR_RANGE_FULL: 902 return mat_BT601_Full_8bit; 903 default: 904 break; 905 } 906 return NULL; 907} 908 909static const float *SDL_GetBT709ConversionMatrix(SDL_Colorspace colorspace) 910{ 911 switch (SDL_COLORSPACERANGE(colorspace)) { 912 case SDL_COLOR_RANGE_LIMITED: 913 case SDL_COLOR_RANGE_UNKNOWN: 914 return mat_BT709_Limited_8bit; 915 case SDL_COLOR_RANGE_FULL: 916 return mat_BT709_Full_8bit; 917 default: 918 break; 919 } 920 return NULL; 921} 922 923static const float *SDL_GetBT2020ConversionMatrix(SDL_Colorspace colorspace) 924{ 925 switch (SDL_COLORSPACERANGE(colorspace)) { 926 case SDL_COLOR_RANGE_LIMITED: 927 case SDL_COLOR_RANGE_UNKNOWN: 928 return mat_BT2020_Limited_10bit; 929 case SDL_COLOR_RANGE_FULL: 930 return mat_BT2020_Full_10bit; 931 default: 932 break; 933 } 934 return NULL; 935} 936 937const float *SDL_GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w, int h, int bits_per_pixel) 938{ 939 const int YUV_SD_THRESHOLD = 576; 940 941 switch (SDL_COLORSPACEMATRIX(colorspace)) { 942 case SDL_MATRIX_COEFFICIENTS_BT601: 943 case SDL_MATRIX_COEFFICIENTS_BT470BG: 944 return SDL_GetBT601ConversionMatrix(colorspace); 945 946 case SDL_MATRIX_COEFFICIENTS_BT709: 947 return SDL_GetBT709ConversionMatrix(colorspace); 948 949 case SDL_MATRIX_COEFFICIENTS_BT2020_NCL: 950 return SDL_GetBT2020ConversionMatrix(colorspace); 951 952 case SDL_MATRIX_COEFFICIENTS_UNSPECIFIED: 953 switch (bits_per_pixel) { 954 case 8: 955 if (h <= YUV_SD_THRESHOLD) { 956 return SDL_GetBT601ConversionMatrix(colorspace); 957 } else { 958 return SDL_GetBT709ConversionMatrix(colorspace); 959 } 960 case 10: 961 case 16: 962 return SDL_GetBT2020ConversionMatrix(colorspace); 963 default: 964 break; 965 } 966 break; 967 default: 968 break; 969 } 970 return NULL; 971} 972 973const float *SDL_GetColorPrimariesConversionMatrix(SDL_ColorPrimaries src, SDL_ColorPrimaries dst) 974{ 975 /* Conversion matrices generated using gamescope color helpers and the primaries definitions at: 976 * https://www.itu.int/rec/T-REC-H.273-201612-S/en 977 * 978 * You can also generate these online using the RGB-XYZ matrix calculator, and then multiplying 979 * XYZ_to_dst * src_to_XYZ to get the combined conversion matrix: 980 * https://www.russellcottrell.com/photo/matrixCalculator.htm 981 */ 982 static const float mat601to709[] = { 983 0.939542f, 0.050181f, 0.010277f, 984 0.017772f, 0.965793f, 0.016435f, 985 -0.001622f, -0.004370f, 1.005991f, 986 }; 987 static const float mat601to2020[] = { 988 0.595254f, 0.349314f, 0.055432f, 989 0.081244f, 0.891503f, 0.027253f, 990 0.015512f, 0.081912f, 0.902576f, 991 }; 992 static const float mat709to601[] = { 993 1.065379f, -0.055401f, -0.009978f, 994 -0.019633f, 1.036363f, -0.016731f, 995 0.001632f, 0.004412f, 0.993956f, 996 }; 997 static const float mat709to2020[] = { 998 0.627404f, 0.329283f, 0.043313f, 999 0.069097f, 0.919541f, 0.011362f, 1000 0.016391f, 0.088013f, 0.895595f, 1001 }; 1002 static const float mat2020to601[] = { 1003 1.776133f, -0.687820f, -0.088313f, 1004 -0.161376f, 1.187315f, -0.025940f, 1005 -0.015881f, -0.095931f, 1.111812f, 1006 }; 1007 static const float mat2020to709[] = { 1008 1.660496f, -0.587656f, -0.072840f, 1009 -0.124547f, 1.132895f, -0.008348f, 1010 -0.018154f, -0.100597f, 1.118751f 1011 }; 1012 static const float matSMPTE431to709[] = { 1013 1.120713f, -0.234649f, 0.000000f, 1014 -0.038478f, 1.087034f, 0.000000f, 1015 -0.017967f, -0.082030f, 0.954576f, 1016 }; 1017 static const float matSMPTE431to2020[] = { 1018 0.689691f, 0.207169f, 0.041346f, 1019 0.041852f, 0.982426f, 0.010846f, 1020 -0.001107f, 0.018362f, 0.854914f, 1021 }; 1022 static const float matSMPTE432to709[] = { 1023 1.224940f, -0.224940f, -0.000000f, 1024 -0.042057f, 1.042057f, 0.000000f, 1025 -0.019638f, -0.078636f, 1.098273f, 1026 }; 1027 static const float matSMPTE432to2020[] = { 1028 0.753833f, 0.198597f, 0.047570f, 1029 0.045744f, 0.941777f, 0.012479f, 1030 -0.001210f, 0.017602f, 0.983609f, 1031 }; 1032 1033 switch (dst) { 1034 case SDL_COLOR_PRIMARIES_BT601: 1035 case SDL_COLOR_PRIMARIES_SMPTE240: 1036 switch (src) { 1037 case SDL_COLOR_PRIMARIES_BT709: 1038 return mat709to601; 1039 case SDL_COLOR_PRIMARIES_BT2020: 1040 return mat2020to601; 1041 default: 1042 break; 1043 } 1044 break; 1045 case SDL_COLOR_PRIMARIES_BT709: 1046 switch (src) { 1047 case SDL_COLOR_PRIMARIES_BT601: 1048 case SDL_COLOR_PRIMARIES_SMPTE240: 1049 return mat601to709; 1050 case SDL_COLOR_PRIMARIES_BT2020: 1051 return mat2020to709; 1052 case SDL_COLOR_PRIMARIES_SMPTE431: 1053 return matSMPTE431to709; 1054 case SDL_COLOR_PRIMARIES_SMPTE432: 1055 return matSMPTE432to709; 1056 default: 1057 break; 1058 } 1059 break; 1060 case SDL_COLOR_PRIMARIES_BT2020: 1061 switch (src) { 1062 case SDL_COLOR_PRIMARIES_BT601: 1063 case SDL_COLOR_PRIMARIES_SMPTE240: 1064 return mat601to2020; 1065 case SDL_COLOR_PRIMARIES_BT709: 1066 return mat709to2020; 1067 case SDL_COLOR_PRIMARIES_SMPTE431: 1068 return matSMPTE431to2020; 1069 case SDL_COLOR_PRIMARIES_SMPTE432: 1070 return matSMPTE432to2020; 1071 default: 1072 break; 1073 } 1074 break; 1075 default: 1076 break; 1077 } 1078 return NULL; 1079} 1080 1081void SDL_ConvertColorPrimaries(float *fR, float *fG, float *fB, const float *matrix) 1082{ 1083 float v[3]; 1084 1085 v[0] = *fR; 1086 v[1] = *fG; 1087 v[2] = *fB; 1088 1089 *fR = matrix[0 * 3 + 0] * v[0] + matrix[0 * 3 + 1] * v[1] + matrix[0 * 3 + 2] * v[2]; 1090 *fG = matrix[1 * 3 + 0] * v[0] + matrix[1 * 3 + 1] * v[1] + matrix[1 * 3 + 2] * v[2]; 1091 *fB = matrix[2 * 3 + 0] * v[0] + matrix[2 * 3 + 1] * v[1] + matrix[2 * 3 + 2] * v[2]; 1092} 1093 1094SDL_Palette *SDL_CreatePalette(int ncolors) 1095{ 1096 SDL_Palette *palette; 1097 1098 // Input validation 1099 CHECK_PARAM(ncolors < 1) { 1100 SDL_InvalidParamError("ncolors"); 1101 return NULL; 1102 } 1103 1104 palette = (SDL_Palette *)SDL_malloc(sizeof(*palette)); 1105 if (!palette) { 1106 return NULL; 1107 } 1108 palette->colors = (SDL_Color *)SDL_malloc(ncolors * sizeof(*palette->colors)); 1109 if (!palette->colors) { 1110 SDL_free(palette); 1111 return NULL; 1112 } 1113 palette->ncolors = ncolors; 1114 palette->version = 1; 1115 palette->refcount = 1; 1116 1117 SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors)); 1118 1119 return palette; 1120} 1121 1122bool SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors, int firstcolor, int ncolors) 1123{ 1124 bool result = true; 1125 1126 // Verify the parameters 1127 if (!palette) { 1128 return false; 1129 } 1130 if (ncolors > (palette->ncolors - firstcolor)) { 1131 ncolors = (palette->ncolors - firstcolor); 1132 result = false; 1133 } 1134 1135 if (colors != (palette->colors + firstcolor)) { 1136 SDL_memcpy(palette->colors + firstcolor, colors, 1137 ncolors * sizeof(*colors)); 1138 } 1139 ++palette->version; 1140 if (!palette->version) { 1141 palette->version = 1; 1142 } 1143 1144 return result; 1145} 1146 1147void SDL_DestroyPalette(SDL_Palette *palette) 1148{ 1149 if (!palette) { 1150 return; 1151 } 1152 if (--palette->refcount > 0) { 1153 return; 1154 } 1155 SDL_free(palette->colors); 1156 SDL_free(palette); 1157} 1158 1159/* 1160 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors 1161 */ 1162void SDL_DitherPalette(SDL_Palette *palette) 1163{ 1164 int i; 1165 if (palette->ncolors != 256) { 1166 return; // only 8bpp supported right now 1167 } 1168 1169 for (i = 0; i < palette->ncolors; i++) { 1170 int r, g, b; 1171 /* map each bit field to the full [0, 255] interval, 1172 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ 1173 r = i & 0xe0; 1174 r |= r >> 3 | r >> 6; 1175 palette->colors[i].r = (Uint8)r; 1176 g = (i << 3) & 0xe0; 1177 g |= g >> 3 | g >> 6; 1178 palette->colors[i].g = (Uint8)g; 1179 b = i & 0x3; 1180 b |= b << 2; 1181 b |= b << 4; 1182 palette->colors[i].b = (Uint8)b; 1183 palette->colors[i].a = SDL_ALPHA_OPAQUE; 1184 } 1185} 1186 1187/* 1188 * Match an RGB value to a particular palette index 1189 */ 1190static Uint8 SDL_FindColor(const SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 1191{ 1192 // Do colorspace distance matching 1193 unsigned int smallest; 1194 unsigned int distance; 1195 int rd, gd, bd, ad; 1196 int i; 1197 Uint8 pixelvalue = 0; 1198 1199 smallest = ~0U; 1200 for (i = 0; i < pal->ncolors; ++i) { 1201 rd = pal->colors[i].r - r; 1202 gd = pal->colors[i].g - g; 1203 bd = pal->colors[i].b - b; 1204 ad = pal->colors[i].a - a; 1205 distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad); 1206 if (distance < smallest) { 1207 pixelvalue = (Uint8)i; 1208 if (distance == 0) { // Perfect match! 1209 break; 1210 } 1211 smallest = distance; 1212 } 1213 } 1214 return pixelvalue; 1215} 1216 1217Uint8 SDL_LookupRGBAColor(SDL_HashTable *palette_map, Uint32 pixelvalue, const SDL_Palette *pal) 1218{ 1219 Uint8 color_index = 0; 1220 if (pal) { 1221 const void *value; 1222 if (SDL_FindInHashTable(palette_map, (const void *)(uintptr_t)pixelvalue, &value)) { 1223 color_index = (Uint8)(uintptr_t)value; 1224 } else { 1225 Uint8 r = (Uint8)((pixelvalue >> 24) & 0xFF); 1226 Uint8 g = (Uint8)((pixelvalue >> 16) & 0xFF); 1227 Uint8 b = (Uint8)((pixelvalue >> 8) & 0xFF); 1228 Uint8 a = (Uint8)((pixelvalue >> 0) & 0xFF); 1229 color_index = SDL_FindColor(pal, r, g, b, a); 1230 SDL_InsertIntoHashTable(palette_map, (const void *)(uintptr_t)pixelvalue, (const void *)(uintptr_t)color_index, true); 1231 } 1232 } 1233 return color_index; 1234} 1235 1236// Tell whether palette is opaque, and if it has an alpha_channel 1237void SDL_DetectPalette(const SDL_Palette *pal, bool *is_opaque, bool *has_alpha_channel) 1238{ 1239 int i; 1240 1241 { 1242 bool all_opaque = true; 1243 for (i = 0; i < pal->ncolors; i++) { 1244 Uint8 alpha_value = pal->colors[i].a; 1245 if (alpha_value != SDL_ALPHA_OPAQUE) { 1246 all_opaque = false; 1247 break; 1248 } 1249 } 1250 1251 if (all_opaque) { 1252 // Palette is opaque, with an alpha channel 1253 *is_opaque = true; 1254 *has_alpha_channel = true; 1255 return; 1256 } 1257 } 1258 1259 { 1260 bool all_transparent = true; 1261 for (i = 0; i < pal->ncolors; i++) { 1262 Uint8 alpha_value = pal->colors[i].a; 1263 if (alpha_value != SDL_ALPHA_TRANSPARENT) { 1264 all_transparent = false; 1265 break; 1266 } 1267 } 1268 1269 if (all_transparent) { 1270 // Palette is opaque, without an alpha channel 1271 *is_opaque = true; 1272 *has_alpha_channel = false; 1273 return; 1274 } 1275 } 1276 1277 // Palette has alpha values 1278 *is_opaque = false; 1279 *has_alpha_channel = true; 1280} 1281 1282// Find the opaque pixel value corresponding to an RGB triple 1283Uint32 SDL_MapRGB(const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 r, Uint8 g, Uint8 b) 1284{ 1285 CHECK_PARAM(!format) { 1286 SDL_InvalidParamError("format"); 1287 return 0; 1288 } 1289 1290 if (SDL_ISPIXELFORMAT_INDEXED(format->format)) { 1291 CHECK_PARAM(!palette) { 1292 SDL_InvalidParamError("palette"); 1293 return 0; 1294 } 1295 return SDL_FindColor(palette, r, g, b, SDL_ALPHA_OPAQUE); 1296 } 1297 1298 if (SDL_ISPIXELFORMAT_10BIT(format->format)) { 1299 return (((Uint32)SDL_expand_byte_10[r]) << format->Rshift) | 1300 (((Uint32)SDL_expand_byte_10[g]) << format->Gshift) | 1301 (((Uint32)SDL_expand_byte_10[b]) << format->Bshift) | 1302 format->Amask; 1303 } else { 1304 return ((Uint32)(r >> (8 - format->Rbits))) << format->Rshift | 1305 ((Uint32)(g >> (8 - format->Gbits))) << format->Gshift | 1306 ((Uint32)(b >> (8 - format->Bbits))) << format->Bshift | 1307 format->Amask; 1308 } 1309} 1310 1311// Find the pixel value corresponding to an RGBA quadruple 1312Uint32 SDL_MapRGBA(const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 1313{ 1314 CHECK_PARAM(!format) { 1315 SDL_InvalidParamError("format"); 1316 return 0; 1317 } 1318 1319 if (SDL_ISPIXELFORMAT_INDEXED(format->format)) { 1320 CHECK_PARAM(!palette) { 1321 SDL_InvalidParamError("palette"); 1322 return 0; 1323 } 1324 return SDL_FindColor(palette, r, g, b, a); 1325 } 1326 1327 if (SDL_ISPIXELFORMAT_10BIT(format->format)) { 1328 return (((Uint32)SDL_expand_byte_10[r]) << format->Rshift) | 1329 (((Uint32)SDL_expand_byte_10[g]) << format->Gshift) | 1330 (((Uint32)SDL_expand_byte_10[b]) << format->Bshift) | 1331 ((((Uint32)(a >> (8 - format->Abits))) << format->Ashift) & format->Amask); 1332 } else { 1333 return ((Uint32)(r >> (8 - format->Rbits))) << format->Rshift | 1334 ((Uint32)(g >> (8 - format->Gbits))) << format->Gshift | 1335 ((Uint32)(b >> (8 - format->Bbits))) << format->Bshift | 1336 ((((Uint32)(a >> (8 - format->Abits))) << format->Ashift) & format->Amask); 1337 } 1338} 1339 1340void SDL_GetRGB(Uint32 pixelvalue, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b) 1341{ 1342 Uint8 unused; 1343 1344 if (!r) { 1345 r = &unused; 1346 } 1347 if (!g) { 1348 g = &unused; 1349 } 1350 if (!b) { 1351 b = &unused; 1352 } 1353 1354 if (!format) { 1355 *r = *g = *b = 0; 1356 return; 1357 } 1358 1359 if (SDL_ISPIXELFORMAT_INDEXED(format->format)) { 1360 if (palette && pixelvalue < (unsigned)palette->ncolors) { 1361 *r = palette->colors[pixelvalue].r; 1362 *g = palette->colors[pixelvalue].g; 1363 *b = palette->colors[pixelvalue].b; 1364 } else { 1365 *r = *g = *b = 0; 1366 } 1367 return; 1368 } 1369 1370 if (SDL_ISPIXELFORMAT_10BIT(format->format)) { 1371 unsigned v; 1372 v = (pixelvalue & format->Rmask) >> format->Rshift; 1373 *r = (Uint8)(v >> 2); 1374 v = (pixelvalue & format->Gmask) >> format->Gshift; 1375 *g = (Uint8)(v >> 2); 1376 v = (pixelvalue & format->Bmask) >> format->Bshift; 1377 *b = (Uint8)(v >> 2); 1378 } else { 1379 unsigned v; 1380 v = (pixelvalue & format->Rmask) >> format->Rshift; 1381 *r = SDL_expand_byte[format->Rbits][v]; 1382 v = (pixelvalue & format->Gmask) >> format->Gshift; 1383 *g = SDL_expand_byte[format->Gbits][v]; 1384 v = (pixelvalue & format->Bmask) >> format->Bshift; 1385 *b = SDL_expand_byte[format->Bbits][v]; 1386 } 1387} 1388 1389void SDL_GetRGBA(Uint32 pixelvalue, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) 1390{ 1391 Uint8 unused; 1392 1393 if (!r) { 1394 r = &unused; 1395 } 1396 if (!g) { 1397 g = &unused; 1398 } 1399 if (!b) { 1400 b = &unused; 1401 } 1402 if (!a) { 1403 a = &unused; 1404 } 1405 1406 if (!format) { 1407 *r = *g = *b = *a = 0; 1408 return; 1409 } 1410 1411 if (SDL_ISPIXELFORMAT_INDEXED(format->format)) { 1412 if (palette && pixelvalue < (unsigned)palette->ncolors) { 1413 *r = palette->colors[pixelvalue].r; 1414 *g = palette->colors[pixelvalue].g; 1415 *b = palette->colors[pixelvalue].b; 1416 *a = palette->colors[pixelvalue].a; 1417 } else { 1418 *r = *g = *b = *a = 0; 1419 } 1420 return; 1421 } 1422 1423 if (SDL_ISPIXELFORMAT_10BIT(format->format)) { 1424 unsigned v; 1425 v = (pixelvalue & format->Rmask) >> format->Rshift; 1426 *r = (Uint8)(v >> 2); 1427 v = (pixelvalue & format->Gmask) >> format->Gshift; 1428 *g = (Uint8)(v >> 2); 1429 v = (pixelvalue & format->Bmask) >> format->Bshift; 1430 *b = (Uint8)(v >> 2); 1431 v = (pixelvalue & format->Amask) >> format->Ashift; 1432 *a = SDL_expand_byte[format->Abits][v]; 1433 } else { 1434 unsigned v; 1435 v = (pixelvalue & format->Rmask) >> format->Rshift; 1436 *r = SDL_expand_byte[format->Rbits][v]; 1437 v = (pixelvalue & format->Gmask) >> format->Gshift; 1438 *g = SDL_expand_byte[format->Gbits][v]; 1439 v = (pixelvalue & format->Bmask) >> format->Bshift; 1440 *b = SDL_expand_byte[format->Bbits][v]; 1441 v = (pixelvalue & format->Amask) >> format->Ashift; 1442 *a = SDL_expand_byte[format->Abits][v]; 1443 } 1444} 1445 1446bool SDL_IsSamePalette(const SDL_Palette *src, const SDL_Palette *dst) 1447{ 1448 if (src->ncolors <= dst->ncolors) { 1449 // If an identical palette, no need to map 1450 if (src == dst || 1451 (SDL_memcmp(src->colors, dst->colors, 1452 src->ncolors * sizeof(SDL_Color)) == 0)) { 1453 return true; 1454 } 1455 } 1456 return false; 1457} 1458 1459// Map from Palette to Palette 1460static Uint8 *Map1to1(const SDL_Palette *src, const SDL_Palette *dst, int *identical) 1461{ 1462 Uint8 *map; 1463 int i; 1464 1465 if (SDL_IsSamePalette(src, dst)) { 1466 *identical = 1; 1467 return NULL; 1468 } 1469 *identical = 0; 1470 1471 map = (Uint8 *)SDL_calloc(256, sizeof(Uint8)); 1472 if (!map) { 1473 return NULL; 1474 } 1475 for (i = 0; i < src->ncolors; ++i) { 1476 map[i] = SDL_FindColor(dst, 1477 src->colors[i].r, src->colors[i].g, 1478 src->colors[i].b, src->colors[i].a); 1479 } 1480 return map; 1481} 1482 1483// Map from Palette to BitField 1484static Uint8 *Map1toN(const SDL_Palette *pal, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod, const SDL_PixelFormatDetails *dst) 1485{ 1486 Uint8 *map; 1487 int i; 1488 int bpp; 1489 1490 if (!pal) { 1491 SDL_SetError("src does not have a palette set"); 1492 return NULL; 1493 } 1494 1495 bpp = ((SDL_BYTESPERPIXEL(dst->format) == 3) ? 4 : SDL_BYTESPERPIXEL(dst->format)); 1496 map = (Uint8 *)SDL_calloc(256, bpp); 1497 if (!map) { 1498 return NULL; 1499 } 1500 1501 // We memory copy to the pixel map so the endianness is preserved 1502 for (i = 0; i < pal->ncolors; ++i) { 1503 Uint8 R = (Uint8)((pal->colors[i].r * Rmod) / 255); 1504 Uint8 G = (Uint8)((pal->colors[i].g * Gmod) / 255); 1505 Uint8 B = (Uint8)((pal->colors[i].b * Bmod) / 255); 1506 Uint8 A = (Uint8)((pal->colors[i].a * Amod) / 255); 1507 ASSEMBLE_RGBA(&map[i * bpp], SDL_BYTESPERPIXEL(dst->format), dst, (Uint32)R, 1508 (Uint32)G, (Uint32)B, (Uint32)A); 1509 } 1510 return map; 1511} 1512 1513bool SDL_ValidateMap(SDL_Surface *src, SDL_Surface *dst) 1514{ 1515 SDL_BlitMap *map = &src->map; 1516 1517 if (map->info.dst_fmt != dst->fmt || 1518 map->info.dst_pal != dst->palette || 1519 (dst->palette && 1520 map->dst_palette_version != dst->palette->version) || 1521 (src->palette && 1522 map->src_palette_version != src->palette->version)) { 1523 if (!SDL_MapSurface(src, dst)) { 1524 return false; 1525 } 1526 // just here for debugging 1527 // printf 1528 // ("src = 0x%08X src->flags = %08X map->info.flags = %08x\ndst = 0x%08X dst->flags = %08X dst->map.info.flags = %08X\nmap->blit = 0x%08x\n", 1529 // src, dst->flags, map->info.flags, dst, dst->flags, 1530 // dst->map.info.flags, map->blit); 1531 } else { 1532 map->info.dst_surface = dst; 1533 } 1534 return true; 1535} 1536 1537void SDL_InvalidateMap(SDL_BlitMap *map) 1538{ 1539 map->info.dst_fmt = NULL; 1540 map->info.dst_pal = NULL; 1541 map->src_palette_version = 0; 1542 map->dst_palette_version = 0; 1543 if (map->info.table) { 1544 SDL_free(map->info.table); 1545 map->info.table = NULL; 1546 } 1547 if (map->info.palette_map) { 1548 SDL_DestroyHashTable(map->info.palette_map); 1549 map->info.palette_map = NULL; 1550 } 1551} 1552 1553bool SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst) 1554{ 1555 const SDL_PixelFormatDetails *srcfmt; 1556 const SDL_Palette *srcpal; 1557 const SDL_PixelFormatDetails *dstfmt; 1558 const SDL_Palette *dstpal; 1559 SDL_BlitMap *map; 1560 1561 // Clear out any previous mapping 1562 map = &src->map; 1563#ifdef SDL_HAVE_RLE 1564 if (src->internal_flags & SDL_INTERNAL_SURFACE_RLEACCEL) { 1565 SDL_UnRLESurface(src); 1566 } 1567#endif 1568 SDL_InvalidateMap(map); 1569 1570 // Figure out what kind of mapping we're doing 1571 map->identity = 0; 1572 srcfmt = src->fmt; 1573 srcpal = src->palette; 1574 dstfmt = dst->fmt; 1575 dstpal = dst->palette; 1576 if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) { 1577 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) { 1578 // Palette --> Palette 1579 if (srcpal && dstpal) { 1580 map->info.table = Map1to1(srcpal, dstpal, &map->identity); 1581 } else { 1582 map->identity = 1; 1583 } 1584 if (!map->identity) { 1585 if (!map->info.table) { 1586 return false; 1587 } 1588 } 1589 if (srcfmt->bits_per_pixel != dstfmt->bits_per_pixel) { 1590 map->identity = 0; 1591 } 1592 } else { 1593 // Palette --> BitField 1594 map->info.table = 1595 Map1toN(srcpal, src->map.info.r, src->map.info.g, 1596 src->map.info.b, src->map.info.a, dstfmt); 1597 if (!map->info.table) { 1598 return false; 1599 } 1600 } 1601 } else { 1602 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) { 1603 // BitField --> Palette 1604 map->info.palette_map = SDL_CreateHashTable(0, false, SDL_HashID, SDL_KeyMatchID, NULL, NULL); 1605 } else { 1606 // BitField --> BitField 1607 if (srcfmt == dstfmt) { 1608 map->identity = 1; 1609 } 1610 } 1611 } 1612 1613 if (dstpal) { 1614 map->dst_palette_version = dstpal->version; 1615 } else { 1616 map->dst_palette_version = 0; 1617 } 1618 1619 if (srcpal) { 1620 map->src_palette_version = srcpal->version; 1621 } else { 1622 map->src_palette_version = 0; 1623 } 1624 1625 // Choose your blitters wisely 1626 return SDL_CalculateBlit(src, dst); 1627} 1628 1629
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.