I recently tried to load a PNG file into an SDL_Texture to render on screen. SDL supports BMP only by default, so I’d need to grab a library. SDL_Image exists as an extension to SDL and runs on any platform supported by SDL. It’s a great option that I’ll probably use it at some point, but I’ve always been a fan of the lightweight stb libraries. So for fun I decided to go with stb_image.
As you may have guessed, this is useful for loading images of all types. From the header itself:
Primarily of interest to game developers and other people who can avoid problematic images and only need the trivial interface JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) PNG 1/2/4/8/16-bit-per-channel TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE PSD (composited view only, no extra channels, 8/16 bit-per-channel) GIF (*comp always reports as 4-channel) HDR (radiance rgbE format) PIC (Softimage PIC) PNM (PPM and PGM binary only)
The documentation is quite verbose and complete, and it makes what we want to do very easy. Just add
stb_image.h to your includes (or drop it straight into your project) and add this to your include block:
#define STB_IMAGE_IMPLEMENTATION #include <stb_image.h>
SDL has a nice sample that loads a PNG using stbi_load and creates a surface from it. However! Disaster strikes when you try to compile the code!
The Link Error
2>Main.obj : error LNK2019: unresolved external symbol SDL_CreateRGBSurfaceWithFormatFrom referenced in function SDL_main
Since everything seemed alright on my end I immediately went to the SDL bug database, and yup, lo and behold I wasn’t alone in this. It looks like the DLL files were updated but libs were not rebuild for SDL 2.0.5. Not to worry, I learnt something new! How to rebuild .lib files using only a DLL. It’s very simple, I followed the steps outlined here, but I’ll re-list them for completions sake.
- Open the developer command prompt located in:
Start->Programs->Microsoft Visual Studio->Tools
- Run the dumpbin command to list all of the functions exported by the DLL
dumpbin /exports C:\path\to\SDL2.dll
This prints a whole bunch of stuff to the console that looks like this
ordinal hint RVA name 1 0 00038180 SDL_AddEventWatch 2 1 000385C0 SDL_AddHintCallback 3 2 000398E0 SDL_AddTimer 4 3 00038B70 SDL_AllocFormat 5 4 00038B90 SDL_AllocPalette 6 5 00039090 SDL_AllocRW 7 6 00037DB0 SDL_AtomicAdd 8 7 00037D80 SDL_AtomicCAS ...
What we wanna do now is copy paste all of the function names (and only the function names) into a new
SDL2.deffile and add the line “EXPORTS” up the top. It will look like this:
EXPORTS SDL_AddEventWatch SDL_AddHintCallback SDL_AddTimer SDL_AllocFormat SDL_AllocPalette SDL_AllocRW SDL_AtomicAdd SDL_AtomicCAS ...
- Hurray! We can finally create the .lib from this .def file
lib /def:C:\path\to\SDL2.def /OUT:C:\path\to\SDL2.lib
The good news is that an SDL 2.0.6 release is underway and this should be fixed simply by recompiling the libraries