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.
547 lines
15 KiB
C++
547 lines
15 KiB
C++
#include"image.h"
|
|
#include<string.h>
|
|
|
|
int Image::IsTiff(FILE *fl)
|
|
{
|
|
unsigned short int tmps;
|
|
|
|
if(!fl) GENNFERR("(Is Tiff)Invalid File");
|
|
int fpos=ftell(fl);
|
|
|
|
fread(&tmps,2,1,fl); // read data type
|
|
if(tmps==0x4949 || tmps==0x4d4d)
|
|
{
|
|
fread(&tmps,2,1,fl); // read data type
|
|
fseek(fl,fpos,SEEK_SET);
|
|
if(tmps==0x2a) return 1;
|
|
}
|
|
fseek(fl,fpos,SEEK_SET);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Image::LoadTiff(char *str)
|
|
{
|
|
FILE *fl=fopen(str,"rb");
|
|
|
|
if(!fl)
|
|
{
|
|
char tfn[MAX_PATH*2];
|
|
strcpy(tfn,"Cannont open TIF file for reading:");
|
|
strcat(tfn,str);
|
|
GENNFERR(tfn);
|
|
}
|
|
|
|
LoadTiff(fl);
|
|
fclose(fl);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
void Image::SaveTiff(char *str)
|
|
{
|
|
FILE *fl=fopen(str,"wb");
|
|
|
|
if(!fl)
|
|
{
|
|
char tfn[200];
|
|
strcpy(tfn,"Cannont open TIF file for Writeing:");
|
|
strcat(tfn,str);
|
|
GENNFERR(tfn);
|
|
}
|
|
|
|
SaveTiff(fl);
|
|
fclose(fl);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
|
|
//>>>>>>>>Tiff
|
|
void Image::LoadTiff(FILE *fl)
|
|
{
|
|
unsigned char *odata,*cdata;
|
|
long int *sloc,*bps;
|
|
long int i,initpos,fpos,tmpl,comp=999;
|
|
long int strip,rps,samples;
|
|
short int abts,rbts,gbts,bbts,tmps,nof,nos;
|
|
long unsigned int *codetable;
|
|
unsigned char *FileBuf;
|
|
int dflag=0;
|
|
abts=0;
|
|
initpos=ftell(fl); //get file position
|
|
|
|
fread(&tmps,2,1,fl); // read data type
|
|
switch(tmps)
|
|
{
|
|
case 0x4949: break; //LSB
|
|
case 0x4D4D: GENNFERR("Tiff Error-Mac Images unsupported"); break; //MSB
|
|
default: GENNFERR("Tiff Error-Undefined Byte ordering");
|
|
}
|
|
|
|
fread(&tmps,2,1,fl); // read version number
|
|
if(tmps!=0x2a) GENNFERR("Tiff Error-Wrong Version"); //wrong version
|
|
|
|
fread(&tmpl,4,1,fl); // read offset to directory
|
|
fseek(fl,tmpl+initpos,SEEK_SET); // setposition
|
|
|
|
fread(&nof,2,1,fl); // read number of fieldss
|
|
|
|
for(i=0;i<nof;i++)
|
|
{
|
|
struct { short int tag,type; long int lenght,offset;} field;
|
|
fread(&field,12,1,fl); // read number of field
|
|
|
|
fpos=ftell(fl); //get file position
|
|
switch(field.tag)
|
|
{
|
|
case 254: //File Subtype
|
|
break;
|
|
|
|
case 256: vxlen=xlen=field.offset; break; //Get xsize
|
|
case 257: vylen=ylen=field.offset; break; //Get ysize
|
|
|
|
case 258: //get bits per sample
|
|
fseek(fl,initpos+field.offset,SEEK_SET); // setposition
|
|
fread(&rbts,2,1,fl); // red bits
|
|
fread(&gbts,2,1,fl); // green bits
|
|
fread(&bbts,2,1,fl); // blue bits
|
|
if(field.lenght>3)
|
|
fread(&abts,2,1,fl); // alpha bits ABCD :)
|
|
break;
|
|
|
|
case 259: //get compression scheme
|
|
comp=field.offset;
|
|
if(comp!=1 && comp!=5) GENNFERR("Tiff Error-Unsupported Compression"); //for uncompressed
|
|
break;
|
|
|
|
case 262: //get photometric interp
|
|
if(field.offset!=2) GENNFERR("Tiff Error-Image Not RGB"); // not RGB
|
|
break;
|
|
|
|
case 273: //get striplocation
|
|
nos=(short int)field.lenght;
|
|
sloc=new long int[nos];
|
|
if(nos<=1) sloc[0]=(short unsigned int)field.offset;
|
|
else
|
|
{
|
|
fseek(fl,initpos+field.offset,SEEK_SET); // setposition
|
|
if(field.type==3) fread(sloc,2*nos,1,fl);
|
|
else if(field.type==4) fread(sloc,4*nos,1,fl);
|
|
else GENNFERR("Tiff Error");
|
|
|
|
}
|
|
break;
|
|
|
|
case 277: //samples per pixel
|
|
samples=field.offset;
|
|
switch(samples)
|
|
{
|
|
case 4:
|
|
case 3:
|
|
case 2:
|
|
itype=ITYPE_RGB;
|
|
Bpp=8*samples;
|
|
break;
|
|
|
|
default:
|
|
GENNFERR("Tiff Error-Invalid Pixel Format");
|
|
}
|
|
break;
|
|
|
|
case 278: rps=field.offset; break; //rowsperstrip
|
|
|
|
case 279:
|
|
bps=new long int[nos];
|
|
if(nos<=1) bps[0]=(short unsigned int)field.offset;
|
|
else
|
|
{
|
|
fseek(fl,initpos+field.offset,SEEK_SET); // setposition
|
|
fread(bps,nos*4,1,fl);
|
|
}
|
|
break; //bytesperstrip
|
|
|
|
case 282: break; //pixels per xres
|
|
case 283: break; //pixels per yres
|
|
|
|
case 284: //sampleplanes
|
|
if(field.offset!=1) GENNFERR("Tiff Error-Not Single Plane"); //not single planer
|
|
break;
|
|
|
|
case 296: break; //resolution unit
|
|
|
|
case 317: //predictor
|
|
dflag=field.offset;
|
|
if(dflag!=1 && dflag!=2) GENNFERR("Tiff Error-Invalid Diff"); //uses differtiation
|
|
break;
|
|
|
|
} //end of switch
|
|
fseek(fl,fpos,SEEK_SET); // resetposition
|
|
} //end of number of fields
|
|
|
|
if(abts) Mask.Set(0x000000ff,0x0000ff00,0x00ff0000,0xff000000);
|
|
else Mask.Set(0x000000ff,0x0000ff00,0x00ff0000,0) ;
|
|
|
|
IAlloc();
|
|
cdata=Lock();
|
|
odata=cdata;
|
|
|
|
//begin decompression
|
|
|
|
codetable=new DWORD[4096*4];
|
|
|
|
if(comp==5)
|
|
for(strip=0;strip<nos;strip++)
|
|
{
|
|
int endflag=1,bitlen=9,totalbits=0,newcode;
|
|
int bytecount,currentcode=258;
|
|
register DWORD li;
|
|
DWORD offset=0,databuf=0,mask;
|
|
bytecount=rps*(Bpp>>3)*xlen;
|
|
|
|
fseek(fl,initpos+sloc[strip],SEEK_SET); //goto strip
|
|
FileBuf= new unsigned char[bps[strip]];
|
|
fread(FileBuf,bps[strip],1,fl);
|
|
int fbufcnt=0;
|
|
|
|
mask=(1<<bitlen)-1;
|
|
while(endflag && bytecount>0)
|
|
{ //do lzw
|
|
while(totalbits<bitlen) //get more data
|
|
{
|
|
databuf=(databuf<<8)+(DWORD)FileBuf[fbufcnt++]; totalbits+=8; }
|
|
|
|
|
|
newcode=(databuf>>(totalbits-bitlen))&mask; //get the code
|
|
totalbits-=bitlen;
|
|
|
|
if (newcode==257) endflag=0;
|
|
else // end code
|
|
if (newcode==256) {bitlen=9; currentcode=257; mask=(1<<bitlen)-1;} // clearcode
|
|
else
|
|
if (newcode<256)
|
|
{
|
|
cdata[offset]=(unsigned char)newcode;
|
|
codetable[currentcode]=offset++;
|
|
codetable[currentcode+1]=offset;
|
|
bytecount--;
|
|
}
|
|
else
|
|
{
|
|
if (newcode>currentcode) GENNFERR("Tiff Decompression Error"); //check for bad code
|
|
codetable[currentcode]=offset;
|
|
|
|
for(li=codetable[newcode];li<=codetable[newcode+1];li++)
|
|
cdata[offset++]=cdata[li];
|
|
bytecount-=codetable[newcode+1]-codetable[newcode]+1;
|
|
|
|
codetable[currentcode+1]=offset;
|
|
|
|
} //end of else >=256
|
|
|
|
if(((DWORD)++currentcode)==(DWORD)1<<bitlen && bitlen<12)
|
|
{ bitlen++; mask=(1<<bitlen)-1; }
|
|
} //end of while endflag
|
|
cdata+=offset;
|
|
delete FileBuf;
|
|
} //end of strip loop
|
|
else
|
|
if(comp==1)
|
|
for(strip=0;strip<nos;strip++)
|
|
{
|
|
fseek(fl,initpos+sloc[strip],SEEK_SET); //goto strip
|
|
fread(cdata+strip*rps*xlen*(Bpp>>3),bps[strip],1,fl);
|
|
}
|
|
|
|
CorrectPitch(); //adjust data for pitch.
|
|
if(dflag==2) UnDifference();
|
|
|
|
|
|
UnLock();
|
|
delete codetable;
|
|
delete bps;
|
|
delete sloc;
|
|
} //end of load Tiff Member
|
|
|
|
//>>>>>>>>>>>>>>>>>> File Writers
|
|
|
|
//>>>>>>>>Tiff
|
|
|
|
void Image::SaveTiff(FILE *fl)
|
|
{
|
|
int i,initpos,pos,cpos,tmpl,btotal,samples;
|
|
int strip,bps,slc,byps,nos,res,lps,bpstrip;
|
|
int *sloc,*bpsl;
|
|
unsigned char *cpydata;
|
|
WORD tmps;
|
|
short int *nptable;
|
|
DWORD *codetable;
|
|
struct { short int tag,type; long int lenght,offset;} field;
|
|
int ep,fof,evl,ocd,cnt;
|
|
unsigned char *ptmp,*p2;
|
|
int *iptmp,*ip2;
|
|
|
|
//fname=fl.GetFileName();
|
|
if(Mask.GetAMask()) MaskTo(RGBMask(0x0000ff,0x00ff00,0xff0000,0xff000000));
|
|
else MaskTo(RGBMask(0x0000ff,0x00ff00,0xff0000));
|
|
if(!IsData()) GENNFERR("(SaveTiff)Image does not contain data");
|
|
|
|
BYTE *tmpbuf;
|
|
if(Pitch==xlen*(Bpp>>3)) cpydata=Lock();
|
|
else DePitch(cpydata=tmpbuf=new BYTE[xlen*ylen*(Bpp>>3)]);
|
|
|
|
|
|
initpos=ftell(fl);
|
|
|
|
samples=Bpp>>3;
|
|
/*
|
|
switch(Bpp)
|
|
{
|
|
case 2: samples=2; break;
|
|
case 3: samples=3; break;
|
|
default : return 12;
|
|
}
|
|
*/
|
|
lps=0x4000/(xlen*samples);
|
|
bpstrip=lps*xlen*samples;
|
|
nos=ylen/lps;
|
|
if(ylen%lps) nos++;
|
|
btotal=xlen*ylen*samples;
|
|
|
|
fwrite("II",2,1,fl); //write lsb code
|
|
tmps=0x2a; fwrite(&tmps,2,1,fl); // write version number
|
|
tmpl=8; fwrite(&tmpl,4,1,fl); // write offset to directory
|
|
tmps=15; fwrite(&tmps,2,1,fl); // write number of fieldss
|
|
|
|
field.tag=254; field.type=4; field.lenght=1; field.offset=0;
|
|
fwrite(&field,12,1,fl); //write file code
|
|
|
|
field.tag=256; field.type=4; field.lenght=1; field.offset=xlen;
|
|
fwrite(&field,12,1,fl); //write file xlen
|
|
|
|
field.tag=257; field.type=4; field.lenght=1; field.offset=ylen;
|
|
fwrite(&field,12,1,fl); //write file ylen
|
|
|
|
bps=ftell(fl);
|
|
field.tag=258; field.type=3; field.lenght=3; field.offset=999;
|
|
fwrite(&field,12,1,fl); //write bit per sample
|
|
|
|
field.tag=259; field.type=3; field.lenght=1; field.offset=5;
|
|
fwrite(&field,12,1,fl); //write compression scheme(LZW)
|
|
|
|
field.tag=262; field.type=3; field.lenght=1; field.offset=2;
|
|
fwrite(&field,12,1,fl); //write photometric RGB
|
|
|
|
slc=ftell(fl);
|
|
field.tag=273; field.type=4; field.lenght=nos; field.offset=999;
|
|
fwrite(&field,12,1,fl); //write striplocation
|
|
|
|
|
|
field.tag=277; field.type=3; field.lenght=1; field.offset=samples;
|
|
fwrite(&field,12,1,fl); //write samples perpixel
|
|
|
|
field.tag=278; field.type=4; field.lenght=1; field.offset=lps;
|
|
fwrite(&field,12,1,fl); //write rows per strip
|
|
|
|
byps=ftell(fl);
|
|
field.tag=279; field.type=4; field.lenght=nos; field.offset=999;
|
|
fwrite(&field,12,1,fl); //write bytes per strip
|
|
|
|
res=ftell(fl);
|
|
field.tag=282; field.type=5; field.lenght=1; field.offset=999;
|
|
fwrite(&field,12,1,fl); //write planer
|
|
|
|
field.tag=283; field.type=5; field.lenght=1; field.offset=999;
|
|
fwrite(&field,12,1,fl); //write xres
|
|
|
|
field.tag=284; field.type=3; field.lenght=1; field.offset=1;
|
|
fwrite(&field,12,1,fl); //write yres
|
|
|
|
field.tag=296; field.type=3; field.lenght=1; field.offset=2;
|
|
fwrite(&field,12,1,fl); //write resolution
|
|
|
|
field.tag=317; field.type=3; field.lenght=1; field.offset=1;
|
|
fwrite(&field,12,1,fl); //write predictor
|
|
|
|
tmpl=0;
|
|
fwrite(&tmpl,4,1,fl); // write bits persample
|
|
|
|
pos=ftell(fl);
|
|
samples=Bpp>>3;
|
|
tmps=(WORD)Mask.GetRBits(); fwrite(&tmps,2,1,fl); // write red bits persample
|
|
tmps=(WORD)Mask.GetGBits(); fwrite(&tmps,2,1,fl); // write green bits persample
|
|
tmps=(WORD)Mask.GetBBits(); fwrite(&tmps,2,1,fl); // write blue bits persample
|
|
if(Mask.GetAMask())
|
|
{tmps=(WORD)Mask.GetABits(); fwrite(&tmps,2,1,fl); }// write alpha bits persample
|
|
|
|
cpos=ftell(fl);
|
|
fseek(fl,bps,SEEK_SET); // setposition
|
|
field.tag=258; field.type=3; field.lenght=3; field.offset=pos-initpos;
|
|
if(Mask.GetAMask()) field.lenght++;
|
|
fwrite(&field,12,1,fl); //write bit per sample
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
|
|
pos=ftell(fl);
|
|
tmpl=576; fwrite(&tmpl,4,1,fl);
|
|
tmpl=5; fwrite(&tmpl,4,1,fl);
|
|
tmpl=72; fwrite(&tmpl,4,1,fl);
|
|
tmpl=1; fwrite(&tmpl,4,1,fl);
|
|
cpos=ftell(fl);
|
|
|
|
fseek(fl,res,SEEK_SET); // setposition
|
|
field.tag=282; field.type=5; field.lenght=1; field.offset=pos-initpos;
|
|
fwrite(&field,12,1,fl); //xres
|
|
field.tag=283; field.type=5; field.lenght=1; field.offset+=8;
|
|
fwrite(&field,12,1,fl); //yres
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
|
|
sloc=new int[nos];
|
|
bpsl=new int[nos];
|
|
nptable=new short int[4096];
|
|
codetable=new DWORD[4096];
|
|
|
|
for(strip=0;strip<nos;strip++)
|
|
{
|
|
DWORD databuf=256,offset=0;
|
|
int bytecount,totalbits=9,bitlen=9,currentcode=258;
|
|
int endflag=1,match=0;
|
|
unsigned char tbyte;
|
|
|
|
bytecount=bpstrip;
|
|
|
|
if(bytecount>btotal) bytecount=btotal;
|
|
else btotal-=bytecount;
|
|
|
|
sloc[strip]=ftell(fl)-initpos;
|
|
|
|
for(i=0;i<4096;i++) nptable[i]=-1;
|
|
|
|
while (endflag)
|
|
{
|
|
while(totalbits>=8) { tbyte=(unsigned char)(databuf>>(totalbits-8))&0xff; fwrite(&tbyte,1,1,fl); totalbits-=8;}
|
|
codetable[currentcode]=offset;
|
|
|
|
ptmp=cpydata+offset;
|
|
iptmp=(int *)ptmp;
|
|
match=0;
|
|
ocd=nptable[*ptmp]; // get the starting reference code
|
|
while(ocd!=-1 && !match) // if there is a prior code and no match
|
|
{
|
|
fof=codetable[ocd];
|
|
evl=(codetable[ocd+1]-fof)+1;
|
|
p2=cpydata+fof;
|
|
ip2=(int *)p2;
|
|
|
|
if (evl<=bytecount)
|
|
{
|
|
ep=evl>>2; //dword method
|
|
for(cnt=0;cnt<ep && ip2[cnt]==iptmp[cnt];cnt++); //compare dwords
|
|
for(cnt<<=2;cnt<evl && p2[cnt]==ptmp[cnt];cnt++); //compare end bytes
|
|
}
|
|
|
|
if(cnt==evl && cnt<=bytecount)
|
|
{
|
|
match=1; //set the match
|
|
databuf=(databuf<<bitlen)|(DWORD)(ocd);
|
|
totalbits+=bitlen; //add the code
|
|
offset+=cnt; //increment the count
|
|
bytecount-=cnt;
|
|
codetable[currentcode+1]=offset; //set the offset
|
|
nptable[currentcode]=nptable[*ptmp]; //record last current code
|
|
nptable[*ptmp]=currentcode; //record most recent code
|
|
}
|
|
else
|
|
ocd=nptable[ocd]; //reference next code
|
|
} //end of ocd while
|
|
|
|
if(!match)
|
|
{
|
|
databuf=(databuf<<bitlen)|((DWORD)cpydata[offset]); totalbits+=bitlen;
|
|
offset++;
|
|
codetable[currentcode+1]=offset; //set the offset
|
|
bytecount--;
|
|
nptable[currentcode]=nptable[*ptmp]; //record last current code
|
|
nptable[*ptmp]=currentcode; //record most recent code
|
|
}
|
|
|
|
if(currentcode>=0xffe) //send clear code
|
|
{
|
|
databuf=(databuf<<bitlen)|((DWORD)256);
|
|
totalbits+=bitlen;
|
|
bitlen=9;
|
|
currentcode=257;
|
|
for(i=0;i<4096;i++) nptable[i]=-1;
|
|
}
|
|
|
|
|
|
if(bytecount<0) GENNFERR("(SaveTiff)Bad Byte Count");
|
|
|
|
if(bytecount==0)
|
|
{
|
|
endflag=0; //endflag
|
|
while(totalbits>=8) {tbyte=(unsigned char)(databuf>>(totalbits-8))&0xff; fwrite(&tbyte,1,1,fl); totalbits-=8;}
|
|
databuf=(databuf<<bitlen)|((DWORD)257); totalbits+=bitlen; //send end code
|
|
while(totalbits>=8) {tbyte=(unsigned char)(databuf>>(totalbits-8))&0xff; fwrite(&tbyte,1,1,fl); totalbits-=8;}
|
|
tbyte=(unsigned char)databuf<<(8-totalbits);
|
|
fwrite(&tbyte,1,1,fl);
|
|
}
|
|
|
|
if(((DWORD)++currentcode)==(DWORD)1<<bitlen) bitlen++;
|
|
|
|
} //end of while
|
|
cpydata+=offset;
|
|
bpsl[strip]=(ftell(fl)-initpos)-sloc[strip];
|
|
} //end of strip
|
|
|
|
pos=ftell(fl);
|
|
for(i=0;i<nos;i++) fwrite(sloc+i,4,1,fl); // striplocations
|
|
cpos=ftell(fl);
|
|
fseek(fl,slc,SEEK_SET); // setposition
|
|
field.tag=273; field.type=4; field.lenght=nos; field.offset=pos-initpos;
|
|
fwrite(&field,12,1,fl); //write striplocation
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
|
|
if(nos>1)
|
|
{
|
|
pos=ftell(fl);
|
|
for(i=0;i<nos;i++) fwrite(sloc+i,4,1,fl); // striplocations
|
|
cpos=ftell(fl);
|
|
fseek(fl,slc,SEEK_SET); // setposition
|
|
field.tag=273; field.type=4; field.lenght=nos; field.offset=pos-initpos;
|
|
fwrite(&field,12,1,fl); //write striplocation
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
|
|
|
|
pos=ftell(fl);
|
|
for(i=0;i<nos;i++) fwrite(bpsl+i,4,1,fl); // byte per strip
|
|
cpos=ftell(fl);
|
|
fseek(fl,byps,SEEK_SET); // setposition
|
|
field.tag=279; field.type=4; field.lenght=nos; field.offset=pos-initpos;
|
|
fwrite(&field,12,1,fl); //write bytes per strip
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
}
|
|
else
|
|
{
|
|
cpos=ftell(fl);
|
|
fseek(fl,slc,SEEK_SET); // setposition
|
|
field.tag=273; field.type=4; field.lenght=nos; field.offset=sloc[0];
|
|
fwrite(&field,12,1,fl); //write striplocation
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
|
|
|
|
cpos=ftell(fl);
|
|
fseek(fl,byps,SEEK_SET); // setposition
|
|
field.tag=279; field.type=4; field.lenght=nos; field.offset=bpsl[0];
|
|
fwrite(&field,12,1,fl); //write bytes per strip
|
|
fseek(fl,cpos,SEEK_SET); // resetposition
|
|
}
|
|
|
|
|
|
if(Pitch==(xlen*(Bpp>>3))) UnLock();
|
|
else delete tmpbuf;
|
|
MaskFrom(RGBMask(0x0000ff,0x00ff00,0xff0000));
|
|
|
|
delete nptable;
|
|
delete codetable;
|
|
delete sloc;
|
|
delete bpsl;
|
|
}
|