Skip to content

Instantly share code, notes, and snippets.

@devinacker
Last active June 18, 2018 13:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devinacker/bd02c7276845d66bf9cd46616d43be2d to your computer and use it in GitHub Desktop.
Save devinacker/bd02c7276845d66bf9cd46616d43be2d to your computer and use it in GitHub Desktop.
/*
Quick SDL2 wrapper for uPNG
d@revenant1.net
This code is public domain.
*/
// https://github.com/elanthis/upng
#include "upng/upng.h"
#include <SDL2/SDL.h>
SDL_Surface* PNG_Load(const char *file);
SDL_Surface* PNG_LoadMem(const unsigned char *data, unsigned size);
static const char *PNG_error[] = {
"no error",
"out of memory",
"file not found",
"not a PNG file",
"invalid PNG image",
"unsupported PNG chunk",
"image interlacing not supported",
"unsupported color format",
"invalid parameter",
};
static SDL_Surface* PNG_Decode(upng_t *png) {
SDL_Surface *s = 0;
uint8_t *out, *in;
unsigned inpitch, format;
if (!png || upng_decode(png) != UPNG_EOK) goto end;
// get format of decoded PNG
switch (upng_get_format(png)) {
case UPNG_RGB8:
format = SDL_PIXELFORMAT_RGB24;
break;
case UPNG_RGBA8:
format = SDL_PIXELFORMAT_RGBA32;
break;
default:
// unsupported
SDL_SetError("SDL_upng: only RGB24 and RGBA32 are supported");
goto end;
}
s = SDL_CreateRGBSurfaceWithFormat(0,
upng_get_width(png), upng_get_height(png),
upng_get_bpp(png), format);
if (!s) goto end;
// copy decoded image
SDL_LockSurface(s);
out = (uint8_t*)s->pixels;
in = (uint8_t*)upng_get_buffer(png);
/*
upng_get_pixelsize is supposed to return bytes, but returns bits instead...
Just use upng_get_bpp in case that gets fixed later
(https://github.com/elanthis/upng/pull/6)
*/
inpitch = s->w * ((upng_get_bpp(png)+7) / 8);
for (int i = 0; i < s->h; i++) {
memcpy(out, in, inpitch);
out += s->pitch;
in += inpitch;
}
SDL_UnlockSurface(s);
end:
if (png) {
if (upng_get_error(png)) {
SDL_SetError("uPNG: %s", PNG_error[upng_get_error(png)]);
}
upng_free(png);
} else {
SDL_SetError("SDL_upng: couldn't allocate PNG info");
}
return s;
}
SDL_Surface* PNG_Load(const char *file) {
upng_t *png = upng_new_from_file(file);
return PNG_Decode(png);
}
SDL_Surface* PNG_LoadMem(const unsigned char *data, unsigned size) {
upng_t *png = upng_new_from_bytes(data, size);
return PNG_Decode(png);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment