// Jan 22  0.3 s first frame
#define giffilename "40t.gif"
int gifimagewidth=42;
int imageheight=42;
unsigned int Log2colors=4;  // 4=16 colors in global color table
float gsfy=0.7*imageheight;
float gsfx=(0.7/1.57)*gifimagewidth;

// scragif.cpp   convert "scr" file to animated looping gif file
// scr2gif.cpp  June 15, 2002
// June 14, 2002 - general starting point to make a gif file
//                 starting from a picture drawn on the screen

#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <math.h>
#include <dos.h>
#include <graphics.h>
#include <stdlib.h>
#include <process.h>
#include <time.h>

char RunCode[400],RunOkay[400],RunDice[400];char material[1000];
float diceheight[100];float dicediam[100];
int irect[100];int icirc[100];int itotal[100];int runused[100];

//-----------------------------------------------------------
void dotat(int ix1,int iy1,int icolor);
FILE *fout;
int GlobalColorTableFlag=1;  // 1=Yes 0=No
unsigned int delaytime=0; // Delay time in 100ths of a second
unsigned int disposalmethod=1;  // 1=do not dispose
unsigned int transparentcolorflag=0;
unsigned int transparentcolor=0;
unsigned int colorresolution=2;
unsigned int backgroundcolor=0; // Netscape doesn't care
void writeimagedescriptor(int imageleftposition,int imagetopposition,int gifimagewidth,int imageheight,int Log2colors);
void encodeimage(long int *Lnopix,int Log2colors);
int pushbytelist[256],pl[4096],pats[4096],fpat[4096],twoto[13];
long int ps[4096];
void pushbits(int inumb,int biqtspercode,long int *Lpushbitsnum,long int *Lpushbitsfact,int *pushbytecount,int *pushbytelist);
void endofbits(long int *Lpushbitsnum,long int *Lpushbitsfact,long int *pushbytecount,int *pushbytelist);
void pushbyte(int thebyte,int *pushbytecount,int *pushbytelist);
unsigned char getrs(long int Lip);
unsigned char ucscrcol1[30000];
unsigned char ucscrcol2[30000];
unsigned char ucscrcol3[30000];

