mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 17:48:46 -10:00
182 lines
3.4 KiB
C++
182 lines
3.4 KiB
C++
#include "ddsutils/ddsutils.h"
|
|
#include "cfile/cfile.h"
|
|
|
|
int Texture_compression_enabled=0;
|
|
|
|
static int dds_read_header_internal(LPDDSURFACEDESC2 lpddsd, char *filename, int *width, int *height, int *bpp, int *compression_type, int *levels)
|
|
{
|
|
char code[5];
|
|
CFILE *ddsfile;
|
|
char real_name[MAX_FILENAME_LEN];
|
|
char *p;
|
|
int retval=DDS_ERROR_NONE;
|
|
int ct;
|
|
int bits=0;
|
|
|
|
//this better not happen.. ever
|
|
Assert(filename!=NULL);
|
|
|
|
//make sure there is an extension
|
|
strcpy(real_name, filename);
|
|
p=strchr(real_name, '.');
|
|
if (p) *p=0;
|
|
strcat(real_name, ".dds");
|
|
|
|
memset(code,0,sizeof(code));
|
|
//try to open the file
|
|
ddsfile = cfopen(real_name, "rb");
|
|
|
|
//file not found
|
|
if (!ddsfile)
|
|
{
|
|
return DDS_ERROR_INVALID_FILENAME;
|
|
}
|
|
|
|
//read the code
|
|
cfread(code,1,4,ddsfile);
|
|
code[4]=0;
|
|
|
|
//check it
|
|
if (strncmp(code,DDS_FILECODE,4)!=0)
|
|
{
|
|
return DDS_ERROR_BAD_HEADER;
|
|
}
|
|
|
|
//read the header
|
|
cfread(lpddsd,sizeof(DDSURFACEDESC2),1,ddsfile);
|
|
|
|
//stuff important info
|
|
if (width)
|
|
*width = lpddsd->dwWidth;
|
|
|
|
if (height)
|
|
*height = lpddsd->dwHeight;
|
|
|
|
if (levels)
|
|
*levels = lpddsd->dwMipMapCount;
|
|
|
|
switch(lpddsd->ddpfPixelFormat.dwFourCC)
|
|
{
|
|
case FOURCC_DXT1:
|
|
bits=24;
|
|
ct=DDS_DXT1;
|
|
break;
|
|
|
|
case FOURCC_DXT3:
|
|
bits=32;
|
|
ct=DDS_DXT3;
|
|
break;
|
|
|
|
case FOURCC_DXT5:
|
|
bits=32;
|
|
ct=DDS_DXT5;
|
|
break;
|
|
|
|
//dxt2 and dxt4 aren't supported
|
|
case FOURCC_DXT2:
|
|
case FOURCC_DXT4:
|
|
retval=DDS_ERROR_INVALID_FORMAT;
|
|
ct=DDS_DXT_INVALID;
|
|
break;
|
|
|
|
//none of the above
|
|
default:
|
|
retval=DDS_ERROR_UNCOMPRESSED;
|
|
ct=DDS_DXT_INVALID;
|
|
break;
|
|
}
|
|
|
|
if (bpp) *bpp=bits;
|
|
if (compression_type) *compression_type=ct;
|
|
|
|
//close file and return
|
|
cfclose(ddsfile);
|
|
return retval;
|
|
}
|
|
|
|
int dds_read_header(char *filename, int *width, int *height, int *bpp, int *compression_type, int *levels)
|
|
{
|
|
DDSURFACEDESC2 ddsd;
|
|
return dds_read_header_internal(&ddsd, filename, width, height, bpp, compression_type, levels);
|
|
}
|
|
|
|
//reads pixel info from a dds file
|
|
int dds_read_bitmap(char *filename, int *size, uint* data)
|
|
{
|
|
int retval;
|
|
DDSURFACEDESC2 ddsd;
|
|
int w,h,ct,bpp;
|
|
CFILE *cfp;
|
|
ubyte* tmp;
|
|
|
|
//this must be set
|
|
Assert(size!=NULL);
|
|
|
|
//read the header -- if its at this stage, it should be legal.
|
|
retval=dds_read_header_internal(&ddsd, filename, &w, &h, &bpp, &ct);
|
|
Assert(retval==DDS_ERROR_NONE);
|
|
|
|
//get some more info from the surface
|
|
*size=ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * 2 : ddsd.dwLinearSize;
|
|
|
|
//open it up and go to the data section
|
|
cfp=cfopen(filename,"rb");
|
|
cfseek(cfp,DDS_OFFSET, CF_SEEK_SET);
|
|
|
|
//get the data
|
|
tmp=(ubyte*)malloc(*size);
|
|
|
|
if (!tmp)
|
|
{
|
|
cfclose(cfp);
|
|
return DDS_ERROR_NO_MEM; //barf
|
|
}
|
|
|
|
cfread(tmp,1,*size,cfp);
|
|
|
|
*data=(uint)tmp;
|
|
//we look done here
|
|
cfclose(cfp);
|
|
return DDS_ERROR_NONE;
|
|
}
|
|
|
|
//returns string representation of DDS_** error code
|
|
const char *dds_error_string(int code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case DDS_ERROR_NONE:
|
|
return "No error";
|
|
|
|
case DDS_ERROR_NO_MEM:
|
|
return "Insufficient memory";
|
|
|
|
case DDS_ERROR_INVALID_FILENAME:
|
|
return "File not found";
|
|
|
|
case DDS_ERROR_BAD_HEADER:
|
|
return "Filecode did not equal \"DDS \"";
|
|
|
|
case DDS_ERROR_INVALID_FORMAT:
|
|
return "File was compressed, but it was DXT2 or DXT4";
|
|
|
|
case DDS_ERROR_UNCOMPRESSED:
|
|
return "*.DDS files must be compressed and use DXT1, DXT3, or DXT5 compression";
|
|
|
|
default:
|
|
return "Abort, retry, fail?";
|
|
}
|
|
|
|
//get a warning otherwise
|
|
return "Abort, retry, fail?";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|