#include"image.h"
#include<string.h>

void Image::SaveGif(char *str)
{
FILE *fl=fopen(str,"wb"); 

if(!fl) 
{
char tfn[200];
strcpy(tfn,"Cannont open GIF file for writeing:");
strcat(tfn,str);
 GENNFERR(tfn);
}

SaveGif(fl);
fclose(fl);
strcpy(fname,str);
}

int Image::IsGif(FILE *fl)
{
unsigned short int tmps;
if(!fl)  GENNFERR("Invalid File");

int fpos=ftell(fl);

char tstr[4];

				//look for a giff;
fread(&tstr,3,1,fl);    // read data type
tstr[3]=0;
if(!strcmp(tstr,"GIF"))
 {
 fread(&tmps,2,1,fl);    // read data type
 fseek(fl,fpos,SEEK_SET);
 return 1;
 }
fseek(fl,fpos,SEEK_SET);

return 0;
}

void Image::LoadGif(char *str)
{
FILE *fl=fopen(str,"rb"); 

if(!fl) 
{
char tfn[MAX_PATH*2];
strcpy(tfn,"Cannont open GIF file for reading:");
strcat(tfn,str);
 GENNFERR(tfn);
}

LoadGif(fl);
fclose(fl);
strcpy(fname,str);
}

void Image::LoadGif(FILE *fl)
{
int i,bcnt,bits=9,fg=1,etb=0;
unsigned int li,nb,code=258,eta=0,ofs=0,imax;
unsigned int *oss;
oss=new unsigned int[8200];
for(i=0;i<=12;i++) getc(fl);   // get header 
int ix,iy;

AllocPal();
for(i=0;i<256;i++)				//fill pallette
 {
 pal[i].r=getc(fl);
 pal[i].g=getc(fl);
 pal[i].b=getc(fl);
 }


for(i=0;i<5;i++) getc(fl);   // get secondary header 
ix=getc(fl);
ix+=getc(fl)<<8;
iy=getc(fl);
iy+=getc(fl)<<8;
int iflag;
iflag=getc(fl);
iflag&=0x40;	 //interlace flag

getc(fl);   // get secondary header 

imax=ix*iy;
vxlen=xlen=ix; vylen=ylen=iy;
itype=ITYPE_INDEXED;
Bpp=8;

IAlloc();
RealizePalette();
BYTE *dest=Lock();

bcnt=getc(fl);

while(fg)
 {
  while(etb<bits)       //get data from file
  {
  if (!bcnt) bcnt=getc(fl);
  eta=(unsigned int)(((unsigned long)getc(fl))<<etb)+eta;
  etb+=8;
  bcnt--;
  }
 nb=eta&((1<<bits)-1);
 eta>>=bits;
 etb-=bits;

if (nb==257) fg=0; else           // end code 
if (nb==256) {code=257; bits=9;}   // clear code 
else
 if (nb<=255)
 {*(dest+ofs)=(char)nb; *(oss+code-258)=ofs; ofs++; *(oss+code-257)=ofs;}
 else
 {
  if (nb>code)  GENNFERR("Gif Decompression Error");
  *(oss+code-258)=ofs;
  for(li=*(oss+nb-258);li<=*(oss+nb-257) && ofs<(unsigned int)imax;li++)
  {
  *(dest+ofs)=*(dest+li);
  ofs++;
  }
  *(oss+code-257)=ofs;

 }

if(code==(unsigned int)1<<bits && bits<12) bits++;
code++;
if (ofs>=imax) fg=0;
}

delete oss;
UnLock();
CorrectPitch();
if(iflag) DeInterlace();
}  //end of degif

void Image::SaveGif(FILE *fl)
{
char sig[]="GIF87a";
int bytes=0,i,j,hc,pc,code=0,dto=0;
WORD x=(WORD)xlen,y=(WORD)ylen,tz=0;
int pos,opos,opd=0,shft=9,dtsz=x*y,byc=0,bits=0;

int *cdl=new int[8200*4];
BYTE *dat,*tmpbuf;
tmpbuf=NULL;
pos=0;

if(Pitch==xlen*(Bpp>>3)) dat=Lock();
 else DePitch(dat=tmpbuf=new BYTE[xlen*ylen*(Bpp>>3)]);

for(i=0;i<6;i++) putc(sig[i],fl);
fwrite(&x,1,2,fl);
fwrite(&y,1,2,fl);
putc(0xf7,fl);
putc(0,fl);
putc(0,fl);

for(i=0;i<256;i++) 
{
putc(pal[i].r,fl);
putc(pal[i].g,fl);
putc(pal[i].b,fl);
}


putc(',',fl);
fwrite(&tz,1,2,fl);
fwrite(&tz,1,2,fl);
fwrite(&x,1,2,fl);
fwrite(&y,1,2,fl);
putc(0,fl);
putc(8,fl);


cdl[1]=0;
cdl[2]=1;

putc(0xff,fl); //put byte count
byc=0xff;
opd=256;
bits=9;
pc=dat[0]; 
dto++;

while(dto<=dtsz)
{
code++;
if((code+256)==1<<shft)  shft++;
if((code+256)==4095) 
 { 
 opd=opd+(pc<<bits); bits+=12;
 opd=opd+(256<<bits); bits+=12;
 shft=9; code=0;
 }  //clear code
 else {opd=opd+(pc<<bits); bits+=shft;}
cdl[code]=dto;


while(bits>=8) 
 { bytes++; 
  putc(opd&0xff,fl); 
  byc--; 
  if(byc==0) { pos=ftell(fl); byc=255; putc(255,fl); bytes++; }
  opd>>=8; 
  bits-=8;
 }

hc=0;
for(i=code-1;i>0;i--)
 {
for(j=cdl[i];j<(cdl[i+1]+1) && dat[j]==dat[dto+(j-cdl[i])];j++);
if(j==(cdl[i+1]+1) ) { hc=i+258; break; }
 } //end of for i;
 if(hc) {pc=hc; dto+=(cdl[i+1]+1)-cdl[i];} else { pc=dat[dto]; dto++;}

} //end of while dto size

opd=opd+(pc<<bits); bits+=shft;
opd=opd+(1<<bits)*257; bits+=shft; 
while(bits>0) {byc--; bytes++; putc(opd&0xff,fl); opd/=256; bits-=8;}

putc(0,fl); bytes++;
opos=ftell(fl);
fseek(fl,pos,SEEK_SET); putc(255-byc,fl);
fseek(fl,opos,SEEK_SET);

if(Pitch==(xlen*(Bpp>>3))) UnLock();
 else delete tmpbuf;

delete cdl;
}
