User:TakuyaMurata/load png.c

From Wikipedia, the free encyclopedia

// The following code loads a png file into a bitmap image in Windows.

// No error handling
void PNGAPI user_error_fn (png_structp png, png_const_charp sz) { }
void PNGAPI user_warning_fn (png_structp png, png_const_charp sz) { }
 
HBITMAP
load_png (const char *szFile)
{
    FILE *fp = fopen (szFile, "rb");
    if (!fp)
        return NULL;
        
    BYTE header[8];
    fread (header, 1, 8, fp);
        
    if (png_sig_cmp (header, 0, 8))
        return NULL;
    fseek (fp, 0, SEEK_SET);
                
    // set up
        
    png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 
        NULL, user_error_fn, user_warning_fn);
    if (!png_ptr)
        return NULL;
    png_infop info = png_create_info_struct (png_ptr);
    if (!info) {
        png_destroy_read_struct (&png_ptr, NULL, NULL);
        return NULL;
    }
        
    png_init_io (png_ptr, fp);
        
    png_read_info (png_ptr, info);

    int width = info->width, height = info->height, channels = info->channels;
        
    if (height > PNG_UINT_32_MAX / sizeof (png_bytep))
        return NULL;    // too big

    png_bytep buf = malloc (height * width * channels);
    png_bytep *rows = malloc (sizeof (png_bytep) * height);
    int i;
    for (i = 0; i < height; i++)
        rows[i] = buf + width * channels * i;
        
    png_set_strip_16 (png_ptr); // ensure bbp <= 8
    png_set_packing (png_ptr);
    png_set_expand (png_ptr);
    png_set_bgr (png_ptr);              // flip the RGB pixels to BGR (or RGBA to BGRA)
                
    png_read_image (png_ptr, rows);

    png_read_end (png_ptr, info);
    png_destroy_read_struct (&png_ptr, &info, NULL);
        
    fclose (fp);
    free (rows);
                        
    return CreateBitmap (width, height, 1, 32, buf);
}