2013-04-14 19:39:56 -06:00
|
|
|
// Copyright (C) 2003 Dolphin Project.
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, version 2.0.
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
// Official SVN repository and contact information can be found at
|
|
|
|
// http://code.google.com/p/dolphin-emu/
|
|
|
|
|
|
|
|
#include "GLInterface.h"
|
|
|
|
#include <png.h>
|
2013-09-02 00:40:05 -06:00
|
|
|
char* LoadPNG(const char *filename, u32 &width, u32 &height)
|
2013-04-14 19:39:56 -06:00
|
|
|
{
|
|
|
|
FILE *infile; /* PNG file pointer */
|
|
|
|
png_structp png_ptr; /* internally used by libpng */
|
|
|
|
png_infop info_ptr; /* user requested transforms */
|
|
|
|
|
|
|
|
char *image_data; /* raw png image data */
|
|
|
|
char sig[8]; /* PNG signature array */
|
|
|
|
/*char **row_pointers; */
|
|
|
|
|
|
|
|
int bit_depth;
|
|
|
|
int color_type;
|
|
|
|
|
2013-09-02 00:40:05 -06:00
|
|
|
png_uint_32 _width;
|
|
|
|
png_uint_32 _height;
|
2013-04-14 19:39:56 -06:00
|
|
|
unsigned int rowbytes; /* raw bytes at row n in image */
|
|
|
|
|
|
|
|
image_data = NULL;
|
|
|
|
unsigned int i;
|
|
|
|
png_bytepp row_pointers = NULL;
|
|
|
|
|
|
|
|
/* Open the file. */
|
|
|
|
infile = fopen(filename, "rb");
|
|
|
|
if (!infile)
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL;
|
2013-04-14 19:39:56 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 13.3 readpng_init()
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Check for the 8-byte signature */
|
|
|
|
fread(sig, 1, 8, infile);
|
|
|
|
|
|
|
|
if (!png_check_sig((unsigned char *) sig, 8)) {
|
|
|
|
fclose(infile);
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL;
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the PNG structs
|
|
|
|
*/
|
|
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
if (!png_ptr) {
|
|
|
|
fclose(infile);
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL; /* out of memory */
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL; /* out of memory */
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL;
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
2013-09-02 00:40:05 -06:00
|
|
|
png_get_IHDR(png_ptr, info_ptr, &_width, &_height, &bit_depth,
|
2013-04-14 19:39:56 -06:00
|
|
|
&color_type, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
/* Set up some transforms. */
|
|
|
|
if (bit_depth > 8)
|
|
|
|
png_set_strip_16(png_ptr);
|
|
|
|
|
|
|
|
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
|
|
|
png_set_gray_to_rgb(png_ptr);
|
|
|
|
|
|
|
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
|
|
|
png_set_palette_to_rgb(png_ptr);
|
|
|
|
|
|
|
|
/* Update the png info struct.*/
|
|
|
|
png_read_update_info(png_ptr, info_ptr);
|
|
|
|
|
|
|
|
/* Rowsize in bytes. */
|
|
|
|
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
|
|
|
|
|
|
|
|
|
|
|
/* Allocate the image_data buffer. */
|
2013-09-02 00:40:05 -06:00
|
|
|
if ((image_data = (char *) malloc(rowbytes * _height))==NULL) {
|
2013-04-14 19:39:56 -06:00
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL;
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|
|
|
|
|
2013-09-02 00:40:05 -06:00
|
|
|
if ((row_pointers = (png_bytepp)malloc(_height*sizeof(png_bytep))) == NULL) {
|
2013-04-14 19:39:56 -06:00
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
|
|
free(image_data);
|
|
|
|
image_data = NULL;
|
2013-09-02 00:40:05 -06:00
|
|
|
return NULL;
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* set the individual row_pointers to point at the correct offsets */
|
|
|
|
|
2013-09-02 00:40:05 -06:00
|
|
|
for (i = 0; i < _height; ++i)
|
2013-04-14 19:39:56 -06:00
|
|
|
row_pointers[i] = (png_byte*)(image_data + i*rowbytes);
|
|
|
|
|
|
|
|
|
|
|
|
/* now we can go ahead and just read the whole image */
|
|
|
|
png_read_image(png_ptr, row_pointers);
|
|
|
|
|
|
|
|
/* and we're done! (png_read_end() can be omitted if no processing of
|
|
|
|
* post-IDAT text/time/etc. is desired) */
|
|
|
|
|
|
|
|
/* Clean up. */
|
|
|
|
free(row_pointers);
|
|
|
|
|
|
|
|
/* Clean up. */
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
|
|
fclose(infile);
|
|
|
|
|
2013-09-02 00:40:05 -06:00
|
|
|
width = (u32)_width;
|
|
|
|
height = (u32)_height;
|
|
|
|
return image_data;
|
2013-04-14 19:39:56 -06:00
|
|
|
}
|