
char *snapfmt = "album/%02d.%04d%s.ppm.gz";

/* Antialiasing: shrink two RGB pixel rows of 'wide' pixels
 * into a single row of 'wide/2'.
 */
void shrink2(char *rows, int wide, int rowbytes)
{
  register unsigned char *p;
  unsigned char *q;
  register int roff;
  int v;
  int k;

  q = (unsigned char *)rows;	/* We can do this in place, left-to-right */
  p = (unsigned char *)rows;
  k = wide/2;
  do {
    q[0] = (p[0] + p[3] + p[rowbytes] + p[rowbytes+3]) >> 2;
    q[1] = (p[1] + p[3+1] + p[rowbytes+1] + p[rowbytes+3+1]) >> 2;
    q[2] = (p[2] + p[3+2] + p[rowbytes+2] + p[rowbytes+3+2]) >> 2;
    q += 3;
    p += 3*2;
  } while(--k > 0);
}

int
snapshot(char *sub)
{
  char fname[256];
  char *fnamep = fname;
  char header[500];
  struct viewport { GLint x, y, w, h; } vp;
  int i, rowlen;
  int step = (zoom2==1) ? 2 : 1;
  int owide, ohigh, junk;
  char *img;
#ifdef ZLIB
  gzFile out;
#else
  FILE *outf;
#endif

  mkdir("album", 0777);
  if(snapno < 0) {
    for(snapno = 0; ; snapno += 10000) {
	sprintf(fname, snapfmt, snapno/10000, 0, "");
	/* If neither NN.0000.ppm.gz nor NN.0000.00.00.ppm.gz exist, use it. */
	if(access(fname, 0) < 0) {
	    sprintf(fname, snapfmt, snapno/10000, 0, sub);
	    if(access(fname, 0) < 0)
		break;
	}
    }
  }

#ifdef ZLIB
  sprintf(fname, snapfmt, snapno/10000, snapno%10000, sub);
  out = gzopen(fname, "wb");
  if(out == NULL) {
    fprintf(stderr, "can't write to %s: ", fname);
    perror("");
    return -1;
  }
#else /* no ZLIB, pipe to gzip */
  strcpy(fname, "gzip >");
  fnamep = fname + strlen(fname);
  sprintf(fnamep, snapfmt, snapno/10000, snapno%10000, sub);
  outf = popen(fname, "w");
  if(outf == NULL) {
    fprintf(stderr, "can't spawn gzip to write to %s: ", fnamep);
    perror("");
    return -1;
  }
#endif

  glGetIntegerv(GL_VIEWPORT, (GLint *)&vp);
  rowlen = (vp.w*3 + 4-1) & ~3;
  img = (char *)alloca(vp.h * rowlen);
  glReadPixels(0, 0,  vp.w, vp.h, GL_RGB, GL_UNSIGNED_BYTE, img);

  owide = vp.w/step;
  ohigh = vp.h/step;
  sprintf(header, "P6\n%d %d # Tope %d of %d in %.450s",
	owide, ohigh, topeof(realtope, &junk), ntopes, filename);
  i = strlen(header);
  while((i&7) != 2) header[i++] = ' ';
  strcpy(header+i, "\n255\n");

#ifdef ZLIB
  gzwrite(out, header, strlen(header));
  for(i = vp.h; (i -= step) >= 0; ) {
    char *row = img + i*rowlen;
    if(zoom2==1) shrink2(row, vp.w, rowlen);
    if(gzwrite(out, row, owide*3) != owide*3) {
	fprintf(stderr, "Error writing row %d of %s\n", vp.h - i, fname);
	break;
    }
  }
  if(gzclose(out) != Z_OK && i < 0) {
    fprintf(stderr, "Error closing %s\n", fname);
    return -1;
  }
#else /* no ZLIB, using external gzip */
  fwrite(header, strlen(header), 1, outf);
  for(i = vp.h; --i >= 0; ) {
    char *row = img + i*rowlen;
    if(zoom2==1) shrink2(row, vp.w, rowlen);
    if(fwrite(row, owide*3, 1, outf) != 1) {
	fprintf(stderr, "Error writing row %d of %s\n", vp.h - i, fnamep);
	break;
    }
  }
  if(pclose(outf) && i < 0) {
    fprintf(stderr, "Error closing %s\n", fnamep);
    return -1;
  }
#endif
  if(i < 0) {
    printf("%s\n", fnamep);
    return 0;
  }
  return -1;
}


