SDL_pixels.c (31965B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 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_endian.h" 26#include "SDL_video.h" 27#include "SDL_sysvideo.h" 28#include "SDL_blit.h" 29#include "SDL_pixels_c.h" 30#include "SDL_RLEaccel_c.h" 31 32 33/* Lookup tables to expand partial bytes to the full 0..255 range */ 34 35static Uint8 lookup_0[] = { 360, 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 37}; 38 39static Uint8 lookup_1[] = { 400, 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, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255 41}; 42 43static Uint8 lookup_2[] = { 440, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255 45}; 46 47static Uint8 lookup_3[] = { 480, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255 49}; 50 51static Uint8 lookup_4[] = { 520, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 53}; 54 55static Uint8 lookup_5[] = { 560, 36, 72, 109, 145, 182, 218, 255 57}; 58 59static Uint8 lookup_6[] = { 600, 85, 170, 255 61}; 62 63static Uint8 lookup_7[] = { 640, 255 65}; 66 67static Uint8 lookup_8[] = { 68255 69}; 70 71Uint8* SDL_expand_byte[9] = { 72 lookup_0, 73 lookup_1, 74 lookup_2, 75 lookup_3, 76 lookup_4, 77 lookup_5, 78 lookup_6, 79 lookup_7, 80 lookup_8 81}; 82 83/* Helper functions */ 84 85const char* 86SDL_GetPixelFormatName(Uint32 format) 87{ 88 switch (format) { 89#define CASE(X) case X: return #X; 90 CASE(SDL_PIXELFORMAT_INDEX1LSB) 91 CASE(SDL_PIXELFORMAT_INDEX1MSB) 92 CASE(SDL_PIXELFORMAT_INDEX4LSB) 93 CASE(SDL_PIXELFORMAT_INDEX4MSB) 94 CASE(SDL_PIXELFORMAT_INDEX8) 95 CASE(SDL_PIXELFORMAT_RGB332) 96 CASE(SDL_PIXELFORMAT_RGB444) 97 CASE(SDL_PIXELFORMAT_RGB555) 98 CASE(SDL_PIXELFORMAT_BGR555) 99 CASE(SDL_PIXELFORMAT_ARGB4444) 100 CASE(SDL_PIXELFORMAT_RGBA4444) 101 CASE(SDL_PIXELFORMAT_ABGR4444) 102 CASE(SDL_PIXELFORMAT_BGRA4444) 103 CASE(SDL_PIXELFORMAT_ARGB1555) 104 CASE(SDL_PIXELFORMAT_RGBA5551) 105 CASE(SDL_PIXELFORMAT_ABGR1555) 106 CASE(SDL_PIXELFORMAT_BGRA5551) 107 CASE(SDL_PIXELFORMAT_RGB565) 108 CASE(SDL_PIXELFORMAT_BGR565) 109 CASE(SDL_PIXELFORMAT_RGB24) 110 CASE(SDL_PIXELFORMAT_BGR24) 111 CASE(SDL_PIXELFORMAT_RGB888) 112 CASE(SDL_PIXELFORMAT_RGBX8888) 113 CASE(SDL_PIXELFORMAT_BGR888) 114 CASE(SDL_PIXELFORMAT_BGRX8888) 115 CASE(SDL_PIXELFORMAT_ARGB8888) 116 CASE(SDL_PIXELFORMAT_RGBA8888) 117 CASE(SDL_PIXELFORMAT_ABGR8888) 118 CASE(SDL_PIXELFORMAT_BGRA8888) 119 CASE(SDL_PIXELFORMAT_ARGB2101010) 120 CASE(SDL_PIXELFORMAT_YV12) 121 CASE(SDL_PIXELFORMAT_IYUV) 122 CASE(SDL_PIXELFORMAT_YUY2) 123 CASE(SDL_PIXELFORMAT_UYVY) 124 CASE(SDL_PIXELFORMAT_YVYU) 125 CASE(SDL_PIXELFORMAT_NV12) 126 CASE(SDL_PIXELFORMAT_NV21) 127#undef CASE 128 default: 129 return "SDL_PIXELFORMAT_UNKNOWN"; 130 } 131} 132 133SDL_bool 134SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask, 135 Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask) 136{ 137 Uint32 masks[4]; 138 139 /* This function doesn't work with FourCC pixel formats */ 140 if (SDL_ISPIXELFORMAT_FOURCC(format)) { 141 SDL_SetError("FOURCC pixel formats are not supported"); 142 return SDL_FALSE; 143 } 144 145 /* Initialize the values here */ 146 if (SDL_BYTESPERPIXEL(format) <= 2) { 147 *bpp = SDL_BITSPERPIXEL(format); 148 } else { 149 *bpp = SDL_BYTESPERPIXEL(format) * 8; 150 } 151 *Rmask = *Gmask = *Bmask = *Amask = 0; 152 153 if (format == SDL_PIXELFORMAT_RGB24) { 154#if SDL_BYTEORDER == SDL_BIG_ENDIAN 155 *Rmask = 0x00FF0000; 156 *Gmask = 0x0000FF00; 157 *Bmask = 0x000000FF; 158#else 159 *Rmask = 0x000000FF; 160 *Gmask = 0x0000FF00; 161 *Bmask = 0x00FF0000; 162#endif 163 return SDL_TRUE; 164 } 165 166 if (format == SDL_PIXELFORMAT_BGR24) { 167#if SDL_BYTEORDER == SDL_BIG_ENDIAN 168 *Rmask = 0x000000FF; 169 *Gmask = 0x0000FF00; 170 *Bmask = 0x00FF0000; 171#else 172 *Rmask = 0x00FF0000; 173 *Gmask = 0x0000FF00; 174 *Bmask = 0x000000FF; 175#endif 176 return SDL_TRUE; 177 } 178 179 if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 && 180 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 && 181 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) { 182 /* Not a format that uses masks */ 183 return SDL_TRUE; 184 } 185 186 switch (SDL_PIXELLAYOUT(format)) { 187 case SDL_PACKEDLAYOUT_332: 188 masks[0] = 0x00000000; 189 masks[1] = 0x000000E0; 190 masks[2] = 0x0000001C; 191 masks[3] = 0x00000003; 192 break; 193 case SDL_PACKEDLAYOUT_4444: 194 masks[0] = 0x0000F000; 195 masks[1] = 0x00000F00; 196 masks[2] = 0x000000F0; 197 masks[3] = 0x0000000F; 198 break; 199 case SDL_PACKEDLAYOUT_1555: 200 masks[0] = 0x00008000; 201 masks[1] = 0x00007C00; 202 masks[2] = 0x000003E0; 203 masks[3] = 0x0000001F; 204 break; 205 case SDL_PACKEDLAYOUT_5551: 206 masks[0] = 0x0000F800; 207 masks[1] = 0x000007C0; 208 masks[2] = 0x0000003E; 209 masks[3] = 0x00000001; 210 break; 211 case SDL_PACKEDLAYOUT_565: 212 masks[0] = 0x00000000; 213 masks[1] = 0x0000F800; 214 masks[2] = 0x000007E0; 215 masks[3] = 0x0000001F; 216 break; 217 case SDL_PACKEDLAYOUT_8888: 218 masks[0] = 0xFF000000; 219 masks[1] = 0x00FF0000; 220 masks[2] = 0x0000FF00; 221 masks[3] = 0x000000FF; 222 break; 223 case SDL_PACKEDLAYOUT_2101010: 224 masks[0] = 0xC0000000; 225 masks[1] = 0x3FF00000; 226 masks[2] = 0x000FFC00; 227 masks[3] = 0x000003FF; 228 break; 229 case SDL_PACKEDLAYOUT_1010102: 230 masks[0] = 0xFFC00000; 231 masks[1] = 0x003FF000; 232 masks[2] = 0x00000FFC; 233 masks[3] = 0x00000003; 234 break; 235 default: 236 SDL_SetError("Unknown pixel format"); 237 return SDL_FALSE; 238 } 239 240 switch (SDL_PIXELORDER(format)) { 241 case SDL_PACKEDORDER_XRGB: 242 *Rmask = masks[1]; 243 *Gmask = masks[2]; 244 *Bmask = masks[3]; 245 break; 246 case SDL_PACKEDORDER_RGBX: 247 *Rmask = masks[0]; 248 *Gmask = masks[1]; 249 *Bmask = masks[2]; 250 break; 251 case SDL_PACKEDORDER_ARGB: 252 *Amask = masks[0]; 253 *Rmask = masks[1]; 254 *Gmask = masks[2]; 255 *Bmask = masks[3]; 256 break; 257 case SDL_PACKEDORDER_RGBA: 258 *Rmask = masks[0]; 259 *Gmask = masks[1]; 260 *Bmask = masks[2]; 261 *Amask = masks[3]; 262 break; 263 case SDL_PACKEDORDER_XBGR: 264 *Bmask = masks[1]; 265 *Gmask = masks[2]; 266 *Rmask = masks[3]; 267 break; 268 case SDL_PACKEDORDER_BGRX: 269 *Bmask = masks[0]; 270 *Gmask = masks[1]; 271 *Rmask = masks[2]; 272 break; 273 case SDL_PACKEDORDER_BGRA: 274 *Bmask = masks[0]; 275 *Gmask = masks[1]; 276 *Rmask = masks[2]; 277 *Amask = masks[3]; 278 break; 279 case SDL_PACKEDORDER_ABGR: 280 *Amask = masks[0]; 281 *Bmask = masks[1]; 282 *Gmask = masks[2]; 283 *Rmask = masks[3]; 284 break; 285 default: 286 SDL_SetError("Unknown pixel format"); 287 return SDL_FALSE; 288 } 289 return SDL_TRUE; 290} 291 292Uint32 293SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, 294 Uint32 Amask) 295{ 296 switch (bpp) { 297 case 1: 298 /* SDL defaults to MSB ordering */ 299 return SDL_PIXELFORMAT_INDEX1MSB; 300 case 4: 301 /* SDL defaults to MSB ordering */ 302 return SDL_PIXELFORMAT_INDEX4MSB; 303 case 8: 304 if (Rmask == 0) { 305 return SDL_PIXELFORMAT_INDEX8; 306 } 307 if (Rmask == 0xE0 && 308 Gmask == 0x1C && 309 Bmask == 0x03 && 310 Amask == 0x00) { 311 return SDL_PIXELFORMAT_RGB332; 312 } 313 break; 314 case 12: 315 if (Rmask == 0) { 316 return SDL_PIXELFORMAT_RGB444; 317 } 318 if (Rmask == 0x0F00 && 319 Gmask == 0x00F0 && 320 Bmask == 0x000F && 321 Amask == 0x0000) { 322 return SDL_PIXELFORMAT_RGB444; 323 } 324 break; 325 case 15: 326 if (Rmask == 0) { 327 return SDL_PIXELFORMAT_RGB555; 328 } 329 /* Fall through to 16-bit checks */ 330 case 16: 331 if (Rmask == 0) { 332 return SDL_PIXELFORMAT_RGB565; 333 } 334 if (Rmask == 0x7C00 && 335 Gmask == 0x03E0 && 336 Bmask == 0x001F && 337 Amask == 0x0000) { 338 return SDL_PIXELFORMAT_RGB555; 339 } 340 if (Rmask == 0x001F && 341 Gmask == 0x03E0 && 342 Bmask == 0x7C00 && 343 Amask == 0x0000) { 344 return SDL_PIXELFORMAT_BGR555; 345 } 346 if (Rmask == 0x0F00 && 347 Gmask == 0x00F0 && 348 Bmask == 0x000F && 349 Amask == 0xF000) { 350 return SDL_PIXELFORMAT_ARGB4444; 351 } 352 if (Rmask == 0xF000 && 353 Gmask == 0x0F00 && 354 Bmask == 0x00F0 && 355 Amask == 0x000F) { 356 return SDL_PIXELFORMAT_RGBA4444; 357 } 358 if (Rmask == 0x000F && 359 Gmask == 0x00F0 && 360 Bmask == 0x0F00 && 361 Amask == 0xF000) { 362 return SDL_PIXELFORMAT_ABGR4444; 363 } 364 if (Rmask == 0x00F0 && 365 Gmask == 0x0F00 && 366 Bmask == 0xF000 && 367 Amask == 0x000F) { 368 return SDL_PIXELFORMAT_BGRA4444; 369 } 370 if (Rmask == 0x7C00 && 371 Gmask == 0x03E0 && 372 Bmask == 0x001F && 373 Amask == 0x8000) { 374 return SDL_PIXELFORMAT_ARGB1555; 375 } 376 if (Rmask == 0xF800 && 377 Gmask == 0x07C0 && 378 Bmask == 0x003E && 379 Amask == 0x0001) { 380 return SDL_PIXELFORMAT_RGBA5551; 381 } 382 if (Rmask == 0x001F && 383 Gmask == 0x03E0 && 384 Bmask == 0x7C00 && 385 Amask == 0x8000) { 386 return SDL_PIXELFORMAT_ABGR1555; 387 } 388 if (Rmask == 0x003E && 389 Gmask == 0x07C0 && 390 Bmask == 0xF800 && 391 Amask == 0x0001) { 392 return SDL_PIXELFORMAT_BGRA5551; 393 } 394 if (Rmask == 0xF800 && 395 Gmask == 0x07E0 && 396 Bmask == 0x001F && 397 Amask == 0x0000) { 398 return SDL_PIXELFORMAT_RGB565; 399 } 400 if (Rmask == 0x001F && 401 Gmask == 0x07E0 && 402 Bmask == 0xF800 && 403 Amask == 0x0000) { 404 return SDL_PIXELFORMAT_BGR565; 405 } 406 break; 407 case 24: 408 switch (Rmask) { 409 case 0: 410 case 0x00FF0000: 411#if SDL_BYTEORDER == SDL_BIG_ENDIAN 412 return SDL_PIXELFORMAT_RGB24; 413#else 414 return SDL_PIXELFORMAT_BGR24; 415#endif 416 case 0x000000FF: 417#if SDL_BYTEORDER == SDL_BIG_ENDIAN 418 return SDL_PIXELFORMAT_BGR24; 419#else 420 return SDL_PIXELFORMAT_RGB24; 421#endif 422 } 423 case 32: 424 if (Rmask == 0) { 425 return SDL_PIXELFORMAT_RGB888; 426 } 427 if (Rmask == 0x00FF0000 && 428 Gmask == 0x0000FF00 && 429 Bmask == 0x000000FF && 430 Amask == 0x00000000) { 431 return SDL_PIXELFORMAT_RGB888; 432 } 433 if (Rmask == 0xFF000000 && 434 Gmask == 0x00FF0000 && 435 Bmask == 0x0000FF00 && 436 Amask == 0x00000000) { 437 return SDL_PIXELFORMAT_RGBX8888; 438 } 439 if (Rmask == 0x000000FF && 440 Gmask == 0x0000FF00 && 441 Bmask == 0x00FF0000 && 442 Amask == 0x00000000) { 443 return SDL_PIXELFORMAT_BGR888; 444 } 445 if (Rmask == 0x0000FF00 && 446 Gmask == 0x00FF0000 && 447 Bmask == 0xFF000000 && 448 Amask == 0x00000000) { 449 return SDL_PIXELFORMAT_BGRX8888; 450 } 451 if (Rmask == 0x00FF0000 && 452 Gmask == 0x0000FF00 && 453 Bmask == 0x000000FF && 454 Amask == 0xFF000000) { 455 return SDL_PIXELFORMAT_ARGB8888; 456 } 457 if (Rmask == 0xFF000000 && 458 Gmask == 0x00FF0000 && 459 Bmask == 0x0000FF00 && 460 Amask == 0x000000FF) { 461 return SDL_PIXELFORMAT_RGBA8888; 462 } 463 if (Rmask == 0x000000FF && 464 Gmask == 0x0000FF00 && 465 Bmask == 0x00FF0000 && 466 Amask == 0xFF000000) { 467 return SDL_PIXELFORMAT_ABGR8888; 468 } 469 if (Rmask == 0x0000FF00 && 470 Gmask == 0x00FF0000 && 471 Bmask == 0xFF000000 && 472 Amask == 0x000000FF) { 473 return SDL_PIXELFORMAT_BGRA8888; 474 } 475 if (Rmask == 0x3FF00000 && 476 Gmask == 0x000FFC00 && 477 Bmask == 0x000003FF && 478 Amask == 0xC0000000) { 479 return SDL_PIXELFORMAT_ARGB2101010; 480 } 481 } 482 return SDL_PIXELFORMAT_UNKNOWN; 483} 484 485static SDL_PixelFormat *formats; 486 487SDL_PixelFormat * 488SDL_AllocFormat(Uint32 pixel_format) 489{ 490 SDL_PixelFormat *format; 491 492 /* Look it up in our list of previously allocated formats */ 493 for (format = formats; format; format = format->next) { 494 if (pixel_format == format->format) { 495 ++format->refcount; 496 return format; 497 } 498 } 499 500 /* Allocate an empty pixel format structure, and initialize it */ 501 format = SDL_malloc(sizeof(*format)); 502 if (format == NULL) { 503 SDL_OutOfMemory(); 504 return NULL; 505 } 506 if (SDL_InitFormat(format, pixel_format) < 0) { 507 SDL_free(format); 508 SDL_InvalidParamError("format"); 509 return NULL; 510 } 511 512 if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) { 513 /* Cache the RGB formats */ 514 format->next = formats; 515 formats = format; 516 } 517 return format; 518} 519 520int 521SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format) 522{ 523 int bpp; 524 Uint32 Rmask, Gmask, Bmask, Amask; 525 Uint32 mask; 526 527 if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp, 528 &Rmask, &Gmask, &Bmask, &Amask)) { 529 return -1; 530 } 531 532 /* Set up the format */ 533 SDL_zerop(format); 534 format->format = pixel_format; 535 format->BitsPerPixel = bpp; 536 format->BytesPerPixel = (bpp + 7) / 8; 537 538 format->Rmask = Rmask; 539 format->Rshift = 0; 540 format->Rloss = 8; 541 if (Rmask) { 542 for (mask = Rmask; !(mask & 0x01); mask >>= 1) 543 ++format->Rshift; 544 for (; (mask & 0x01); mask >>= 1) 545 --format->Rloss; 546 } 547 548 format->Gmask = Gmask; 549 format->Gshift = 0; 550 format->Gloss = 8; 551 if (Gmask) { 552 for (mask = Gmask; !(mask & 0x01); mask >>= 1) 553 ++format->Gshift; 554 for (; (mask & 0x01); mask >>= 1) 555 --format->Gloss; 556 } 557 558 format->Bmask = Bmask; 559 format->Bshift = 0; 560 format->Bloss = 8; 561 if (Bmask) { 562 for (mask = Bmask; !(mask & 0x01); mask >>= 1) 563 ++format->Bshift; 564 for (; (mask & 0x01); mask >>= 1) 565 --format->Bloss; 566 } 567 568 format->Amask = Amask; 569 format->Ashift = 0; 570 format->Aloss = 8; 571 if (Amask) { 572 for (mask = Amask; !(mask & 0x01); mask >>= 1) 573 ++format->Ashift; 574 for (; (mask & 0x01); mask >>= 1) 575 --format->Aloss; 576 } 577 578 format->palette = NULL; 579 format->refcount = 1; 580 format->next = NULL; 581 582 return 0; 583} 584 585void 586SDL_FreeFormat(SDL_PixelFormat *format) 587{ 588 SDL_PixelFormat *prev; 589 590 if (!format) { 591 SDL_InvalidParamError("format"); 592 return; 593 } 594 if (--format->refcount > 0) { 595 return; 596 } 597 598 /* Remove this format from our list */ 599 if (format == formats) { 600 formats = format->next; 601 } else if (formats) { 602 for (prev = formats; prev->next; prev = prev->next) { 603 if (prev->next == format) { 604 prev->next = format->next; 605 break; 606 } 607 } 608 } 609 610 if (format->palette) { 611 SDL_FreePalette(format->palette); 612 } 613 SDL_free(format); 614} 615 616SDL_Palette * 617SDL_AllocPalette(int ncolors) 618{ 619 SDL_Palette *palette; 620 621 /* Input validation */ 622 if (ncolors < 1) { 623 SDL_InvalidParamError("ncolors"); 624 return NULL; 625 } 626 627 palette = (SDL_Palette *) SDL_malloc(sizeof(*palette)); 628 if (!palette) { 629 SDL_OutOfMemory(); 630 return NULL; 631 } 632 palette->colors = 633 (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors)); 634 if (!palette->colors) { 635 SDL_free(palette); 636 return NULL; 637 } 638 palette->ncolors = ncolors; 639 palette->version = 1; 640 palette->refcount = 1; 641 642 SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors)); 643 644 return palette; 645} 646 647int 648SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette) 649{ 650 if (!format) { 651 return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format"); 652 } 653 654 if (palette && palette->ncolors != (1 << format->BitsPerPixel)) { 655 return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format"); 656 } 657 658 if (format->palette == palette) { 659 return 0; 660 } 661 662 if (format->palette) { 663 SDL_FreePalette(format->palette); 664 } 665 666 format->palette = palette; 667 668 if (format->palette) { 669 ++format->palette->refcount; 670 } 671 672 return 0; 673} 674 675int 676SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors, 677 int firstcolor, int ncolors) 678{ 679 int status = 0; 680 681 /* Verify the parameters */ 682 if (!palette) { 683 return -1; 684 } 685 if (ncolors > (palette->ncolors - firstcolor)) { 686 ncolors = (palette->ncolors - firstcolor); 687 status = -1; 688 } 689 690 if (colors != (palette->colors + firstcolor)) { 691 SDL_memcpy(palette->colors + firstcolor, colors, 692 ncolors * sizeof(*colors)); 693 } 694 ++palette->version; 695 if (!palette->version) { 696 palette->version = 1; 697 } 698 699 return status; 700} 701 702void 703SDL_FreePalette(SDL_Palette * palette) 704{ 705 if (!palette) { 706 SDL_InvalidParamError("palette"); 707 return; 708 } 709 if (--palette->refcount > 0) { 710 return; 711 } 712 SDL_free(palette->colors); 713 SDL_free(palette); 714} 715 716/* 717 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors 718 */ 719void 720SDL_DitherColors(SDL_Color * colors, int bpp) 721{ 722 int i; 723 if (bpp != 8) 724 return; /* only 8bpp supported right now */ 725 726 for (i = 0; i < 256; i++) { 727 int r, g, b; 728 /* map each bit field to the full [0, 255] interval, 729 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ 730 r = i & 0xe0; 731 r |= r >> 3 | r >> 6; 732 colors[i].r = r; 733 g = (i << 3) & 0xe0; 734 g |= g >> 3 | g >> 6; 735 colors[i].g = g; 736 b = i & 0x3; 737 b |= b << 2; 738 b |= b << 4; 739 colors[i].b = b; 740 colors[i].a = SDL_ALPHA_OPAQUE; 741 } 742} 743 744/* 745 * Calculate the pad-aligned scanline width of a surface 746 */ 747int 748SDL_CalculatePitch(SDL_Surface * surface) 749{ 750 int pitch; 751 752 /* Surface should be 4-byte aligned for speed */ 753 pitch = surface->w * surface->format->BytesPerPixel; 754 switch (surface->format->BitsPerPixel) { 755 case 1: 756 pitch = (pitch + 7) / 8; 757 break; 758 case 4: 759 pitch = (pitch + 1) / 2; 760 break; 761 default: 762 break; 763 } 764 pitch = (pitch + 3) & ~3; /* 4-byte aligning */ 765 return (pitch); 766} 767 768/* 769 * Match an RGB value to a particular palette index 770 */ 771Uint8 772SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 773{ 774 /* Do colorspace distance matching */ 775 unsigned int smallest; 776 unsigned int distance; 777 int rd, gd, bd, ad; 778 int i; 779 Uint8 pixel = 0; 780 781 smallest = ~0; 782 for (i = 0; i < pal->ncolors; ++i) { 783 rd = pal->colors[i].r - r; 784 gd = pal->colors[i].g - g; 785 bd = pal->colors[i].b - b; 786 ad = pal->colors[i].a - a; 787 distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad); 788 if (distance < smallest) { 789 pixel = i; 790 if (distance == 0) { /* Perfect match! */ 791 break; 792 } 793 smallest = distance; 794 } 795 } 796 return (pixel); 797} 798 799/* Find the opaque pixel value corresponding to an RGB triple */ 800Uint32 801SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b) 802{ 803 if (format->palette == NULL) { 804 return (r >> format->Rloss) << format->Rshift 805 | (g >> format->Gloss) << format->Gshift 806 | (b >> format->Bloss) << format->Bshift | format->Amask; 807 } else { 808 return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE); 809 } 810} 811 812/* Find the pixel value corresponding to an RGBA quadruple */ 813Uint32 814SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b, 815 Uint8 a) 816{ 817 if (format->palette == NULL) { 818 return (r >> format->Rloss) << format->Rshift 819 | (g >> format->Gloss) << format->Gshift 820 | (b >> format->Bloss) << format->Bshift 821 | ((a >> format->Aloss) << format->Ashift & format->Amask); 822 } else { 823 return SDL_FindColor(format->palette, r, g, b, a); 824 } 825} 826 827void 828SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g, 829 Uint8 * b) 830{ 831 if (format->palette == NULL) { 832 unsigned v; 833 v = (pixel & format->Rmask) >> format->Rshift; 834 *r = SDL_expand_byte[format->Rloss][v]; 835 v = (pixel & format->Gmask) >> format->Gshift; 836 *g = SDL_expand_byte[format->Gloss][v]; 837 v = (pixel & format->Bmask) >> format->Bshift; 838 *b = SDL_expand_byte[format->Bloss][v]; 839 } else { 840 if (pixel < (unsigned)format->palette->ncolors) { 841 *r = format->palette->colors[pixel].r; 842 *g = format->palette->colors[pixel].g; 843 *b = format->palette->colors[pixel].b; 844 } else { 845 *r = *g = *b = 0; 846 } 847 } 848} 849 850void 851SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format, 852 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a) 853{ 854 if (format->palette == NULL) { 855 unsigned v; 856 v = (pixel & format->Rmask) >> format->Rshift; 857 *r = SDL_expand_byte[format->Rloss][v]; 858 v = (pixel & format->Gmask) >> format->Gshift; 859 *g = SDL_expand_byte[format->Gloss][v]; 860 v = (pixel & format->Bmask) >> format->Bshift; 861 *b = SDL_expand_byte[format->Bloss][v]; 862 v = (pixel & format->Amask) >> format->Ashift; 863 *a = SDL_expand_byte[format->Aloss][v]; 864 } else { 865 if (pixel < (unsigned)format->palette->ncolors) { 866 *r = format->palette->colors[pixel].r; 867 *g = format->palette->colors[pixel].g; 868 *b = format->palette->colors[pixel].b; 869 *a = format->palette->colors[pixel].a; 870 } else { 871 *r = *g = *b = *a = 0; 872 } 873 } 874} 875 876/* Map from Palette to Palette */ 877static Uint8 * 878Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical) 879{ 880 Uint8 *map; 881 int i; 882 883 if (identical) { 884 if (src->ncolors <= dst->ncolors) { 885 /* If an identical palette, no need to map */ 886 if (src == dst 887 || 888 (SDL_memcmp 889 (src->colors, dst->colors, 890 src->ncolors * sizeof(SDL_Color)) == 0)) { 891 *identical = 1; 892 return (NULL); 893 } 894 } 895 *identical = 0; 896 } 897 map = (Uint8 *) SDL_malloc(src->ncolors); 898 if (map == NULL) { 899 SDL_OutOfMemory(); 900 return (NULL); 901 } 902 for (i = 0; i < src->ncolors; ++i) { 903 map[i] = SDL_FindColor(dst, 904 src->colors[i].r, src->colors[i].g, 905 src->colors[i].b, src->colors[i].a); 906 } 907 return (map); 908} 909 910/* Map from Palette to BitField */ 911static Uint8 * 912Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod, 913 SDL_PixelFormat * dst) 914{ 915 Uint8 *map; 916 int i; 917 int bpp; 918 SDL_Palette *pal = src->palette; 919 920 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); 921 map = (Uint8 *) SDL_malloc(pal->ncolors * bpp); 922 if (map == NULL) { 923 SDL_OutOfMemory(); 924 return (NULL); 925 } 926 927 /* We memory copy to the pixel map so the endianness is preserved */ 928 for (i = 0; i < pal->ncolors; ++i) { 929 Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255); 930 Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255); 931 Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255); 932 Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255); 933 ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A); 934 } 935 return (map); 936} 937 938/* Map from BitField to Dithered-Palette to Palette */ 939static Uint8 * 940MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical) 941{ 942 /* Generate a 256 color dither palette */ 943 SDL_Palette dithered; 944 SDL_Color colors[256]; 945 SDL_Palette *pal = dst->palette; 946 947 dithered.ncolors = 256; 948 SDL_DitherColors(colors, 8); 949 dithered.colors = colors; 950 return (Map1to1(&dithered, pal, identical)); 951} 952 953SDL_BlitMap * 954SDL_AllocBlitMap(void) 955{ 956 SDL_BlitMap *map; 957 958 /* Allocate the empty map */ 959 map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map)); 960 if (map == NULL) { 961 SDL_OutOfMemory(); 962 return (NULL); 963 } 964 map->info.r = 0xFF; 965 map->info.g = 0xFF; 966 map->info.b = 0xFF; 967 map->info.a = 0xFF; 968 969 /* It's ready to go */ 970 return (map); 971} 972 973void 974SDL_InvalidateMap(SDL_BlitMap * map) 975{ 976 if (!map) { 977 return; 978 } 979 if (map->dst) { 980 /* Release our reference to the surface - see the note below */ 981 if (--map->dst->refcount <= 0) { 982 SDL_FreeSurface(map->dst); 983 } 984 } 985 map->dst = NULL; 986 map->src_palette_version = 0; 987 map->dst_palette_version = 0; 988 SDL_free(map->info.table); 989 map->info.table = NULL; 990} 991 992int 993SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst) 994{ 995 SDL_PixelFormat *srcfmt; 996 SDL_PixelFormat *dstfmt; 997 SDL_BlitMap *map; 998 999 /* Clear out any previous mapping */ 1000 map = src->map; 1001 if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { 1002 SDL_UnRLESurface(src, 1); 1003 } 1004 SDL_InvalidateMap(map); 1005 1006 /* Figure out what kind of mapping we're doing */ 1007 map->identity = 0; 1008 srcfmt = src->format; 1009 dstfmt = dst->format; 1010 if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) { 1011 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) { 1012 /* Palette --> Palette */ 1013 map->info.table = 1014 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity); 1015 if (!map->identity) { 1016 if (map->info.table == NULL) { 1017 return (-1); 1018 } 1019 } 1020 if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel) 1021 map->identity = 0; 1022 } else { 1023 /* Palette --> BitField */ 1024 map->info.table = 1025 Map1toN(srcfmt, src->map->info.r, src->map->info.g, 1026 src->map->info.b, src->map->info.a, dstfmt); 1027 if (map->info.table == NULL) { 1028 return (-1); 1029 } 1030 } 1031 } else { 1032 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) { 1033 /* BitField --> Palette */ 1034 map->info.table = MapNto1(srcfmt, dstfmt, &map->identity); 1035 if (!map->identity) { 1036 if (map->info.table == NULL) { 1037 return (-1); 1038 } 1039 } 1040 map->identity = 0; /* Don't optimize to copy */ 1041 } else { 1042 /* BitField --> BitField */ 1043 if (srcfmt == dstfmt) { 1044 map->identity = 1; 1045 } 1046 } 1047 } 1048 1049 map->dst = dst; 1050 1051 if (map->dst) { 1052 /* Keep a reference to this surface so it doesn't get deleted 1053 while we're still pointing at it. 1054 1055 A better method would be for the destination surface to keep 1056 track of surfaces that are mapped to it and automatically 1057 invalidate them when it is freed, but this will do for now. 1058 */ 1059 ++map->dst->refcount; 1060 } 1061 1062 if (dstfmt->palette) { 1063 map->dst_palette_version = dstfmt->palette->version; 1064 } else { 1065 map->dst_palette_version = 0; 1066 } 1067 1068 if (srcfmt->palette) { 1069 map->src_palette_version = srcfmt->palette->version; 1070 } else { 1071 map->src_palette_version = 0; 1072 } 1073 1074 /* Choose your blitters wisely */ 1075 return (SDL_CalculateBlit(src)); 1076} 1077 1078void 1079SDL_FreeBlitMap(SDL_BlitMap * map) 1080{ 1081 if (map) { 1082 SDL_InvalidateMap(map); 1083 SDL_free(map); 1084 } 1085} 1086 1087void 1088SDL_CalculateGammaRamp(float gamma, Uint16 * ramp) 1089{ 1090 int i; 1091 1092 /* Input validation */ 1093 if (gamma < 0.0f ) { 1094 SDL_InvalidParamError("gamma"); 1095 return; 1096 } 1097 if (ramp == NULL) { 1098 SDL_InvalidParamError("ramp"); 1099 return; 1100 } 1101 1102 /* 0.0 gamma is all black */ 1103 if (gamma == 0.0f) { 1104 for (i = 0; i < 256; ++i) { 1105 ramp[i] = 0; 1106 } 1107 return; 1108 } else if (gamma == 1.0f) { 1109 /* 1.0 gamma is identity */ 1110 for (i = 0; i < 256; ++i) { 1111 ramp[i] = (i << 8) | i; 1112 } 1113 return; 1114 } else { 1115 /* Calculate a real gamma ramp */ 1116 int value; 1117 gamma = 1.0f / gamma; 1118 for (i = 0; i < 256; ++i) { 1119 value = 1120 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5); 1121 if (value > 65535) { 1122 value = 65535; 1123 } 1124 ramp[i] = (Uint16) value; 1125 } 1126 } 1127} 1128 1129/* vi: set ts=4 sw=4 expandtab: */