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