Files
firestorm/Gameleap/code/mw4/Libraries/imagelib/Png.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

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);
}