void main(void)
{ // main                                                     main
int gdriver=VGA;
int gmode=VGAHI;
textmode(C4350);
initgraph(&gdriver,&gmode,"c:\\tc\\bgi");
cleardevice();
struct palettetype pal;
getpalette(&pal);
int i1;
/*
for (i1=0;i1<16;i1++)
{ // .
setrgbpalette(pal.colors[i1],i1*4.15,i1*4.15,i1*4.15);
} // .
setrgbpalette(pal.colors[0],63,63,48);
*/

//------------------------------------------------------------------
// Define the image:

char scrfilename[40];
FILE *scrfin;
strcpy(scrfilename,"40t.scr");
scrfin=fopen(scrfilename,"rb");
gotoxy(1,20);cout<<"Now get file..."<<scrfilename<<" ";
int countframesread=0;
int firsttimethrough=1;
ReadNextFrame:
countframesread++;
int scrwid,scrhgt,scrx0,scry0;
setcolor(8);
//..rectangle(scrx0-1,scry0-1,scrx0+scrwid,scry0+scrhgt);
unsigned char ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8,ch9,ch10,ch11,ch12,ch13;

fscanf(scrfin,"%c%c%c%c%c%c%c%c%c%c%c%c%c",&ch1,&ch2,&ch3,&ch4,&ch5,&ch6,&ch7,&ch8,&ch9,&ch10,&ch11,&ch12,&ch13);
gotoxy(44,3);cout<<"Frames read "<<countframesread<<" ";
gotoxy(44,5);cout<<"First 3: "<<ch1<<ch2<<ch3<<" ";
if ((ch1!='s')||(ch2!='c')||(ch3!='r'))
{
fprintf(fout,"%c",0x3b); // 0x3b // Trailer   (byte at end of GIF file)
fclose(scrfin);
fclose(fout);
//---------------------------------------------------------------
gotoxy(1,25); cout << "Time: "<<clock()/CLK_TCK<<" s  Press any key...";
getch();
//closegraph();
return;
}
//if (ch2!='c') goto ALLDONE;
//if (ch3!='r') goto ALLDONE;
scrwid=ch5; scrwid=scrwid+256*ch4;
scrhgt=ch7; scrhgt=scrhgt+256*ch6;
//scrwid=scrwid+256;
//scrhgt=scrhgt+256;
gotoxy(40,6);cout<<"wid = "<<scrwid<<" ";
gotoxy(40,7);cout<<"height = "<<scrhgt<<" ";
gifimagewidth=scrwid;
imageheight=scrhgt;

int ipixcol,ix,iy;
for (iy=0;iy<scrhgt;iy++)
{ // iy
for (ix=0;ix<scrwid;ix++)
{ //
char ch1;
fscanf(scrfin,"%c",&ch1);
ipixcol=ch1-'A';
putpixel(ix,iy,ipixcol);
} //
fscanf(scrfin,"%c%c",&ch2,&ch3);
} // iy



//setcolor(15);
//settextstyle(2,0,6);
//outtextxy(35,-3,"Cylindrical dice landing");
//outtextxy(35,15,"on 15.50 mm glass table");

//int bx0=0.20*gifimagewidth,by0=0.85*;

//setcolor(15);
//settextstyle(2,0,6);
//outtextxy(43,251,"arctan(height/diameter)");




//------------------------------------------------------------------
// Draw lines to show image borders:
setcolor(8);line(gifimagewidth,0,gifimagewidth,imageheight);
line(0,imageheight,gifimagewidth,imageheight);
setcolor(7);line(gifimagewidth+1,0,gifimagewidth+1,imageheight);
line(0,imageheight+1,gifimagewidth,imageheight+1);
setcolor(15);line(gifimagewidth+2,0,gifimagewidth+2,imageheight);
line(0,imageheight+2,gifimagewidth,imageheight+2);
//gotoxy(60,22);cout<<"Do you want to ";
//gotoxy(60,23);cout<<"make a "<<gifimagewidth<<"x"<<imageheight<<" ";
//gotoxy(60,24);cout<<"gif file? (y/n)";
//gotoxy(60,25);cout<<"File: "<<giffilename<<" ";
//if (getch()!='y')
//{
//closegraph();
//return;
//}
//------------------------------------------------------------------
long int li5,li6,li7,li8;
for (li5=0;li5<30000;li5++)
{
li8=gifimagewidth;li6=li5%li8;li7=li5/li8;
ucscrcol1[li5]=getpixel(li6,li7);
}
for (li5=30000;li5<60000;li5++)
{
li8=gifimagewidth;li6=li5%li8;li7=li5/li8;
ucscrcol2[li5-30000]=getpixel(li6,li7);
}
for (li5=60000;li5<90000;li5++)
{
li8=gifimagewidth;li6=li5%li8;li7=li5/li8;
ucscrcol3[li5-60000]=getpixel(li6,li7);
}
twoto[0]=1;twoto[1]=2;twoto[2]=4;twoto[3]=8;twoto[4]=16;twoto[5]=32;
twoto[6]=64;twoto[7]=128;twoto[8]=256;twoto[9]=512;twoto[10]=1024;
twoto[11]=2048;twoto[12]=4096;
// User-chosen parameters for the GIF:
if (firsttimethrough==1)
{ // firsttimethrough==1)
fout=fopen(giffilename,"wb");
int LogicalScreenWidth=gifimagewidth;
int LogicalScreenHeight=imageheight;
// Header
fprintf(fout,"%c%c%c%c%c%c",'G','I','F','8','9','a');
// Logical Screen Descriptor
int i2,i3;
unsigned char c2;
i2=LogicalScreenWidth/256;c2=i2;i3=LogicalScreenWidth%256;
fprintf(fout,"%c%c",i3,c2);
i2=LogicalScreenHeight/256;c2=i2;i3=LogicalScreenHeight%256;
fprintf(fout,"%c%c",i3,c2);
unsigned int packedfield;
packedfield=0;
packedfield += 128*GlobalColorTableFlag;
packedfield += 16*colorresolution;  // color resolution  (bits per color)
packedfield += 8*0; // sortflag is 0 (most common choice)
packedfield += 1*(Log2colors-1);
fprintf(fout,"%c",packedfield);
fprintf(fout,"%c",backgroundcolor); // background color index (pixels on screen
		      // not in image(s) are given this color
fprintf(fout,"%c",0); // pixel aspect ratio=0=no information given

if ((GlobalColorTableFlag)&&((Log2colors-1)==3))
{ // have global color table
/*
//fprintf(fout,"%c%c%c",0,0,0);        // 0=black
fprintf(fout,"%c%c%c",255,255,190);  // 0 = "#ffffc0" light yellow
fprintf(fout,"%c%c%c",0,0,128);      // 1=dark blue
fprintf(fout,"%c%c%c",0,128,0);      // 2=dark green
fprintf(fout,"%c%c%c",0,128,128);    // 3= dark turquoise
fprintf(fout,"%c%c%c",128,  0,0);    // 4 dark red
fprintf(fout,"%c%c%c",128,  0,128);  // 5 yellow
fprintf(fout,"%c%c%c",128,128,  0);  // 6 dark yellow
//fprintf(fout,"%c%c%c",150,150,150);  // 7= light gray
fprintf(fout,"%c%c%c",  0,  0,  0);  // 7= black !!!
fprintf(fout,"%c%c%c",128,128,128);  // 8= dark gray
fprintf(fout,"%c%c%c",  0,  0,255);  // 9=blue
fprintf(fout,"%c%c%c",  0,255,  0);  // 10=green
fprintf(fout,"%c%c%c",  0,255,255);  // 11=turquoise
fprintf(fout,"%c%c%c",255,0  ,0  );  // 12=red
fprintf(fout,"%c%c%c",255,  0,255);  // 13=purple
fprintf(fout,"%c%c%c",255,255,  0);  // 14=yellow
fprintf(fout,"%c%c%c",255,255,255);  // 15=white
*/
fprintf(fout,"%c%c%c",255,255,192);        // light yellow
fprintf(fout,"%c%c%c",17,17,17);      // 2=dark blue
fprintf(fout,"%c%c%c",34,34,34);      // 2=dark green
fprintf(fout,"%c%c%c",51,51,51);    // 3= dark turquoise
fprintf(fout,"%c%c%c",68 , 68,68);    // 4 dark red
fprintf(fout,"%c%c%c",85 , 85, 85);  // 5 yellow
fprintf(fout,"%c%c%c",102,102,102);  // 6 dark yellow
fprintf(fout,"%c%c%c",119,119,119);  // 7= light gray
fprintf(fout,"%c%c%c",136,136,136);  // 8= dark gray
fprintf(fout,"%c%c%c",153,153,153);  // 9=blue
fprintf(fout,"%c%c%c",170,170,170);  // 10=green
fprintf(fout,"%c%c%c",187,187,187);  // 11=turquoise
fprintf(fout,"%c%c%c",204,204,204);  // 12=red
fprintf(fout,"%c%c%c",221,221,221);  // 13=purple
fprintf(fout,"%c%c%c",238,238,238);  // 14=yellow
fprintf(fout,"%c%c%c",255,255,255);  // 15=white

} // have global color table

 // LOOP command  -   (Application Extension)
fprintf(fout,"%c",0x21); // extension introducer=0x21=33 decimal
fprintf(fout,"%c",0xff); // Application extension label=0xff
fprintf(fout,"%c",11); // block size: must be 11
fprintf(fout,"%c%c%c%c%c%c%c%c%c%c%c",
 'N','E','T','S','C','A','P','E','2','.','0');
fprintf(fout,"%c%c%c%c",3,1,0,0); // This makes it loop forever.
fprintf(fout,"%c",0); // block terminator

} // firsttimethrough

 // CONTROL - Graphic Control Extension
fprintf(fout,"%c",0x21); // extension introducer=0x21=33 decimal
fprintf(fout,"%c",0xf9); // graphic control extension label=0xf9
fprintf(fout,"%c",4); // block length: must be 4
//fpntf(fout,"%c",4*disposalmethod+transparentcolorflag); // packed field
fprintf(fout,"%c",0); // packed field
// // Lowest bit:   transparentcolorflag  (1=yes or 0=no)
int delaytime=10;
if (firsttimethrough==1) delaytime=30;
fprintf(fout,"%c%c",delaytime%256,delaytime/256);
fprintf(fout,"%c",0); // Only used if above flag is 1.
fprintf(fout,"%c",0); // Block terminator

long int Lnopix,Li1,Li2;
Li1 = gifimagewidth;Li2 = imageheight;Lnopix=Li1*Li2;
writeimagedescriptor(0,0,gifimagewidth,imageheight,Log2colors);

firsttimethrough=0;
if (!kbhit()) goto ReadNextFrame;
getch();
fclose(scrfin);
return;

} // main                                                     main

