#include #include #include "png.h" #include "globalincs/pstypes.h" #include "pngutils/pngutils.h" #include "cfile/cfile.h" #include "bmpman/bmpman.h" #include "palman/palman.h" #include "graphics/2d.h" CFILE *png_file = NULL; //copy/pasted from libpng void png_scp_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; if (png_ptr == NULL) return; /* fread() returns 0 on error, so it is OK to store this in a png_size_t * instead of an int, which is what fread() actually returns. */ check = (png_size_t)cfread(data, (png_size_t)1, length, png_file); if (check != length) png_error(png_ptr, "Read Error"); } // Reads header information from the PNG file into the bitmap pointer // // filename - name of the PNG bitmap file // w - (output) width of the bitmap // h - (output) height of the bitmap // bpp - (output) bits per pixel of the bitmap // // returns - PNG_ERROR_NONE if successful, otherwise error code // int png_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette) { char filename[MAX_FILENAME_LEN]; png_infop info_ptr; png_structp png_ptr; png_file = NULL; //mprintf(("png_read_header: %s\n", real_filename)); if (img_cfp == NULL) { strcpy_s( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat_s( filename, ".png" ); png_file = cfopen( filename , "rb" ); if ( !png_file ) { return PNG_ERROR_READING; } } else { png_file = img_cfp; } Assert( png_file != NULL ); if (png_file == NULL) return PNG_ERROR_READING; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { mprintf(("png_read_header: error creating read struct\n")); cfclose(png_file); return PNG_ERROR_READING; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { mprintf(("png_read_header: error creating info struct\n")); cfclose(png_file); png_destroy_read_struct(&png_ptr, NULL, NULL); return PNG_ERROR_READING; } if (setjmp(png_jmpbuf(png_ptr))) { mprintf(("png_read_header: something went wrong\n")); /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); cfclose(png_file); /* If we get here, we had a problem reading the file */ return PNG_ERROR_READING; } png_set_read_fn(png_ptr, &png_file, png_scp_read_data); png_read_info(png_ptr, info_ptr); if (w) *w = png_get_image_width(png_ptr, info_ptr); if (h) *h = png_get_image_height(png_ptr, info_ptr); // this turns out to be near useless, but meh if (bpp) *bpp = (png_get_channels(png_ptr, info_ptr) * png_get_bit_depth(png_ptr, info_ptr)); if (img_cfp == NULL) { cfclose(png_file); png_file = NULL; } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return PNG_ERROR_NONE; } // Loads a PNG image // // filename - name of the targa file to load // image_data - allocated storage for the bitmap // // returns - true if succesful, false otherwise // int png_read_bitmap(const char *real_filename, ubyte *image_data, ubyte *bpp, int dest_size, int cf_type) { char filename[MAX_FILENAME_LEN]; png_infop info_ptr; png_structp png_ptr; png_bytepp row_pointers; unsigned int i, len; png_file = NULL; strcpy_s( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat_s( filename, ".png" ); png_file = cfopen(filename, "rb", CFILE_NORMAL, cf_type); if (png_file == NULL) return PNG_ERROR_READING; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { mprintf(("png_read_bitmap: png_ptr went wrong\n")); cfclose(png_file); return PNG_ERROR_READING; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { mprintf(("png_read_bitmap: info_ptr went wrong\n")); cfclose(png_file); png_destroy_read_struct(&png_ptr, NULL, NULL); return PNG_ERROR_READING; } if (setjmp(png_jmpbuf(png_ptr))) { mprintf(("png_read_bitmap: something went wrong\n")); /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); cfclose(png_file); /* If we get here, we had a problem reading the file */ return PNG_ERROR_READING; } png_set_read_fn(png_ptr, &png_file, png_scp_read_data); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL); len = png_get_rowbytes(png_ptr, info_ptr); row_pointers = png_get_rows(png_ptr, info_ptr); if(bpp) *bpp = (ubyte)(len / png_get_image_width(png_ptr, info_ptr)) << 3; //copy row data to image unsigned int height = png_get_image_height(png_ptr, info_ptr); for (i = 0; i < height; i++) { memcpy(&image_data[i * len], row_pointers[i], len); } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); cfclose(png_file); return PNG_ERROR_NONE; }