Files
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

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