/* w1glgif.c   capture pixels and write w1glgif.gif */

#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>

static void write_gif_file(char filename[]);
static void write_gif_data(unsigned char datablk[], unsigned char *byte_count,
                           int * nbit, FILE * FpGif);
int frame_xmax = 199;
int frame_xmin = 1;
int frame_ymax = 124;
int frame_ymin = 1;
int background = 255;

/* just w1gl.c pasted in here to put some bits on the screen */

void display(void)
{
  char text[]="Click here to exit";
  char *p;
  
  /* clear window */
  glClear(GL_COLOR_BUFFER_BIT); 
  glLoadIdentity ();
  
  /* draw rectangle */
  glBegin(GL_LINE_LOOP);
    glVertex2f(-0.75,  0.0);
    glVertex2f(-0.75, -0.5);
    glVertex2f( 0.75, -0.5);
    glVertex2f( 0.75,  0.0);
  glEnd();
  
  /* draw text */
  glEnable(GL_LINE_SMOOTH);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_BLEND);
  glTranslatef(-0.8, 0.5, 0.0);
  glScalef(0.0015, 0.0015, 0.0);
  for(p=text; *p; p++)
    glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);

  glFlush(); 
}

/* This routine handels mouse events */
static void mouse(int button, int state, int x, int y)
{
  /* We are only interested in left clicks */
  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
  {
    write_gif_file("w1glgif.gif"); /* added to write .gif file */
    exit(0);
  }
}

void init()
{
  /* set clear color to white */
  glClearColor (1.0, 1.0, 1.0, 0.0);
  /* set fill  color to black */
  glColor3f(0.0, 0.0, 0.0);

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
  glMatrixMode (GL_MODELVIEW);
}

int main(int argc, char* argv[])
{
  glutInit(&argc,argv);
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);  
  glutInitWindowSize(200,125);
  glutInitWindowPosition(0,0); 
  
  glutCreateWindow(argv[0]); 
  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  init();
  glutMainLoop();
  return 0;
} /* end old w1gl.c */


static void write_gif_file(char filename[])
{
  /* frame_xmin, ... needed first */
  FILE * FpGif;
  int i, j, this_bit;
  GLubyte pixel[3]; /* just RGB */
  unsigned char byte_count;
  unsigned char datablk[1280]; /* [257] */
  int nbit;
  int dbit, jbit;
  int dbyte;
  int ncode = 3; /* smallest for 1 bit */
  int width, height;   /* from frame */
  int xoffs, yoffs;    /* from frame */
  unsigned char head[13]={ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61,
                           0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00};
                         /* head[6]=low width,  head[7]=high width,
                            head[8]=low height, head[9]=high height */
  unsigned char coltab[6]= {0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF};
  unsigned char imgblk[11]= {0x2C, 0x00, 0x00, 0x00, 0x00, 
                             0x00, 0x00, 0x00, 0x00,
                             0x00, 0x02};
                       /* imgblk[5]=low width,  imgblk[6]=high width,
                          imgblk[7]=low height, imgblk[8]=high height */


  printf("gif_out stating to write %s \n", filename);
  FpGif=fopen(filename,"wb");
  if(FpGif==NULL)
  {
    printf("could not open %s for write\n", filename);
    return;
  }
  width =  frame_xmax-frame_xmin-1; /* omit frame line */
  height = frame_ymax-frame_ymin-1;

  head[6]=width&0xFF;
  head[7]=width>>8;
  head[8]=height&0xFF;
  head[9]=height>>8;
  for(i=0; i<13; i++) putc(head[i], FpGif); /* header */
  for(i=0; i<6; i++) putc(coltab[i], FpGif); /* color table */
  imgblk[5]=width&0xFF;
  imgblk[6]=width>>8;
  imgblk[7]=height&0xFF;
  imgblk[8]=height>>8;
  for(i=0; i<11; i++) putc(imgblk[i], FpGif); /* image desc */
  /* read pixels and do non LZW encode */
  /* pack bits in datablk */
  for(i=0; i<1280; i++)datablk[i]=0;  /* zero image data */
  nbit = 0;

  for(i=frame_ymax-frame_ymin-1; i>0; i--) /* Image rightside up  */
  {
    for(j=0; j<frame_xmax-frame_xmin-1; j++)
    {
      glReadPixels( j, i, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
      printf("pixel[%d][%d]=%d %d %d \n", i, j, pixel[0], pixel[1], pixel[2]);
      this_bit = 0;
      if(pixel[0]==background && pixel[1]==background &&
         pixel[2]==background) this_bit = 1; /* reverse image */

      dbit = 0x04;          /* Q&D reset code */
      dbyte = nbit/8;       /* byte index */
      jbit  = nbit-dbyte*8; /* bit index in byte */
      datablk[dbyte] = (datablk[dbyte]+(dbit<<jbit))&0xFF;
      if(jbit+ncode>7) datablk[dbyte+1] = dbit>>(8-jbit);
      nbit = nbit + ncode;

      dbit = this_bit;      /* index into color table to write out */
      dbyte = nbit/8;       /* byte index */
      jbit  = nbit-dbyte*8; /* bit index in byte */
      datablk[dbyte] = (datablk[dbyte]+(dbit<<jbit))&0xFF;
      if(jbit+ncode>7) datablk[dbyte+1] = dbit>>(8-jbit);
      nbit = nbit + ncode;
      byte_count = nbit/8;
      if(byte_count >=253)
                   write_gif_data(datablk, &byte_count, &nbit, FpGif);
    } /* end j loop */
  } /* end i loop */
  dbit = 0x05;          /* end code */
  dbyte = nbit/8;       /* byte index */
  jbit  = nbit-dbyte*8; /* bit index in byte */
  datablk[dbyte] = (datablk[dbyte]+(dbit<<jbit))&0xFF;
  if(jbit+ncode>7) datablk[dbyte+1] = dbit>>(8-jbit);
  nbit = nbit + ncode;
  byte_count = (nbit+7)/8;
  write_gif_data(datablk, &byte_count, &nbit, FpGif);
  putc(0x00, FpGif); /* byte count of zero, indicating last data */
  putc(0x3b, FpGif); /* file terminator */
  fclose(FpGif);
} /* end write_gif_file */

static void write_gif_data(unsigned char datablk[], unsigned char *byte_count,
                           int * nbit, FILE * FpGif)
{
  int j;
  /* write byte count of 254 or less, doing a data block */
  putc(*byte_count, FpGif); /* image data byte count */

  /* write packed bits as bytes */
  for(j=0; j<(*byte_count); j++)
  {
    putc(datablk[j], FpGif); /* image data */
  }
  datablk[0] = datablk[*byte_count];
  for(j=1; j<1280; j++)datablk[j]=0;  /* zero image data */
  *nbit = (*nbit)-(*byte_count)*8;
  *byte_count = 0;
} /* end write_gif_data */

/* end w1glgif.c */

