Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
409 lines
7.7 KiB
C++
409 lines
7.7 KiB
C++
#include"image.h"
|
|
#include<string.h>
|
|
#include<GameOs\PNG\png.h>
|
|
|
|
int Image::IsPng(Stuff::FileStream *stream)
|
|
{
|
|
|
|
int i;
|
|
BYTE hdr[8],chdr[8];
|
|
|
|
bool ret;
|
|
|
|
chdr[0]=0x89;
|
|
chdr[1]=0x50;
|
|
chdr[2]=0x4E;
|
|
chdr[3]=0x47;
|
|
chdr[4]=0x0D;
|
|
chdr[5]=0x0A;
|
|
chdr[6]=0x1A;
|
|
chdr[7]=0x0A;
|
|
|
|
stream->ReadBytes(hdr,8);
|
|
ret=true;
|
|
for(i=0;i<8;i++)
|
|
{
|
|
if(hdr[i]!=chdr[i]) ret=false;
|
|
}
|
|
|
|
stream->Rewind();
|
|
return ret;
|
|
|
|
}
|
|
|
|
FILE *imgpngfl=NULL;
|
|
Stuff::FileStream *imgpngstream=NULL;
|
|
|
|
void imlibPngReadCallback(png_structp png, png_bytep pbtData, png_size_t nLength)
|
|
{
|
|
Verify((imgpngstream!=NULL && imgpngfl==NULL) || (imgpngstream==NULL && imgpngfl!=NULL));
|
|
|
|
if(imgpngfl)
|
|
fread((LPVOID)pbtData,nLength,1,imgpngfl);
|
|
else
|
|
imgpngstream->ReadBytes(pbtData,nLength);
|
|
}
|
|
|
|
void imlibPngWriteCallback(png_structp png, png_bytep pbtData, png_size_t nLength)
|
|
{
|
|
Verify((imgpngstream!=NULL && imgpngfl==NULL) || (imgpngstream==NULL && imgpngfl!=NULL));
|
|
|
|
if(imgpngfl)
|
|
fwrite(pbtData,nLength,1,imgpngfl);
|
|
else
|
|
imgpngstream->WriteBytes(pbtData,nLength);
|
|
}
|
|
|
|
|
|
void Image::InternalLoadPng()
|
|
{
|
|
png_structp m_png; // Our PNG ADT
|
|
png_infop m_pPngInfo; // Info retrieved from the PNG data up to IDAT chunk
|
|
|
|
int m_nColorType;
|
|
int m_nInterlaceType;
|
|
int m_nBitDepth;
|
|
|
|
|
|
//
|
|
// Reading PNG files
|
|
//
|
|
m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
m_pPngInfo = png_create_info_struct(m_png);
|
|
if( m_pPngInfo == NULL )
|
|
STOP(( "Error Reading file '%s'",fname ));
|
|
|
|
#pragma warning( disable: 4611 )
|
|
setjmp(m_png->jmpbuf);
|
|
#pragma warning( default: 4611 )
|
|
|
|
|
|
png_set_read_fn( m_png, 0, imlibPngReadCallback );
|
|
|
|
png_read_info(m_png, m_pPngInfo);
|
|
|
|
png_uint_32 nDummy;
|
|
int nCompressionType, nFilterType;
|
|
png_get_IHDR(m_png, m_pPngInfo, &nDummy, &nDummy, &m_nBitDepth, &m_nColorType, &m_nInterlaceType, &nCompressionType, &nFilterType);
|
|
|
|
/*
|
|
if (m_nColorType == PNG_COLOR_TYPE_PALETTE)
|
|
png_set_expand(m_png);
|
|
|
|
if (m_nColorType == PNG_COLOR_TYPE_GRAY && m_nBitDepth < 8)
|
|
png_set_expand(m_png);
|
|
|
|
if (m_nColorType == PNG_COLOR_TYPE_GRAY)
|
|
png_set_gray_to_rgb(m_png);
|
|
|
|
if (png_get_valid(m_png, m_pPngInfo, PNG_INFO_tRNS))
|
|
png_set_expand(m_png);
|
|
|
|
png_set_bgr(m_png);
|
|
png_set_filler(m_png, 0xff, PNG_FILLER_AFTER);
|
|
*/
|
|
xpos=ypos=0;
|
|
vxlen=xlen=m_pPngInfo->width;
|
|
vylen=ylen=m_pPngInfo->height;
|
|
Bpp=m_pPngInfo->pixel_depth;
|
|
|
|
itype=ITYPE_RGB;
|
|
|
|
if (m_nColorType == PNG_COLOR_TYPE_PALETTE)
|
|
itype=ITYPE_INDEXED;
|
|
|
|
if (m_nColorType == PNG_COLOR_TYPE_GRAY && m_nBitDepth < 8)
|
|
itype=ITYPE_INDEXED;
|
|
|
|
if (m_nColorType == PNG_COLOR_TYPE_GRAY)
|
|
itype=ITYPE_INDEXED;
|
|
|
|
if(itype==ITYPE_INDEXED) MakeGrayscalePalette();
|
|
IAlloc();
|
|
BYTE *dat=(BYTE *)Lock();
|
|
|
|
for( int y=0; y<ylen; y++ )
|
|
{
|
|
png_read_row(m_png, (BYTE*)dat+Pitch*y, NULL);
|
|
}
|
|
//
|
|
// Clean up PNG reading
|
|
//
|
|
UnLock();
|
|
png_read_end(m_png, m_pPngInfo);
|
|
png_destroy_read_struct(&m_png, (png_infopp)(m_pPngInfo ? &m_pPngInfo : NULL), (png_infopp)NULL );
|
|
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0x0000ff,0x00ff00,0xff0000);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x000000ff,0x0000ff00,0x00ff0000,0xff000000);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void Image::LoadPng(Stuff::FileStream *stream)
|
|
{
|
|
imgpngfl=NULL;
|
|
imgpngstream=stream;
|
|
InternalLoadPng();
|
|
}
|
|
|
|
void Image::LoadPng(FILE *fl)
|
|
{
|
|
imgpngfl=fl;
|
|
imgpngstream=NULL;
|
|
InternalLoadPng();
|
|
}
|
|
|
|
|
|
void Image::InternalSavePng()
|
|
{
|
|
png_structp m_png; // Our PNG ADT
|
|
png_infop m_pPngInfo; // Info retrieved from the PNG data up to IDAT chunk
|
|
|
|
m_png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
m_pPngInfo = png_create_info_struct(m_png);
|
|
|
|
#pragma warning( disable: 4611 )
|
|
setjmp(m_png->jmpbuf);
|
|
#pragma warning( default: 4611 )
|
|
|
|
png_set_write_fn( m_png, 0, imlibPngWriteCallback ,NULL);
|
|
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
MaskTo(RGBMask(0x0000ff,0x00ff00,0xff0000));
|
|
else
|
|
if(Bpp==32)
|
|
MaskTo(RGBMask(0x000000ff,0x0000ff00,0x00ff0000,0xff000000));
|
|
}
|
|
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
if(GetBpp()==32)
|
|
png_set_IHDR(m_png, m_pPngInfo, xlen, ylen, 8, PNG_COLOR_TYPE_RGB_ALPHA,
|
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
|
else
|
|
png_set_IHDR(m_png, m_pPngInfo, xlen, ylen, 8, PNG_COLOR_TYPE_RGB,
|
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
|
}
|
|
else
|
|
{
|
|
png_set_IHDR(m_png, m_pPngInfo, xlen, ylen, 8, PNG_COLOR_TYPE_GRAY,
|
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
|
}
|
|
|
|
|
|
|
|
png_write_info(m_png, m_pPngInfo);
|
|
|
|
BYTE *dat=(BYTE *)Lock();
|
|
|
|
for( int y=0; y<ylen; y++ )
|
|
{
|
|
png_write_row(m_png, (BYTE*)dat+Pitch*y);
|
|
}
|
|
UnLock();
|
|
png_write_end(m_png, m_pPngInfo);
|
|
png_destroy_write_struct(&m_png, (png_infopp)(m_pPngInfo ? &m_pPngInfo : NULL));
|
|
|
|
|
|
}
|
|
|
|
|
|
void Image::SavePng(Stuff::FileStream *stream)
|
|
{
|
|
imgpngfl=NULL;
|
|
imgpngstream=stream;
|
|
InternalSavePng();
|
|
}
|
|
|
|
void Image::SavePng(FILE *fl)
|
|
{
|
|
imgpngfl=fl;
|
|
imgpngstream=NULL;
|
|
InternalSavePng();
|
|
}
|
|
|
|
void Image::GetPngInfo(Stuff::FileStream *stream)
|
|
{
|
|
int i;
|
|
BYTE hdr[8],chdr[8];
|
|
|
|
unsigned int cnkhdr=0,chunksize,chunktag;
|
|
|
|
chdr[0]=0x89;
|
|
chdr[1]=0x50;
|
|
chdr[2]=0x4E;
|
|
chdr[3]=0x47;
|
|
chdr[4]=0x0D;
|
|
chdr[5]=0x0A;
|
|
chdr[6]=0x1A;
|
|
chdr[7]=0x0A;
|
|
|
|
stream->ReadBytes(hdr,8);
|
|
for(i=0;i<8;i++)
|
|
{
|
|
if(hdr[i]!=chdr[i]) GENFERR("Not a png file");
|
|
}
|
|
|
|
|
|
stream->ReadBytes(&chunksize,4);
|
|
stream->ReadBytes(&chunktag,4);
|
|
|
|
stream->ReadBytes(&xlen,4);
|
|
stream->ReadBytes(&ylen,4);
|
|
stream->ReadBytes(&ylen,4);
|
|
|
|
Bpp=0;
|
|
stream->ReadBytes(&Bpp,1);
|
|
|
|
BYTE tbt;
|
|
stream->ReadBytes(&tbt,1);
|
|
|
|
if(tbt==3)
|
|
itype=ITYPE_INDEXED;
|
|
else
|
|
itype=ITYPE_RGB;
|
|
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0x0000ff,0x00ff00,0xff0000);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x0000ff00,0x00ff0000,0xff000000,0x000000ff);
|
|
}
|
|
|
|
}
|
|
|
|
int Image::IsPng()
|
|
{
|
|
char *spos;
|
|
spos=NULL;
|
|
int i,slen=strlen(fname);
|
|
for(i=slen-1;i>=0 && fname[i]!='.';i--);
|
|
if(i<0) return 0;
|
|
if(fname[i]=='.') spos=fname+i+1;
|
|
return !strcmpi("png",spos);
|
|
}
|
|
|
|
int Image::IsPng(FILE *fl)
|
|
{
|
|
if(!fl) GENNFERR("Invalid File");
|
|
|
|
int i;
|
|
BYTE hdr[8],chdr[8];
|
|
int fpos=ftell(fl);
|
|
|
|
bool ret;
|
|
|
|
chdr[0]=0x89;
|
|
chdr[1]=0x50;
|
|
chdr[2]=0x4E;
|
|
chdr[3]=0x47;
|
|
chdr[4]=0x0D;
|
|
chdr[5]=0x0A;
|
|
chdr[6]=0x1A;
|
|
chdr[7]=0x0A;
|
|
|
|
fread(hdr,8,1,fl);
|
|
ret=true;
|
|
for(i=0;i<8;i++)
|
|
{
|
|
if(hdr[i]!=chdr[i]) ret=false;
|
|
}
|
|
|
|
fseek(fl,fpos,SEEK_SET);
|
|
return ret;
|
|
}
|
|
|
|
void Image::LoadPng(char *str)
|
|
{
|
|
Stuff::FileStream stream;
|
|
stream.Open(str,Stuff::FileStream::ReadOnly);
|
|
LoadPng(&stream);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
void Image::GetPngInfo(FILE *fl)
|
|
{
|
|
int i,pos;
|
|
BYTE hdr[8],chdr[8];
|
|
pos=ftell(fl);
|
|
|
|
unsigned int cnkhdr=0,chunksize,chunktag;
|
|
|
|
chdr[0]=0x89;
|
|
chdr[1]=0x50;
|
|
chdr[2]=0x4E;
|
|
chdr[3]=0x47;
|
|
chdr[4]=0x0D;
|
|
chdr[5]=0x0A;
|
|
chdr[6]=0x1A;
|
|
chdr[7]=0x0A;
|
|
|
|
fread(hdr,8,1,fl);
|
|
for(i=0;i<8;i++)
|
|
{
|
|
if(hdr[i]!=chdr[i]) GENFERR("Not a png file");
|
|
}
|
|
|
|
|
|
fread(&chunksize,4,0,fl);
|
|
fread(&chunktag,4,0,fl);
|
|
|
|
fread(&xlen,4,0,fl);
|
|
fread(&ylen,4,0,fl);
|
|
|
|
fread(&ylen,4,0,fl);
|
|
|
|
Bpp=(int)getc(fl);
|
|
|
|
if(getc(fl)==3)
|
|
itype=ITYPE_INDEXED;
|
|
else
|
|
itype=ITYPE_RGB;
|
|
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0x0000ff,0x00ff00,0xff0000);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x0000ff00,0x00ff0000,0xff000000,0x000000ff);
|
|
}
|
|
|
|
}
|
|
|
|
void Image::GetPngInfo(char *str)
|
|
{
|
|
Stuff::FileStream stream;
|
|
stream.Open(str,Stuff::FileStream::ReadOnly);
|
|
GetPngInfo(&stream);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Image::SavePng(char *str)
|
|
{
|
|
Stuff::FileStream stream;
|
|
stream.Open(str,Stuff::FileStream::WriteOnly);
|
|
SavePng(&stream);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
|