/*
 * 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 <png.h>
#include <stdio.h>
#include <stdlib.h>

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__ */
