ew-engine/hq engine src/png_loader.c
2006-10-08 00:00:00 +00:00

246 lines
6.2 KiB
C

#include "quakedef.h"
#include "png.h"
typedef struct png_s
{ // TPng = class(TGraphic)
char *tmpBuf;
int tmpi;
long FBgColor; // DL Background color Added 30/05/2000
int FTransparent; // DL Is this Image Transparent Added 30/05/2000
long FRowBytes; //DL Added 30/05/2000
double FGamma; //DL Added 07/06/2000
double FScreenGamma; //DL Added 07/06/2000
char *FRowPtrs; // DL Changed for consistancy 30/05/2000
char* Data; //property Data: pByte read fData;
char* Title;
char* Author;
char* Description;
int BitDepth;
int BytesPerPixel;
int ColorType;
int Height;
int Width;
int Interlace;
int Compression;
int Filter;
double LastModified;
int Transparent;
} png_t;
png_t *my_png=0;
unsigned char* pngbytes;
//_____________________________________________________________________________
void InitializeDemData()
{
long* cvaluep; //ub
long y;
// Initialize Data and RowPtrs
if(my_png->Data)
{
//Z_Free(my_png->Data);
free(my_png->Data);
my_png->Data = 0;
}
if(my_png->FRowPtrs)
{
//Z_Free(my_png->FRowPtrs);
free(my_png->FRowPtrs);
my_png->FRowPtrs = 0;
}
//my_png->Data = Z_Malloc(my_png->Height * my_png->FRowBytes ); // DL Added 30/5/2000
//my_png->FRowPtrs = Z_Malloc(sizeof(void*) * my_png->Height);
my_png->Data = malloc(my_png->Height * my_png->FRowBytes ); // DL Added 30/5/2000
my_png->FRowPtrs = malloc(sizeof(void*) * my_png->Height);
if((my_png->Data)&&(my_png->FRowPtrs))
{
cvaluep = (long*)my_png->FRowPtrs;
for(y=0;y<my_png->Height;y++)
{
cvaluep[y] = (long)my_png->Data + ( y * (long)my_png->FRowBytes ); //DL Added 08/07/2000
}
}
}
//_____________________________________________________________________________
void mypng_struct_create()
{
if(my_png) return;
//my_png = Z_Malloc(sizeof(png_t));
my_png = malloc(sizeof(png_t));
my_png->Data = 0;
my_png->FRowPtrs = 0;
my_png->Height = 0;
my_png->Width = 0;
my_png->ColorType = PNG_COLOR_TYPE_RGB;
my_png->Interlace = PNG_INTERLACE_NONE;
my_png->Compression = PNG_COMPRESSION_TYPE_DEFAULT;
my_png->Filter = PNG_FILTER_TYPE_DEFAULT;
}
//_____________________________________________________________________________
void mypng_struct_destroy(qboolean keepData) {
if(!my_png)
return;
if(my_png->Data && !keepData)
//Z_Free(my_png->Data);
free(my_png->Data);
if(my_png->FRowPtrs)
//Z_Free(my_png->FRowPtrs);
free(my_png->FRowPtrs);
//Z_Free(my_png);
free(my_png);
my_png = 0;
}
//_____________________________________________________________________________
void PNGAPI fReadData(png_structp png,png_bytep data,png_size_t length) { // called by pnglib
int i;
//for(i=0;i<length;i++)
for(i=0;i<(int)length;i++)
data[i] = my_png->tmpBuf[my_png->tmpi++]; // give pnglib a some more bytes
}
//_____________________________________________________________________________
int Filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
//fseek (f, pos, SEEK_SET);
fseek (f, 0, SEEK_SET);
return end;
}
//Tei png version, ripped and adapted from sul_png.c from Quake2max
byte * LoadPNG (FILE *fin,char * name)
{
png_structp png;
png_infop pnginfo;
byte ioBuffer[8192];
int len;
byte *raw;
byte *imagedata;
len = Filelength(fin);
raw = malloc(len+1);//Z_Malloc(len + 1);
fread (raw, 1, len, fin);
if (!raw)
{
Con_Printf ("Bad png file %s\n", name);
return 0;
}
if( png_sig_cmp(raw,0,4))
return 0;
png = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
if(!png)
return 0;
pnginfo = png_create_info_struct( png );
if(!pnginfo)
{
png_destroy_read_struct(&png,&pnginfo,0);
return 0;
}
png_set_sig_bytes(png,0/*sizeof( sig )*/);
mypng_struct_create(); // creates the my_png struct
my_png->tmpBuf = raw; //buf = whole file content
my_png->tmpi=0;
png_set_read_fn(png,ioBuffer,fReadData );
png_read_info( png, pnginfo );
png_get_IHDR(png, pnginfo, &my_png->Width, &my_png->Height,&my_png->BitDepth, &my_png->ColorType, &my_png->Interlace, &my_png->Compression, &my_png->Filter );
// ...removed bgColor code here...
if (my_png->ColorType == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png);
#if 0
if (my_png->ColorType == PNG_COLOR_TYPE_GRAY && my_png->BitDepth < 8)
png_set_gray_1_2_4_to_8(png);
#else //BorisU
if (my_png->ColorType == PNG_COLOR_TYPE_GRAY || my_png->ColorType == PNG_COLOR_TYPE_GRAY_ALPHA){
png_set_gray_to_rgb(png);
if (my_png->BitDepth < 8)
png_set_gray_1_2_4_to_8(png);
}
#endif
// Add alpha channel if present
if(png_get_valid( png, pnginfo, PNG_INFO_tRNS ))
png_set_tRNS_to_alpha(png);
// hax: expand 24bit to 32bit
#if 0
if (my_png->BitDepth == 8 && my_png->ColorType == PNG_COLOR_TYPE_RGB)
png_set_filler(png,255, PNG_FILLER_AFTER);
#else // BorisU
if (my_png->BitDepth == 8 && !(my_png->ColorType & PNG_COLOR_MASK_ALPHA) )
png_set_filler(png, 255, PNG_FILLER_AFTER);
#endif
if (( my_png->ColorType == PNG_COLOR_TYPE_GRAY) || (my_png->ColorType == PNG_COLOR_TYPE_GRAY_ALPHA ))
png_set_gray_to_rgb( png );
if (my_png->BitDepth < 8)
png_set_expand (png);
// update the info structure
png_read_update_info( png, pnginfo );
my_png->FRowBytes = png_get_rowbytes( png, pnginfo );
my_png->BytesPerPixel = png_get_channels( png, pnginfo ); // DL Added 30/08/2000
InitializeDemData();
if((my_png->Data)&&(my_png->FRowPtrs))
png_read_image(png, (png_bytepp)my_png->FRowPtrs);
png_read_end(png, pnginfo); // read last information chunks
png_destroy_read_struct(&png, &pnginfo, 0);
//only load 32 bit by now...
if (my_png->BitDepth == 8)
{
image_width = my_png->Width;
image_height = my_png->Height;
imagedata = my_png->Data;
}
else
{
Con_Printf ("Bad png color depth: %s\n", name);
//*pic = NULL;
imagedata = 0;
//Z_Free( my_png->Data );
free( my_png->Data );
//Z_Free( raw );
free(raw);
}
mypng_struct_destroy(true);
fclose( fin );
return imagedata;
}
//Tei png version, ripped and adapted from sul_png.c from Quake2max
//_____________________________________________________________________________