1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
#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(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(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;
}
|