mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 13:01:29 -10:00
git-svn-id: svn://svn.icculus.org/fs2open/trunk/fs2_open@9805 387891d4-d844-0410-90c0-e4c51a9137d3
210 lines
5.7 KiB
C++
210 lines
5.7 KiB
C++
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
}
|