int read_png_file(const char *file, int32 *pwidth, int32 *pheight, uint8 **image_data_ptr)
{
FILE *infile; /* PNG file pointer */
png_structp png_ptr; /* internally used by libpng */
png_infop info_ptr; /* user requested transforms */
uint8 *image_data; /* raw png image data */
char sig[8]; /* PNG signature array */
/*char **row_pointers; */
int bit_depth;
int color_type;
png_uint_32 width; /* PNG image width in pixels */
png_uint_32 height; /* PNG image height in pixels */
unsigned int rowbytes; /* raw bytes at row n in image */
image_data = NULL;
int i;
png_bytepp row_pointers = NULL;
/* Open the file. */
infile = fopen(file, "rb");
if (!infile) {
return 0;
}
/*
* 13.3 readpng_init()
*/
/* Check for the 8-byte signature */
fread(sig, 1, 8, infile);
if (png_sig_cmp((unsigned char *) sig, 0, 8) != 0) {
fclose(infile);
return 0;
}
/*
* Set up the PNG structs
*/
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose(infile);
return 4; /* out of memory */
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(infile);
return 4; /* out of memory */
}
/*
* block to handle libpng errors,
* then check whether the PNG file had a bKGD chunk
*/
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(infile);
return 0;
}
/*
* takes our file stream pointer (infile) and
* stores it in the png_ptr struct for later use.
*/
/* png_ptr->io_ptr = (png_voidp)infile;*/
png_init_io(png_ptr, infile);
/*
* lets libpng know that we already checked the 8
* signature bytes, so it should not expect to find
* them at the current file pointer location
*/
png_set_sig_bytes(png_ptr, 8);
/* Read the image info.*/
/*
* reads and processes not only the PNG file's IHDR chunk
* but also any other chunks up to the first IDAT
* (i.e., everything before the image data).
*/
/* read all the info up to the image data */
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
&color_type, NULL, NULL, NULL);
*pwidth = width;
*pheight = height;
if (bit_depth > 8) {
//.........这里部分代码省略.........
static int save_png_to_file (bitmap_t *bitmap, const char *path)
{
FILE * fp;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_byte ** row_pointers = NULL;
/* "status" contains the return value of this function. At first
it is set to a value which means 'failure'. When the routine
has finished its work, it is set to a value which means
'success'. */
int status = -1;
/* The following number is set by trial and error only. I cannot
see where it it is documented in the libpng manual.
*/
int pixel_size = 3;
int depth = 8;
fp = fopen (path, "wb");
if (! fp) {
goto fopen_failed;
}
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
goto png_create_write_struct_failed;
}
info_ptr = png_create_info_struct (png_ptr);
if (info_ptr == NULL) {
goto png_create_info_struct_failed;
}
/* Set up error handling. */
if (setjmp (png_jmpbuf (png_ptr))) {
goto png_failure;
}
/* Set image attributes. */
png_set_IHDR (png_ptr,
info_ptr,
bitmap->width,
bitmap->height,
depth,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Initialize rows of PNG. */
row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
for (y = 0; y < bitmap->height; ++y) {
png_byte *row =
png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
row_pointers[y] = row;
for (x = 0; x < bitmap->width; ++x) {
pixel_t * pixel = pixel_at (bitmap, x, y);
*row++ = pixel->red;
*row++ = pixel->green;
*row++ = pixel->blue;
}
}
/* Write the image data to "fp". */
png_init_io (png_ptr, fp);
png_set_rows (png_ptr, info_ptr, row_pointers);
png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
/* The routine has successfully written the file, so we set
"status" to a value which indicates success. */
status = 0;
for (y = 0; y < bitmap->height; y++) {
png_free (png_ptr, row_pointers[y]);
}
png_free (png_ptr, row_pointers);
png_failure:
png_create_info_struct_failed:
png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
fclose (fp);
fopen_failed:
return status;
}
// 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;
}
bool IGN_Create_PNG_JPR(LPCSTR mapname, long minx, long miny, long maxx, long maxy)
{
char tstring[256];
long bitmap_width = TILE_WIDTH*(maxx-minx)/1000;
long bitmap_size = bitmap_width*TILE_WIDTH;
unsigned char * bitmap_memory = (unsigned char *)malloc(bitmap_size);
CIGNTileDatabase db;
if (bitmap_memory == NULL) {
printf("Couldn't allocate %d bytes of memory\n");
return false;
}
// Create PNG header and write out palette
sprintf(tstring, "%s.png", mapname);
FILE * fp_png = fopen(tstring, "wb");
if (fp_png == NULL) {
printf("Couldn't open %s\n", tstring);
return false;
}
// Create and initialize the png_struct with the desired error handler functions.
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp_png);
return false;
}
/* Allocate/initialize the image information data. REQUIRED */
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
fclose(fp_png);
return false;
}
/* Set error handling. REQUIRED */
if (setjmp(png_jmpbuf(png_ptr))) {
/* If we get here, we had a problem reading the file */
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp_png);
return false;
}
/* set up the output control if you are using standard C streams */
png_init_io(png_ptr, fp_png);
/* Set the image information here. Width and height are up to 2^31,
* bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
* PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
png_set_IHDR(png_ptr, info_ptr, TILE_WIDTH*(maxx-minx)/1000, TILE_WIDTH*((maxy-miny)/1000), 8, PNG_COLOR_TYPE_PALETTE,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
/* set the palette if there is one. REQUIRED for indexed-color images */
png_colorp png_palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
int i;
BYTE * pal_ptr = (BYTE *)png_palette;
BYTE * palette = ign_palette;
for (i=0; i<256; i++) {
*pal_ptr++ = palette[i*4 + 2];
*pal_ptr++ = palette[i*4 + 1];
*pal_ptr++ = palette[i*4 + 0];
}
/* ... set palette colors ... */
png_set_PLTE(png_ptr, info_ptr, png_palette, PNG_MAX_PALETTE_LENGTH);
/* You must not free palette here, because png_set_PLTE only makes a link to
* the palette that you malloced. Wait until you are about to destroy
*the png structure. */
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
CProgressWindow wndProgress;
wndProgress.Initialize();
wndProgress.ResetProgressBar("Tile:", (maxy-miny)/500*(maxx-minx)/500);
for (int y=maxy-1000; y>=miny; y-=1000) {
memset(bitmap_memory, 0x00, bitmap_size);
for (int x=minx; x<maxx; x+=1000) {
IGN_read_bmp(y, x, &db, bitmap_memory+(x-minx)/1000*TILE_WIDTH, bitmap_width);
}
// write row of PNG to file
for (int x=0; x<TILE_WIDTH; x++) {
png_write_row(png_ptr, bitmap_memory + x*bitmap_width);
if (!wndProgress.ProgressBar()) return false;
//.........这里部分代码省略.........
请发表评论