/* * img_compat.c — libpng-backed IMG_Load for the Emscripten build. * * Returns an RGBA8 SDL_Surface. Handles palette, grayscale, tRNS, and 16-bit * inputs by normalizing to 8-bit RGBA in the read pipeline. */ #ifdef __EMSCRIPTEN__ #include "img_compat.h" #include #include #include SDL_Surface *IMG_Load(const char *file) { FILE *fp = fopen(file, "rb"); if(!fp) return NULL; unsigned char hdr[8]; if(fread(hdr, 1, 8, fp) != 8 || png_sig_cmp(hdr, 0, 8)) { fclose(fp); return NULL; } png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png) { fclose(fp); return NULL; } png_infop info = png_create_info_struct(png); if(!info) { png_destroy_read_struct(&png, NULL, NULL); fclose(fp); return NULL; } SDL_Surface *surf = NULL; png_bytep *rows = NULL; if(setjmp(png_jmpbuf(png))) { if(rows) free(rows); if(surf) SDL_DestroySurface(surf); png_destroy_read_struct(&png, &info, NULL); fclose(fp); return NULL; } png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_uint_32 w, h; int depth, ctype; png_get_IHDR(png, info, &w, &h, &depth, &ctype, NULL, NULL, NULL); if(depth == 16) png_set_strip_16(png); if(ctype == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if(ctype == PNG_COLOR_TYPE_GRAY && depth < 8) png_set_expand_gray_1_2_4_to_8(png); if(png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); if(ctype == PNG_COLOR_TYPE_GRAY || ctype == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if(ctype == PNG_COLOR_TYPE_RGB || ctype == PNG_COLOR_TYPE_GRAY || ctype == PNG_COLOR_TYPE_PALETTE) png_set_filler(png, 0xFF, PNG_FILLER_AFTER); png_read_update_info(png, info); surf = SDL_CreateSurface((int)w, (int)h, SDL_PIXELFORMAT_RGBA32); if(!surf) png_error(png, "SDL_CreateSurface failed"); rows = (png_bytep *)malloc(sizeof(png_bytep) * h); if(!rows) png_error(png, "row table alloc failed"); for(png_uint_32 y = 0; y < h; ++y) rows[y] = (png_bytep)((unsigned char *)surf->pixels + y * surf->pitch); png_read_image(png, rows); png_read_end(png, NULL); free(rows); png_destroy_read_struct(&png, &info, NULL); fclose(fp); return surf; } #endif /* __EMSCRIPTEN__ */