2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 /* General (mostly internal) pixel/color manipulation routines for SDL */
25 #include "SDL_endian.h"
26 #include "SDL_video.h"
27 #include "SDL_sysvideo.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_RLEaccel_c.h"
33 /* Lookup tables to expand partial bytes to the full 0..255 range */
35 static Uint8 lookup_0[] = {
36 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
39 static Uint8 lookup_1[] = {
40 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, 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
43 static Uint8 lookup_2[] = {
44 0, 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
47 static Uint8 lookup_3[] = {
48 0, 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
51 static Uint8 lookup_4[] = {
52 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
55 static Uint8 lookup_5[] = {
56 0, 36, 72, 109, 145, 182, 218, 255
59 static Uint8 lookup_6[] = {
63 static Uint8 lookup_7[] = {
67 static Uint8 lookup_8[] = {
71 Uint8* SDL_expand_byte[9] = {
83 /* Helper functions */
86 SDL_GetPixelFormatName(Uint32 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)
129 return "SDL_PIXELFORMAT_UNKNOWN";
134 SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
135 Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
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");
145 /* Initialize the values here */
146 if (SDL_BYTESPERPIXEL(format) <= 2) {
147 *bpp = SDL_BITSPERPIXEL(format);
149 *bpp = SDL_BYTESPERPIXEL(format) * 8;
151 *Rmask = *Gmask = *Bmask = *Amask = 0;
153 if (format == SDL_PIXELFORMAT_RGB24) {
154 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
166 if (format == SDL_PIXELFORMAT_BGR24) {
167 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
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 */
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;
193 case SDL_PACKEDLAYOUT_4444:
194 masks[0] = 0x0000F000;
195 masks[1] = 0x00000F00;
196 masks[2] = 0x000000F0;
197 masks[3] = 0x0000000F;
199 case SDL_PACKEDLAYOUT_1555:
200 masks[0] = 0x00008000;
201 masks[1] = 0x00007C00;
202 masks[2] = 0x000003E0;
203 masks[3] = 0x0000001F;
205 case SDL_PACKEDLAYOUT_5551:
206 masks[0] = 0x0000F800;
207 masks[1] = 0x000007C0;
208 masks[2] = 0x0000003E;
209 masks[3] = 0x00000001;
211 case SDL_PACKEDLAYOUT_565:
212 masks[0] = 0x00000000;
213 masks[1] = 0x0000F800;
214 masks[2] = 0x000007E0;
215 masks[3] = 0x0000001F;
217 case SDL_PACKEDLAYOUT_8888:
218 masks[0] = 0xFF000000;
219 masks[1] = 0x00FF0000;
220 masks[2] = 0x0000FF00;
221 masks[3] = 0x000000FF;
223 case SDL_PACKEDLAYOUT_2101010:
224 masks[0] = 0xC0000000;
225 masks[1] = 0x3FF00000;
226 masks[2] = 0x000FFC00;
227 masks[3] = 0x000003FF;
229 case SDL_PACKEDLAYOUT_1010102:
230 masks[0] = 0xFFC00000;
231 masks[1] = 0x003FF000;
232 masks[2] = 0x00000FFC;
233 masks[3] = 0x00000003;
236 SDL_SetError("Unknown pixel format");
240 switch (SDL_PIXELORDER(format)) {
241 case SDL_PACKEDORDER_XRGB:
246 case SDL_PACKEDORDER_RGBX:
251 case SDL_PACKEDORDER_ARGB:
257 case SDL_PACKEDORDER_RGBA:
263 case SDL_PACKEDORDER_XBGR:
268 case SDL_PACKEDORDER_BGRX:
273 case SDL_PACKEDORDER_BGRA:
279 case SDL_PACKEDORDER_ABGR:
286 SDL_SetError("Unknown pixel format");
293 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
298 /* SDL defaults to MSB ordering */
299 return SDL_PIXELFORMAT_INDEX1MSB;
301 /* SDL defaults to MSB ordering */
302 return SDL_PIXELFORMAT_INDEX4MSB;
305 return SDL_PIXELFORMAT_INDEX8;
311 return SDL_PIXELFORMAT_RGB332;
316 return SDL_PIXELFORMAT_RGB444;
318 if (Rmask == 0x0F00 &&
322 return SDL_PIXELFORMAT_RGB444;
327 return SDL_PIXELFORMAT_RGB555;
329 /* Fall through to 16-bit checks */
332 return SDL_PIXELFORMAT_RGB565;
334 if (Rmask == 0x7C00 &&
338 return SDL_PIXELFORMAT_RGB555;
340 if (Rmask == 0x001F &&
344 return SDL_PIXELFORMAT_BGR555;
346 if (Rmask == 0x0F00 &&
350 return SDL_PIXELFORMAT_ARGB4444;
352 if (Rmask == 0xF000 &&
356 return SDL_PIXELFORMAT_RGBA4444;
358 if (Rmask == 0x000F &&
362 return SDL_PIXELFORMAT_ABGR4444;
364 if (Rmask == 0x00F0 &&
368 return SDL_PIXELFORMAT_BGRA4444;
370 if (Rmask == 0x7C00 &&
374 return SDL_PIXELFORMAT_ARGB1555;
376 if (Rmask == 0xF800 &&
380 return SDL_PIXELFORMAT_RGBA5551;
382 if (Rmask == 0x001F &&
386 return SDL_PIXELFORMAT_ABGR1555;
388 if (Rmask == 0x003E &&
392 return SDL_PIXELFORMAT_BGRA5551;
394 if (Rmask == 0xF800 &&
398 return SDL_PIXELFORMAT_RGB565;
400 if (Rmask == 0x001F &&
404 return SDL_PIXELFORMAT_BGR565;
411 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
412 return SDL_PIXELFORMAT_RGB24;
414 return SDL_PIXELFORMAT_BGR24;
417 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
418 return SDL_PIXELFORMAT_BGR24;
420 return SDL_PIXELFORMAT_RGB24;
425 return SDL_PIXELFORMAT_RGB888;
427 if (Rmask == 0x00FF0000 &&
428 Gmask == 0x0000FF00 &&
429 Bmask == 0x000000FF &&
430 Amask == 0x00000000) {
431 return SDL_PIXELFORMAT_RGB888;
433 if (Rmask == 0xFF000000 &&
434 Gmask == 0x00FF0000 &&
435 Bmask == 0x0000FF00 &&
436 Amask == 0x00000000) {
437 return SDL_PIXELFORMAT_RGBX8888;
439 if (Rmask == 0x000000FF &&
440 Gmask == 0x0000FF00 &&
441 Bmask == 0x00FF0000 &&
442 Amask == 0x00000000) {
443 return SDL_PIXELFORMAT_BGR888;
445 if (Rmask == 0x0000FF00 &&
446 Gmask == 0x00FF0000 &&
447 Bmask == 0xFF000000 &&
448 Amask == 0x00000000) {
449 return SDL_PIXELFORMAT_BGRX8888;
451 if (Rmask == 0x00FF0000 &&
452 Gmask == 0x0000FF00 &&
453 Bmask == 0x000000FF &&
454 Amask == 0xFF000000) {
455 return SDL_PIXELFORMAT_ARGB8888;
457 if (Rmask == 0xFF000000 &&
458 Gmask == 0x00FF0000 &&
459 Bmask == 0x0000FF00 &&
460 Amask == 0x000000FF) {
461 return SDL_PIXELFORMAT_RGBA8888;
463 if (Rmask == 0x000000FF &&
464 Gmask == 0x0000FF00 &&
465 Bmask == 0x00FF0000 &&
466 Amask == 0xFF000000) {
467 return SDL_PIXELFORMAT_ABGR8888;
469 if (Rmask == 0x0000FF00 &&
470 Gmask == 0x00FF0000 &&
471 Bmask == 0xFF000000 &&
472 Amask == 0x000000FF) {
473 return SDL_PIXELFORMAT_BGRA8888;
475 if (Rmask == 0x3FF00000 &&
476 Gmask == 0x000FFC00 &&
477 Bmask == 0x000003FF &&
478 Amask == 0xC0000000) {
479 return SDL_PIXELFORMAT_ARGB2101010;
482 return SDL_PIXELFORMAT_UNKNOWN;
485 static SDL_PixelFormat *formats;
488 SDL_AllocFormat(Uint32 pixel_format)
490 SDL_PixelFormat *format;
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) {
500 /* Allocate an empty pixel format structure, and initialize it */
501 format = SDL_malloc(sizeof(*format));
502 if (format == NULL) {
506 if (SDL_InitFormat(format, pixel_format) < 0) {
508 SDL_InvalidParamError("format");
512 if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
513 /* Cache the RGB formats */
514 format->next = formats;
521 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
524 Uint32 Rmask, Gmask, Bmask, Amask;
527 if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
528 &Rmask, &Gmask, &Bmask, &Amask)) {
532 /* Set up the format */
534 format->format = pixel_format;
535 format->BitsPerPixel = bpp;
536 format->BytesPerPixel = (bpp + 7) / 8;
538 format->Rmask = Rmask;
542 for (mask = Rmask; !(mask & 0x01); mask >>= 1)
544 for (; (mask & 0x01); mask >>= 1)
548 format->Gmask = Gmask;
552 for (mask = Gmask; !(mask & 0x01); mask >>= 1)
554 for (; (mask & 0x01); mask >>= 1)
558 format->Bmask = Bmask;
562 for (mask = Bmask; !(mask & 0x01); mask >>= 1)
564 for (; (mask & 0x01); mask >>= 1)
568 format->Amask = Amask;
572 for (mask = Amask; !(mask & 0x01); mask >>= 1)
574 for (; (mask & 0x01); mask >>= 1)
578 format->palette = NULL;
579 format->refcount = 1;
586 SDL_FreeFormat(SDL_PixelFormat *format)
588 SDL_PixelFormat *prev;
591 SDL_InvalidParamError("format");
594 if (--format->refcount > 0) {
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;
610 if (format->palette) {
611 SDL_FreePalette(format->palette);
617 SDL_AllocPalette(int ncolors)
619 SDL_Palette *palette;
621 /* Input validation */
623 SDL_InvalidParamError("ncolors");
627 palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
633 (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
634 if (!palette->colors) {
638 palette->ncolors = ncolors;
639 palette->version = 1;
640 palette->refcount = 1;
642 SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
648 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
651 return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
654 if (palette && palette->ncolors != (1 << format->BitsPerPixel)) {
655 return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
658 if (format->palette == palette) {
662 if (format->palette) {
663 SDL_FreePalette(format->palette);
666 format->palette = palette;
668 if (format->palette) {
669 ++format->palette->refcount;
676 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
677 int firstcolor, int ncolors)
681 /* Verify the parameters */
685 if (ncolors > (palette->ncolors - firstcolor)) {
686 ncolors = (palette->ncolors - firstcolor);
690 if (colors != (palette->colors + firstcolor)) {
691 SDL_memcpy(palette->colors + firstcolor, colors,
692 ncolors * sizeof(*colors));
695 if (!palette->version) {
696 palette->version = 1;
703 SDL_FreePalette(SDL_Palette * palette)
706 SDL_InvalidParamError("palette");
709 if (--palette->refcount > 0) {
712 SDL_free(palette->colors);
717 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
720 SDL_DitherColors(SDL_Color * colors, int bpp)
724 return; /* only 8bpp supported right now */
726 for (i = 0; i < 256; i++) {
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) */
731 r |= r >> 3 | r >> 6;
734 g |= g >> 3 | g >> 6;
740 colors[i].a = SDL_ALPHA_OPAQUE;
745 * Calculate the pad-aligned scanline width of a surface
748 SDL_CalculatePitch(SDL_Surface * surface)
752 /* Surface should be 4-byte aligned for speed */
753 pitch = surface->w * surface->format->BytesPerPixel;
754 switch (surface->format->BitsPerPixel) {
756 pitch = (pitch + 7) / 8;
759 pitch = (pitch + 1) / 2;
764 pitch = (pitch + 3) & ~3; /* 4-byte aligning */
769 * Match an RGB value to a particular palette index
772 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
774 /* Do colorspace distance matching */
775 unsigned int smallest;
776 unsigned int distance;
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) {
790 if (distance == 0) { /* Perfect match! */
799 /* Find the opaque pixel value corresponding to an RGB triple */
801 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
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;
808 return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
812 /* Find the pixel value corresponding to an RGBA quadruple */
814 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
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);
823 return SDL_FindColor(format->palette, r, g, b, a);
828 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
831 if (format->palette == NULL) {
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];
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;
851 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
852 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
854 if (format->palette == NULL) {
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];
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;
871 *r = *g = *b = *a = 0;
876 /* Map from Palette to Palette */
878 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
884 if (src->ncolors <= dst->ncolors) {
885 /* If an identical palette, no need to map */
889 (src->colors, dst->colors,
890 src->ncolors * sizeof(SDL_Color)) == 0)) {
897 map = (Uint8 *) SDL_malloc(src->ncolors);
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);
910 /* Map from Palette to BitField */
912 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
913 SDL_PixelFormat * dst)
918 SDL_Palette *pal = src->palette;
920 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
921 map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
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);
938 /* Map from BitField to Dithered-Palette to Palette */
940 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
942 /* Generate a 256 color dither palette */
943 SDL_Palette dithered;
944 SDL_Color colors[256];
945 SDL_Palette *pal = dst->palette;
947 dithered.ncolors = 256;
948 SDL_DitherColors(colors, 8);
949 dithered.colors = colors;
950 return (Map1to1(&dithered, pal, identical));
954 SDL_AllocBlitMap(void)
958 /* Allocate the empty map */
959 map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
969 /* It's ready to go */
974 SDL_InvalidateMap(SDL_BlitMap * map)
980 /* Release our reference to the surface - see the note below */
981 if (--map->dst->refcount <= 0) {
982 SDL_FreeSurface(map->dst);
986 map->src_palette_version = 0;
987 map->dst_palette_version = 0;
988 SDL_free(map->info.table);
989 map->info.table = NULL;
993 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
995 SDL_PixelFormat *srcfmt;
996 SDL_PixelFormat *dstfmt;
999 /* Clear out any previous mapping */
1001 if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
1002 SDL_UnRLESurface(src, 1);
1004 SDL_InvalidateMap(map);
1006 /* Figure out what kind of mapping we're doing */
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 */
1014 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
1015 if (!map->identity) {
1016 if (map->info.table == NULL) {
1020 if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
1023 /* Palette --> BitField */
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) {
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) {
1040 map->identity = 0; /* Don't optimize to copy */
1042 /* BitField --> BitField */
1043 if (srcfmt == dstfmt) {
1052 /* Keep a reference to this surface so it doesn't get deleted
1053 while we're still pointing at it.
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.
1059 ++map->dst->refcount;
1062 if (dstfmt->palette) {
1063 map->dst_palette_version = dstfmt->palette->version;
1065 map->dst_palette_version = 0;
1068 if (srcfmt->palette) {
1069 map->src_palette_version = srcfmt->palette->version;
1071 map->src_palette_version = 0;
1074 /* Choose your blitters wisely */
1075 return (SDL_CalculateBlit(src));
1079 SDL_FreeBlitMap(SDL_BlitMap * map)
1082 SDL_InvalidateMap(map);
1088 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
1092 /* Input validation */
1093 if (gamma < 0.0f ) {
1094 SDL_InvalidParamError("gamma");
1098 SDL_InvalidParamError("ramp");
1102 /* 0.0 gamma is all black */
1103 if (gamma == 0.0f) {
1104 SDL_memset(ramp, 0, 256 * sizeof(Uint16));
1106 } else if (gamma == 1.0f) {
1107 /* 1.0 gamma is identity */
1108 for (i = 0; i < 256; ++i) {
1109 ramp[i] = (i << 8) | i;
1113 /* Calculate a real gamma ramp */
1115 gamma = 1.0f / gamma;
1116 for (i = 0; i < 256; ++i) {
1118 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
1119 if (value > 65535) {
1122 ramp[i] = (Uint16) value;
1127 /* vi: set ts=4 sw=4 expandtab: */