Date:2011-06-02 06:19:21 (12 years 9 months ago)
Author:Maarten ter Huurne
Commit:8b17e2ef62bd1528c42e89e5d60bb9ba9ec350ee
Message:PNG: Make loadPNG() responsible for creating an RGBA surface.

Before this commit loadPNG() could return any surface format and the caller
was responsible for converting it to the desired format. However, in practice
all callers want a surface with an alpha channel and SDL only supports that
with 32bpp surfaces, so RGBA or a permutation thereof. So I changed the
contract for loadPNG() so it is required to return an RGBA surface, and
removed the conversion code in the callers.

The next step is to replace IMG_Load() by a function that calls libpng
directly and loads a fixed 32bpp pixel format. That way, we can drop the
SDL_image dependency and avoid unnecessary pixel format conversions.
Files: src/asfont.cpp (1 diff)
src/imageio.cpp (1 diff)
src/imageio.h (1 diff)
src/surface.cpp (1 diff)

Change Details

src/asfont.cpp
1111ASFont::ASFont(const std::string &fontImagePath)
1212    : characters(SFONTPLUS_CHARSET)
1313{
14    // Load PNG file into an SDL surface.
15    SDL_Surface *buf = loadPNG(fontImagePath);
16    if (!buf) {
17        surface = NULL;
14    surface = loadPNG(fontImagePath);
15    if (!surface) {
1816        return;
1917    }
20
21    // Make sure we have a surface that can be blitted using alpha blending.
22    if (buf->format->BytesPerPixel == 4) {
23        surface = buf;
24        SDL_SetAlpha(surface, SDL_SRCALPHA, 255);
25    } else {
26        SDL_PixelFormat format32;
27        memset(&format32, 0, sizeof(format32));
28        format32.BitsPerPixel = 32;
29        format32.BytesPerPixel = 4;
30        format32.Rmask =
31            SDL_BYTEORDER == SDL_BIG_ENDIAN ? 0x00FF0000 : 0x000000FF;
32        format32.Gmask = 0x0000FF00;
33        format32.Bmask =
34            SDL_BYTEORDER == SDL_BIG_ENDIAN ? 0x000000FF : 0x00FF0000;
35        format32.Amask = 0xFF000000;
36        format32.Rshift = SDL_BYTEORDER == SDL_BIG_ENDIAN ? 16 : 0;
37        format32.Gshift = 8;
38        format32.Bshift = SDL_BYTEORDER == SDL_BIG_ENDIAN ? 0 : 16;
39        format32.Ashift = 24;
40        surface = SDL_ConvertSurface(buf, &format32, SDL_SRCALPHA);
41        SDL_FreeSurface(buf);
42    }
4318    assert(surface->format->BytesPerPixel == 4);
4419
4520    SDL_LockSurface(surface);
src/imageio.cpp
22
33#include <SDL_image.h>
44
5SDL_Surface *loadPNG(const std::string &path)
6{
7    return IMG_Load(path.c_str());
5SDL_Surface *loadPNG(const std::string &path) {
6    // Load PNG file into an SDL surface.
7    SDL_Surface *surface = IMG_Load(path.c_str());
8    if (!surface) {
9        return NULL;
10    }
11
12    // Make sure we have a surface that can be blitted using alpha blending.
13    if (surface->format->BytesPerPixel == 4) {
14        SDL_SetAlpha(surface, SDL_SRCALPHA, 255);
15        return surface;
16    } else {
17        SDL_PixelFormat format32;
18        memset(&format32, 0, sizeof(format32));
19        format32.BitsPerPixel = 32;
20        format32.BytesPerPixel = 4;
21        format32.Rmask =
22            SDL_BYTEORDER == SDL_BIG_ENDIAN ? 0x00FF0000 : 0x000000FF;
23        format32.Gmask = 0x0000FF00;
24        format32.Bmask =
25            SDL_BYTEORDER == SDL_BIG_ENDIAN ? 0x000000FF : 0x00FF0000;
26        format32.Amask = 0xFF000000;
27        format32.Rshift = SDL_BYTEORDER == SDL_BIG_ENDIAN ? 16 : 0;
28        format32.Gshift = 8;
29        format32.Bshift = SDL_BYTEORDER == SDL_BIG_ENDIAN ? 0 : 16;
30        format32.Ashift = 24;
31        SDL_Surface *surface32 =
32            SDL_ConvertSurface(surface, &format32, SDL_SRCALPHA);
33        SDL_FreeSurface(surface);
34        return surface32;
35    }
836}
src/imageio.h
55
66struct SDL_Surface;
77
8/** Loads an image from a PNG file into a newly allocated 32bpp RGBA surface.
9  */
810SDL_Surface *loadPNG(const std::string &path);
911
1012#endif
src/surface.cpp
9090        skinpath = img;
9191    }
9292
93    SDL_Surface *buf = loadPNG(skinpath);
94    if (buf!=NULL) {
95        raw = SDL_DisplayFormatAlpha(buf);
96        SDL_FreeSurface(buf);
97    } else {
93    raw = loadPNG(skinpath);
94    if (!raw) {
9895        ERROR("Couldn't load surface '%s'\n", img.c_str());
9996    }
10097}

Archive Download the corresponding diff file



interactive