//-----------------------------------------------------------------
void pushbits(int inumb,int bitspercode,long int *Lpushbitsnum,
	      long int *Lpushbitsfact,int *pushbytecount,int *pushbytelist)
{ // pushbits					          pushbits
// Note:  May 28, 1998:  Leave in this error check.  Doesn't take long.
if (inumb<0) {cout<<"In pushbits, inumb = "<<inumb;getch();exit(0);}
if (inumb>=twoto[bitspercode])
 {cout<<"! In pushbits, inumb too big = "<<inumb<<" bitspercode="<<bitspercode<<" !";getch();exit(0);}
int thebyte;
(*Lpushbitsnum)=(*Lpushbitsnum)+inumb*(*Lpushbitsfact);
(*Lpushbitsfact)=(*Lpushbitsfact)*twoto[bitspercode];
if ((*Lpushbitsfact)>=256)
{ //
(*Lpushbitsfact)=(*Lpushbitsfact)/256;
thebyte=(*Lpushbitsnum)&255;
(*Lpushbitsnum)=(*Lpushbitsnum)/256;
pushbyte(thebyte,pushbytecount,pushbytelist);
} //
if ((*Lpushbitsfact)>=256)
{ //
(*Lpushbitsfact)=(*Lpushbitsfact)/256;
thebyte=(*Lpushbitsnum)&255;
(*Lpushbitsnum)=(*Lpushbitsnum)/256;
pushbyte(thebyte,pushbytecount,pushbytelist);
} //
return;
} // pushbits					          pushbits

