/* Quick SDL2 wrapper for uPNG d@revenant1.net This code is public domain. */ // https://github.com/elanthis/upng #include "upng/upng.h" #include 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); }