src/video/SDL_bmp.c
changeset 9126 08f3b56969b1
parent 9001 c750aab87e82
child 9334 5eb5ab33286e
equal deleted inserted replaced
9125:e004bdb812ce 9126:08f3b56969b1
    83     SDL_bool was_error;
    83     SDL_bool was_error;
    84     Sint64 fp_offset = 0;
    84     Sint64 fp_offset = 0;
    85     int bmpPitch;
    85     int bmpPitch;
    86     int i, pad;
    86     int i, pad;
    87     SDL_Surface *surface;
    87     SDL_Surface *surface;
    88     Uint32 Rmask;
    88     Uint32 Rmask = 0;
    89     Uint32 Gmask;
    89     Uint32 Gmask = 0;
    90     Uint32 Bmask;
    90     Uint32 Bmask = 0;
    91     Uint32 Amask;
    91     Uint32 Amask = 0;
    92     SDL_Palette *palette;
    92     SDL_Palette *palette;
    93     Uint8 *bits;
    93     Uint8 *bits;
    94     Uint8 *top, *end;
    94     Uint8 *top, *end;
    95     SDL_bool topDown;
    95     SDL_bool topDown;
    96     int ExpandBMP;
    96     int ExpandBMP;
       
    97     SDL_bool haveRGBMasks = SDL_FALSE;
       
    98     SDL_bool haveAlphaMask = SDL_FALSE;
    97     SDL_bool correctAlpha = SDL_FALSE;
    99     SDL_bool correctAlpha = SDL_FALSE;
    98 
   100 
    99     /* The Win32 BMP file header (14 bytes) */
   101     /* The Win32 BMP file header (14 bytes) */
   100     char magic[2];
   102     char magic[2];
   101     /* Uint32 bfSize = 0; */
   103     /* Uint32 bfSize = 0; */
   142     /* bfReserved2 = */ SDL_ReadLE16(src);
   144     /* bfReserved2 = */ SDL_ReadLE16(src);
   143     bfOffBits = SDL_ReadLE32(src);
   145     bfOffBits = SDL_ReadLE32(src);
   144 
   146 
   145     /* Read the Win32 BITMAPINFOHEADER */
   147     /* Read the Win32 BITMAPINFOHEADER */
   146     biSize = SDL_ReadLE32(src);
   148     biSize = SDL_ReadLE32(src);
   147     if (biSize == 12) {
   149     if (biSize == 12) {   /* really old BITMAPCOREHEADER */
   148         biWidth = (Uint32) SDL_ReadLE16(src);
   150         biWidth = (Uint32) SDL_ReadLE16(src);
   149         biHeight = (Uint32) SDL_ReadLE16(src);
   151         biHeight = (Uint32) SDL_ReadLE16(src);
   150         /* biPlanes = */ SDL_ReadLE16(src);
   152         /* biPlanes = */ SDL_ReadLE16(src);
   151         biBitCount = SDL_ReadLE16(src);
   153         biBitCount = SDL_ReadLE16(src);
   152         biCompression = BI_RGB;
   154         biCompression = BI_RGB;
   153     } else {
   155     } else if (biSize >= 40) {  /* some version of BITMAPINFOHEADER */
   154         const unsigned int headerSize = 40;
   156         Uint32 headerSize;
   155 
       
   156         biWidth = SDL_ReadLE32(src);
   157         biWidth = SDL_ReadLE32(src);
   157         biHeight = SDL_ReadLE32(src);
   158         biHeight = SDL_ReadLE32(src);
   158         /* biPlanes = */ SDL_ReadLE16(src);
   159         /* biPlanes = */ SDL_ReadLE16(src);
   159         biBitCount = SDL_ReadLE16(src);
   160         biBitCount = SDL_ReadLE16(src);
   160         biCompression = SDL_ReadLE32(src);
   161         biCompression = SDL_ReadLE32(src);
   162         /* biXPelsPerMeter = */ SDL_ReadLE32(src);
   163         /* biXPelsPerMeter = */ SDL_ReadLE32(src);
   163         /* biYPelsPerMeter = */ SDL_ReadLE32(src);
   164         /* biYPelsPerMeter = */ SDL_ReadLE32(src);
   164         biClrUsed = SDL_ReadLE32(src);
   165         biClrUsed = SDL_ReadLE32(src);
   165         /* biClrImportant = */ SDL_ReadLE32(src);
   166         /* biClrImportant = */ SDL_ReadLE32(src);
   166 
   167 
       
   168         /* 64 == BITMAPCOREHEADER2, an incompatible OS/2 2.x extension. Skip this stuff for now. */
       
   169         if (biSize == 64) {
       
   170             /* ignore these extra fields. */
       
   171             if (biCompression == BI_BITFIELDS) {
       
   172                 /* this value is actually huffman compression in this variant. */
       
   173                 SDL_SetError("Compressed BMP files not supported");
       
   174                 was_error = SDL_TRUE;
       
   175                 goto done;
       
   176             }
       
   177         } else {
       
   178             /* This is complicated. If compression is BI_BITFIELDS, then
       
   179                we have 3 DWORDS that specify the RGB masks. This is either
       
   180                stored here in an BITMAPV2INFOHEADER (which only differs in
       
   181                that it adds these RGB masks) and biSize >= 52, or we've got
       
   182                these masks stored in the exact same place, but strictly
       
   183                speaking, this is the bmiColors field in BITMAPINFO immediately
       
   184                following the legacy v1 info header, just past biSize. */
       
   185             if (biCompression == BI_BITFIELDS) {
       
   186                 haveRGBMasks = SDL_TRUE;
       
   187                 Rmask = SDL_ReadLE32(src);
       
   188                 Gmask = SDL_ReadLE32(src);
       
   189                 Bmask = SDL_ReadLE32(src);
       
   190 
       
   191                 /* ...v3 adds an alpha mask. */
       
   192                 if (biSize >= 56) {  /* BITMAPV3INFOHEADER; adds alpha mask */
       
   193                     haveAlphaMask = SDL_TRUE;
       
   194                     Amask = SDL_ReadLE32(src);
       
   195                 }
       
   196             } else {
       
   197                 /* the mask fields are ignored for v2+ headers if not BI_BITFIELD. */
       
   198                 if (biSize >= 52) {  /* BITMAPV2INFOHEADER; adds RGB masks */
       
   199                     /*Rmask = */ SDL_ReadLE32(src);
       
   200                     /*Gmask = */ SDL_ReadLE32(src);
       
   201                     /*Bmask = */ SDL_ReadLE32(src);
       
   202                 }
       
   203                 if (biSize >= 56) {  /* BITMAPV3INFOHEADER; adds alpha mask */
       
   204                     /*Amask = */ SDL_ReadLE32(src);
       
   205                 }
       
   206             }
       
   207 
       
   208             /* Insert other fields here; Wikipedia and MSDN say we're up to
       
   209                v5 of this header, but we ignore those for now (they add gamma,
       
   210                color spaces, etc). Ignoring the weird OS/2 2.x format, we
       
   211                currently parse up to v3 correctly (hopefully!). */
       
   212         }
       
   213 
       
   214         /* skip any header bytes we didn't handle... */
       
   215         headerSize = (Uint32) (SDL_RWtell(src) - (fp_offset + 14));
   167         if (biSize > headerSize) {
   216         if (biSize > headerSize) {
   168             SDL_RWseek(src, (biSize - headerSize), RW_SEEK_CUR);
   217             SDL_RWseek(src, (biSize - headerSize), RW_SEEK_CUR);
   169         }
   218         }
   170     }
   219     }
   171     if (biHeight < 0) {
   220     if (biHeight < 0) {
   192         ExpandBMP = 0;
   241         ExpandBMP = 0;
   193         break;
   242         break;
   194     }
   243     }
   195 
   244 
   196     /* We don't support any BMP compression right now */
   245     /* We don't support any BMP compression right now */
   197     Rmask = Gmask = Bmask = Amask = 0;
       
   198     switch (biCompression) {
   246     switch (biCompression) {
   199     case BI_RGB:
   247     case BI_RGB:
   200         /* If there are no masks, use the defaults */
   248         /* If there are no masks, use the defaults */
   201         if (bfOffBits == (14 + biSize)) {
   249         SDL_assert(!haveRGBMasks);
   202             /* Default values for the BMP format */
   250         SDL_assert(!haveAlphaMask);
   203             switch (biBitCount) {
   251         /* Default values for the BMP format */
   204             case 15:
       
   205             case 16:
       
   206                 Rmask = 0x7C00;
       
   207                 Gmask = 0x03E0;
       
   208                 Bmask = 0x001F;
       
   209                 break;
       
   210             case 24:
       
   211 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
       
   212                 Rmask = 0x000000FF;
       
   213                 Gmask = 0x0000FF00;
       
   214                 Bmask = 0x00FF0000;
       
   215 #else
       
   216                 Rmask = 0x00FF0000;
       
   217                 Gmask = 0x0000FF00;
       
   218                 Bmask = 0x000000FF;
       
   219 #endif
       
   220                 break;
       
   221             case 32:
       
   222                 /* We don't know if this has alpha channel or not */
       
   223                 correctAlpha = SDL_TRUE;
       
   224                 Amask = 0xFF000000;
       
   225                 Rmask = 0x00FF0000;
       
   226                 Gmask = 0x0000FF00;
       
   227                 Bmask = 0x000000FF;
       
   228                 break;
       
   229             default:
       
   230                 break;
       
   231             }
       
   232             break;
       
   233         }
       
   234         /* Fall through -- read the RGB masks */
       
   235 
       
   236     case BI_BITFIELDS:
       
   237         switch (biBitCount) {
   252         switch (biBitCount) {
   238         case 15:
   253         case 15:
   239         case 16:
   254         case 16:
   240             Rmask = SDL_ReadLE32(src);
   255             Rmask = 0x7C00;
   241             Gmask = SDL_ReadLE32(src);
   256             Gmask = 0x03E0;
   242             Bmask = SDL_ReadLE32(src);
   257             Bmask = 0x001F;
       
   258             break;
       
   259         case 24:
       
   260 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
       
   261             Rmask = 0x000000FF;
       
   262             Gmask = 0x0000FF00;
       
   263             Bmask = 0x00FF0000;
       
   264 #else
       
   265             Rmask = 0x00FF0000;
       
   266             Gmask = 0x0000FF00;
       
   267             Bmask = 0x000000FF;
       
   268 #endif
   243             break;
   269             break;
   244         case 32:
   270         case 32:
   245             Rmask = SDL_ReadLE32(src);
   271             /* We don't know if this has alpha channel or not */
   246             Gmask = SDL_ReadLE32(src);
   272             correctAlpha = SDL_TRUE;
   247             Bmask = SDL_ReadLE32(src);
   273             Amask = 0xFF000000;
   248             Amask = SDL_ReadLE32(src);
   274             Rmask = 0x00FF0000;
   249 
   275             Gmask = 0x0000FF00;
   250             /* ImageMagick seems to put out bogus masks here. Pick a default. */
   276             Bmask = 0x000000FF;
   251             if ((Rmask == 0xFFFFFF) && (Gmask == 0xFFFFFF) &&
       
   252                 (Bmask == 0xFFFFFF) && (Amask == 0xFFFFFF) ) {
       
   253                 Amask = 0xFF000000;
       
   254                 Rmask = 0x00FF0000;
       
   255                 Gmask = 0x0000FF00;
       
   256                 Bmask = 0x000000FF;
       
   257             } else if ((Rmask == 0xFFFFFF00) && (Gmask == 0xFFFFFF00) &&
       
   258                        (Bmask == 0xFFFFFF00) && (Amask == 0xFFFFFF00) ) {
       
   259                 /* argh, The Gimp seems to put out different bogus masks! */
       
   260                 Amask = 0x000000FF;
       
   261                 Rmask = 0xFF000000;
       
   262                 Gmask = 0x00FF0000;
       
   263                 Bmask = 0x0000FF00;
       
   264             }
       
   265 
       
   266             break;
   277             break;
   267         default:
   278         default:
   268             break;
   279             break;
   269         }
   280         }
   270         break;
   281         break;
       
   282 
       
   283     case BI_BITFIELDS:
       
   284         break;  /* we handled this in the info header. */
       
   285 
   271     default:
   286     default:
   272         SDL_SetError("Compressed BMP files not supported");
   287         SDL_SetError("Compressed BMP files not supported");
   273         was_error = SDL_TRUE;
   288         was_error = SDL_TRUE;
   274         goto done;
   289         goto done;
   275     }
   290     }