void endofbits(long int *Lpushbitsnum,long int *Lpushbitsfact,
	       int *pushbytecount,int *pushbytelist)
{ // endofbits                                           endofbits
int thebyte;
if ((*Lpushbitsfact)>1)
{ //
thebyte=(*Lpushbitsnum)&255;
pushbyte(thebyte,pushbytecount,pushbytelist);
} //
if ((*pushbytecount)>0)
{ // any data remaining?
if ((*pushbytecount)>255) {cout<<"error:pushbytecount>255";getch();return;}
fprintf(fout,"%c",(*pushbytecount)); //Length of block
int i1;
for (i1=0;i1<(*pushbytecount);i1++)
{ // i1
fprintf(fout,"%c",*(pushbytelist+i1)); //Length of block
} // i1
} // any data remaining?
fprintf(fout,"%c",0); //block terminator (marks end of image data)
return;
} // endofbits                                           endofbits

void pushbyte(int thebyte,int *pushbytecount,int *pushbytelist)
{ // pushbyte                                             pushbyte
*(pushbytelist+(*pushbytecount))=thebyte;
(*pushbytecount)=(*pushbytecount)+1;
if ((*pushbytecount)>250)
{ // enough for a block
fprintf(fout,"%c",(*pushbytecount)); //Length of block
int i1;
for (i1=0;i1<(*pushbytecount);i1++)
{ // i1
fprintf(fout,"%c",*(pushbytelist+i1)); //Length of block
} // i1
(*pushbytecount)=0;
} // enough for a block
return;
} // pushbyte                                             pushbyte

