Introducing SDL_stbimage.h - creating SDL_Surfaces from image files

Hi,

I created a small header-only library that uses the awesome stb_image.h
(see https://github.com/nothings/stb ) to decode image files and creates
SDL_Surfaces from that (in RGB or RGBA, depending on whether the image
file had an alpha channel or not):
https://github.com/DanielGibson/Snippets/blob/master/SDL_stbimage.h

It supports all file formats supported by stb_image.h, which are
currently JPEG, PNG, BMP, PSD, TGA, GIF, PIC and PNM (.ppm, .pgm).

Using it is super-easy: Just drop SDL_stbimage.h and stb_image.h in your
project, and in one of your .c/.cpp files, do

#define SDL_STBIMAGE_IMPLEMENTATION
#include “SDL_stbimage.h”

which will create the implementation of the libraries (both SDL_stbimage
and stb_image) there. Isn’t that a lot easier than integrating libpng,
libjpeg etc in your buildsystem? :slight_smile:

Now you’re ready to use it, like:

SDL_Surface* surf = STBIMG_Load(“test.png”);
if(surf == NULL) {
printf(“ERROR: Couldn’t load test.png: %s\n”, SDL_GetError());
exit(1);
}

// … do something with surf …

SDL_FreeSurface(surf);

(In your other source files just do #include “SDL_stbimage.h” without
the #define SDL_STBIMAGE_IMPLEMENTATION to use the STBIMG_* functions)

It also has functions to load from a constant memory buffer and from
SDL_RWops and a function to create stb_image specific IO-callbacks from
SDL_RWops, in case you wanna use SDL_RWops and stb_image functions, but
not SDL_Surface.
See the homepage and the header itself for more details:
https://github.com/DanielGibson/Snippets
https://github.com/DanielGibson/Snippets/blob/master/SDL_stbimage.h

I hope you like it!

Cheers,
Daniel

1 Like

This looks pretty nice!

I’ll have to look it over and compare it to my implementation in SDL_gpu,
which uses stb-image and stb-image-write.

SDL_gpu has GPU_LoadSurface, GPU_LoadSurface_RW, and GPU_SaveSurface
functions (hmm… looks like it needs SaveSurface_RW).

Jonny DOn Thu, Nov 19, 2015 at 11:06 AM, Daniel Gibson wrote:

Hi,

I created a small header-only library that uses the awesome stb_image.h
(see GitHub - nothings/stb: stb single-file public domain libraries for C/C++ ) to decode image files and creates
SDL_Surfaces from that (in RGB or RGBA, depending on whether the image file
had an alpha channel or not):
Snippets/SDL_stbimage.h at master · DanielGibson/Snippets · GitHub

It supports all file formats supported by stb_image.h, which are currently
JPEG, PNG, BMP, PSD, TGA, GIF, PIC and PNM (.ppm, .pgm).

Using it is super-easy: Just drop SDL_stbimage.h and stb_image.h in your
project, and in one of your .c/.cpp files, do

#define SDL_STBIMAGE_IMPLEMENTATION
#include “SDL_stbimage.h”

which will create the implementation of the libraries (both SDL_stbimage
and stb_image) there. Isn’t that a lot easier than integrating libpng,
libjpeg etc in your buildsystem? :slight_smile:

Now you’re ready to use it, like:

SDL_Surface* surf = STBIMG_Load(“test.png”);
if(surf == NULL) {
printf(“ERROR: Couldn’t load test.png: %s\n”, SDL_GetError());
exit(1);
}

// … do something with surf …

SDL_FreeSurface(surf);

(In your other source files just do #include “SDL_stbimage.h” without the
#define SDL_STBIMAGE_IMPLEMENTATION to use the STBIMG_* functions)

It also has functions to load from a constant memory buffer and from
SDL_RWops and a function to create stb_image specific IO-callbacks from
SDL_RWops, in case you wanna use SDL_RWops and stb_image functions, but not
SDL_Surface.
See the homepage and the header itself for more details:
GitHub - DanielGibson/Snippets: (Hopefully) useful code snippets and header-only libs
Snippets/SDL_stbimage.h at master · DanielGibson/Snippets · GitHub

I hope you like it!

Cheers,
Daniel


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I only support loading surfaces, no writing.

I guess SaveSurface_RW() is pretty easy with stb_image_write, you only
need to write a wrapper around SDL_RWwrite() for stbi_write_func.

One disadvantage of stb_image_write is that the png compression is kinda
poor, the resulting files are often 40-50% bigger than what you’d get
with libpng and 40% bigger than the results from LodePNG.
But it’s still a lot smaller than TGA (even with RLE), so I guess it’s
bearable.

I dunno if I should add support for writing - I guess if there is demand
for it I’d put it in a separate lib and also use stb_image_write.

But currently I’m curious if anyone actually ends up using
SDL_stbimage.h :wink:

Cheers,
DanielOn 11/19/2015 07:49 PM, Jonathan Dearborn wrote:

This looks pretty nice!

I’ll have to look it over and compare it to my implementation in
SDL_gpu, which uses stb-image and stb-image-write.

SDL_gpu has GPU_LoadSurface, GPU_LoadSurface_RW, and GPU_SaveSurface
functions (hmm… looks like it needs SaveSurface_RW).

Yeah, stb_image_write’s PNG compression is also very slow (~800 ms for a
screen-sized image). I have to use TGA when saving images as state in
apps. For me it’d be great if only that were fixed.

Jonny DOn Thu, Nov 19, 2015 at 4:32 PM, Daniel Gibson wrote:

On 11/19/2015 07:49 PM, Jonathan Dearborn wrote:

This looks pretty nice!

I’ll have to look it over and compare it to my implementation in
SDL_gpu, which uses stb-image and stb-image-write.

SDL_gpu has GPU_LoadSurface, GPU_LoadSurface_RW, and GPU_SaveSurface
functions (hmm… looks like it needs SaveSurface_RW).

I only support loading surfaces, no writing.

I guess SaveSurface_RW() is pretty easy with stb_image_write, you only
need to write a wrapper around SDL_RWwrite() for stbi_write_func.

One disadvantage of stb_image_write is that the png compression is kinda
poor, the resulting files are often 40-50% bigger than what you’d get with
libpng and 40% bigger than the results from LodePNG.
But it’s still a lot smaller than TGA (even with RLE), so I guess it’s
bearable.

I dunno if I should add support for writing - I guess if there is demand
for it I’d put it in a separate lib and also use stb_image_write.

But currently I’m curious if anyone actually ends up using SDL_stbimage.h
:wink:

Cheers,
Daniel


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL_stbimage.h is now compatible with SDL3: Snippets/SDL_stbimage.h at master · DanielGibson/Snippets · GitHub

It also still supports SDL2 and (with limited functionality) SDL1.2.

I think the only thing to keep in mind as a user is that when using SDL3, you either need to #include <SDL3/SDL.h> or #define SDL_STBIMG_SDL3 before including it.

Otherwise not much has changed

  • Instead of SDL_bool now bool (from <stdbool.h>) is used, for all SDL versions
  • The functions with _RW in their names (like SDL_Load_RW()) have been renamed to have _IO in their names instead (like SDL_Load_IO()) when using SDL3 - but defines for the old names are provided (#define SDL_Load_RW SDL_Load_IO) so the old names still work.
    For SDL2 and SDL1.2 the function names have not changed.

Usage example (basically the same as in the orig post but with highlighting and for SDL3):
Just drop SDL_stbimage.h and stb_image.h (from stb/stb_image.h at master · nothings/stb · GitHub or, for an updated/bugfixed version, stb/stb_image.h at nbickford/all-fixes · NBickford-NV/stb · GitHub) in your project, and in one your of .c/.cpp files do

#include <SDL3/SDL.h> // before including SDL_stbimage.h

#define SDL_STBIMAGE_IMPLEMENTATION
#include "SDL_stbimage.h"

Now you’re ready to use it in your code, like:

SDL_Surface* surf = STBIMG_Load("test.png");
if(surf == NULL) {
    printf("ERROR: Couldn’t load test.png: %s\n", SDL_GetError());
    exit(1);
}

// … do something with surf …

SDL_DestroySurface(surf);

To use it in other .c/.cpp files, just use

#include <SDL3/SDL.h> // still must be included before SDL_stbimage.h
#include "SDL_stbimage.h"

(without defining SDL_STBIMAGE_IMPLEMENTATION)

As mentioned before, instead of including <SDL3/SDL.h> first, you can also do this:

#define SDL_STBIMG_SDL3
// in *one* source file also add #define SDL_STBIMAGE_IMPLEMENTATION 
#include "SDL_stbimage.h"
2 Likes

Sorry I find this hilarious. STB is a great project

1 Like