#include "c_common.h"
unsigned char linewrk[2048*4];
png_structp png_ptr;
png_infop info_ptr;
FILE *fp;
int getNextPower2(int width)
{
int b = width;
int n;
for (n = 0; b != 0; n++) b >>= 1;
b = 1 << n;
if (b == 2 * width) b >>= 1;
return b;
}
void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
{
}
void PngRamDiskRead(png_struct *png_ptr, png_bytep buf, png_size_t size)
{
/*PngFileInfo *fileinfo = (PngFileInfo *)png_get_io_ptr(png_ptr);
if (fileinfo->offset + size <= fileinfo->len) {
memcpy(buf, fileinfo->data + fileinfo->offset, size);
fileinfo->offset += size;
} else {
png_error(png_ptr,"png_mem_read_func failed");
}*/
unsigned char** data = (unsigned char **)png_get_io_ptr(png_ptr);
*data += (int)size;
return;
}
int PgPngRead(Image* image,int mode,unsigned int FileNo)
{
unsigned int sig_read = 0;
png_uint_32 width;
png_uint_32 height;
int bit_depth;
int color_type;
int interlace_type;
int x;
int y;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) return -102;
png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn);
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) return -103;
if (mode == 0) {
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, sig_read);
} else {
unsigned char* fileinfo = (unsigned char*)PgRamDataGet(FileNo);
png_set_read_fn(png_ptr,(png_voidp)&fileinfo,(png_rw_ptr)PngRamDiskRead);
}
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
if (width > 2048 || height > 2048) return -104;
image->imageWidth = width;
image->imageHeight = height;
if (width > 512) {
image->textureWidth = width;
} else {
image->textureWidth = getNextPower2(width);
}
if (height > 512 ) {
image->textureHeight = height;
} else {
image->textureHeight = getNextPower2(height);
}
image->ColorType = color_type;
if (color_type == PNG_COLOR_TYPE_PALETTE) {
image->BitDepth = bit_depth;
png_colorp palette = NULL;
int num_palette = 0;
png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
int i;
image->ClutPlteCount = num_palette;
int wcolor;
for(i=0; i<num_palette; i++, palette++){
wcolor = palette->red;
wcolor = (wcolor << 8) | palette->green;
wcolor = (wcolor << 8) | palette->blue;
image->ClutPlte[i] = (0xff000000 | wcolor);
}
} else {
image->BitDepth = bit_depth;
image->ClutPlteCount = 0;
}
int w_size = png_get_rowbytes(png_ptr, info_ptr);
image->MemType = PG_MEMTYPE_SYSTEM;
image->TexType = 0;
switch(bit_depth) {
case 4:
{
image
->data
= malloc(image
->textureWidth
*image
->textureHeight
/2); if (!image->data) return -105;
char *line = (char*)&linewrk;
char color;
for (y = 0; y < height; y++) {
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
for (x = 0; x < image->textureWidth/2 ; x++) {
color = line[x];
image->data[x + y * image->textureWidth/2] = ( (color >> 4) | (color << 4) );
}
}
}
break;
case 8:
{
image
->data
= malloc(image
->textureWidth
*image
->textureHeight
); if (!image->data) return -105;
char *line = (char*)&linewrk;
char color;
for (y = 0; y < height; y++) {
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
for (x = 0; x < w_size; x++) {
color = line[x];
image->data[x + y * w_size] = color;
}
}
}
break;
case 16:
{
u16 *line = (u16*)&linewrk;
u16 color;
for (y = 0; y < height; y++) {
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
for (x = 0; x < w_size; x++) {
color = line[x];
image->data[x + y * w_size] = color;
}
}
}
break;
case 32:
{
u32 *line = (u32*)&linewrk;
u32 color;
for (y = 0; y < height; y++) {
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
for (x = 0; x < w_size; x++) {
color = line[x];
image->data[x + y * w_size] = color;
}
}
}
break;
default:
return -106;
break;
}
png_read_end(png_ptr, info_ptr);
return 0;
}
int PgPngLoadRam(unsigned int FileNo,Image* image)
{
int ret = 0;
if (FileNo > (RAMFILEMAX - 1)) return -100;
if (PgRamDataChk(FileNo) == -1) return -101;
ret = PgPngRead(image,1,FileNo);
if (ret == -102) return ret;
if (ret == -103) {
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
} else {
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
}
return ret;
}
int PgPngLoadDisk(const char* filename,Image* image)
{
int ret = 0;
if ((fp
= fopen(filename
, "rb")) == NULL
) return -101;
ret = PgPngRead(image,0,0);
if (ret == -102) return ret;
if (ret == -103) {
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
} else {
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
}
return ret;
}