void encodeimage(long int *Lnopix,int Log2colors)
{ // encodeimage                                       encodeimage
// Note: - perhaps two colors only wouldn't work.
long int onepercent=0.01*(*Lnopix),nextpercent=0;
long int Lpushbitsfact=1;
long int Lpushbitsnum=0;
int pushbytecount=0;
int ClearCode; ClearCode=twoto[Log2colors];
int dataendcode; dataendcode=twoto[Log2colors]+1;
int bitspercode; // (varies as image is drawn)
bitspercode=Log2colors+1;
int iPatt,PattLen,PattSeen;
int imatches;
long int ipix;
long int ipip; // pixel in pattern
int NewPattFlag;
int nextcodetouse;

// list of pattern numbers  (numbered 0 to 4095)
int patrootmodulus = 4096;
{ // local: initialize
for (int i=0;i<patrootmodulus;i++)
fpat[i]=-1;
} // local: initialize

nextcodetouse =twoto[Log2colors]+2;
// Initialize the pattern table and pattern lengths;
pushbits(ClearCode,bitspercode,&Lpushbitsnum,&Lpushbitsfact,
	 &pushbytecount,pushbytelist); // Always begin with a clear code.
ipix=0;
NextPixel:
PattLen=0;PattSeen=-1;
// Display progress in encoding the gif:
if (ipix>nextpercent)  // This takes negligible time.
{ //
float r1=(onepercent);
float r2=ipix;
int i5=r2/r1;
gotoxy(65,19);cout<<i5<<"% ";
//putpixel(638,2.0*30+2.0*ipix/125.0,15);
//putpixel(639,2.0*30+2.0*ipix/125.0,14);
nextpercent=nextpercent+onepercent;
} //
int patroot;// pattern root - could be based on up to 2 pixels - not more
{//
long int Li1,Li2,Li3,Li4;
Li1 = getrs(ipix);
Li2 = 0;
if (ipix+1<(*Lnopix)) Li2=getrs(ipix+1);
Li3 = twoto[Log2colors];
Li4 = Li1 + Li3*Li2;
patroot=Li4%patrootmodulus;
} //

iPatt = fpat[patroot];
int lastpat,PattSeenPrev;

NextPatt:

if (iPatt==-1) goto SeenAllPatt;

if (ipix+pl[iPatt]>(*Lnopix)) goto ChooseNextPatt;
for (ipip=0;ipip<pl[iPatt];ipip++)
{ // ipip
if (getrs(ipix+ipip)!=getrs(ps[iPatt]+ipip)) goto ChooseNextPatt;
} // ipip
if (pl[iPatt]>PattLen){PattLen=pl[iPatt];PattSeen=iPatt;}

ChooseNextPatt:
lastpat = iPatt;
iPatt = pats[iPatt];
goto NextPatt;


SeenAllPatt:

if ((PattSeen<0)||(PattSeen>=nextcodetouse))
{ //
PattSeen=getrs(ipix);PattLen=1;
} //
NewPattFlag=0;
if ((ipix+PattLen+1<=(*Lnopix))&&(nextcodetouse<=4095))
{ // room for new code
NewPattFlag=1;ps[nextcodetouse]=ipix;pl[nextcodetouse]=PattLen+1;
if (fpat[patroot]==-1)
  fpat[patroot]=nextcodetouse;
else
  pats[lastpat]=nextcodetouse;
pats[nextcodetouse]=-1;

} // room for new code
pushbits(PattSeen,bitspercode,&Lpushbitsnum,&Lpushbitsfact,
	 &pushbytecount,pushbytelist); ipix+=PattLen;

// Must send the code first before changing bitspercode!
if (NewPattFlag)
{ // NewPattFlag
if (nextcodetouse==twoto[bitspercode]) bitspercode++;
nextcodetouse++;

if (nextcodetouse==4096)
{ // put in clear code - to avoid problem with Netscape
gotoxy(21,25); cout << "Put in clear code at t="<<clock()/CLK_TCK<<" ";
pushbits(ClearCode,bitspercode,&Lpushbitsnum,&Lpushbitsfact,
	 &pushbytecount,pushbytelist);
bitspercode=Log2colors+1;
nextcodetouse =twoto[Log2colors]+2;
{ // local: initialize
for (int i=0;i<patrootmodulus;i++)
fpat[i]=-1;
} // local: initialize
} // put in clear code

} // NewPattFlag

if (ipix<(*Lnopix)) goto NextPixel;

pushbits(dataendcode,bitspercode,&Lpushbitsnum,&Lpushbitsfact,
	 &pushbytecount,pushbytelist);
// Following required to terminate the image data
endofbits(&Lpushbitsnum,&Lpushbitsfact,&pushbytecount,pushbytelist);
return;
} // encodeimage                                       encodeimage

void writeimagedescriptor(int imageleftposition,int imagetopposition,
			  int gifimagewidth,int imageheight,int Log2colors)
{ // writeimagedescriptor                     writeimagedescriptor
long int Lnopix,Li1,Li2;
Li1=gifimagewidth;Li2=imageheight;Lnopix=Li1*Li2;
int localcolortableflag=0; // Must be zero in this version.
int interlaceflag=0;  // Must be zero in this version.
int localsortflag=0;
int sizeoflocalcolortable=Log2colors;
// Image Descriptor
fprintf(fout,"%c",0x2c); // Image separator  0x2c
fprintf(fout,"%c%c",imageleftposition%256,imageleftposition/256);
fprintf(fout,"%c%c",imagetopposition%256,imagetopposition/256);
fprintf(fout,"%c%c",gifimagewidth%256,gifimagewidth/256);
fprintf(fout,"%c%c",imageheight%256,imageheight/256);
fprintf(fout,"%c",128*localcolortableflag+64*interlaceflag+
		  32*localsortflag+sizeoflocalcolortable);
if (localcolortableflag)
{ // local color table
cout << "No way to put in local color table.  Turn off flag!"; return;
} // local color table
fprintf(fout,"%c",Log2colors);
encodeimage(&Lnopix,Log2colors);
return;
} // writeimagedescriptor                     writeimagedescriptor

unsigned char getrs(long int Lip)
{ // getrs                                                   getrs
unsigned char ui1;long int lix,liy,L2;
if (Lip<30000)
{ //
ui1=ucscrcol1[Lip];
} //
else if (Lip<60000)
{
ui1=ucscrcol2[Lip-30000];
}
else if (Lip<90000)
{
ui1=ucscrcol3[Lip-60000];
}
else
{
L2=gifimagewidth;liy=Lip/L2;lix=Lip%L2;ui1=getpixel(lix,liy);
}
return ui1;
} // getrs                                                   getrs
