/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */
#ifdef PLX
#include "xpointer.h"
#ifdef DITHERCONTROL
#include "VidDither.h"
#endif
#include<stdio.h>
#include<strings.h>
#include<math.h>

#define SOURCE_PIXELS 640*482
#define DEST_PIXELS 150*113
#define source_wd 640
#define source_ht 482

extern Display *dpy;
extern Window livevideo;
extern int screen;
static XImage *ximage = NULL;

/***********************************************************************/

do_grab(event)
     XEvent event;
{
  XImage *get_a_still();
  static lasttime = 0;
  extern char save_filename[];
  extern Window save_query_win;
  extern Pixmap grab_pix;
  Window root_return, child_return;
  int root_x_return, root_y_return, win_x_return, win_y_return;
  unsigned int mask_return;

  if ((unsigned long)event.xbutton.time - (unsigned long)lasttime > 1000) {
    lasttime = event.xbutton.time;
    return;
  }

  if (ximage) {
    XDestroyImage(ximage);
    ximage = NULL;
  }

  ximage = get_a_still(grab_pix);
#ifndef SYSV
  getwd(save_filename);
#else SYSV
  getcwd(save_filename, 60);
#endif SYSV
  strcat(save_filename,"/");
  XQueryPointer(dpy, DefaultRootWindow(dpy), &root_return, &child_return,
		&root_x_return, &root_y_return, &win_x_return,
		&win_y_return, &mask_return);
  XMoveWindow(dpy, save_query_win, win_x_return - 250, win_y_return - 42);
  XMapWindow(dpy, save_query_win);
  XRaiseWindow(dpy, save_query_win);
  return;
}

cancel_save(event)
     XEvent event;
{
  extern Window save_query_win;
  if (ximage) {
    XDestroyImage(ximage);
    ximage = NULL;
  }
  XUnmapWindow(dpy, save_query_win);
  return;
}

save_image(event)
     XEvent event;
{
  extern int child_running;
  unsigned char *R,*G,*B;
#ifndef SYSV
  char *cur_point;
#endif SYSV
  FILE  *writebuf, *fopen();
  int i, x, y, forkval = 0;
  char *tempbuf;
  extern Window save_query_win;
  extern char save_filename[];
  extern int child_pids[];
  extern char child_strings[10][100];  /* messy, huh? */

  forkval = fork();
  if (forkval > 0) {
    if (ximage) {
      XDestroyImage(ximage);
      ximage = NULL;
    }
    for (i = 0; i < 10; i++) {
      if (child_pids[i] == -1) {
	child_pids[i] = forkval;
	sprintf(child_strings[i],"Done saving %s",save_filename);
	break;
      }
    }
#ifndef SYSV
    cur_point = rindex(save_filename,'/');
    *cur_point = '\0';
    chdir(save_filename);
#endif SYSV
    XUnmapWindow(dpy, save_query_win);
    return;
  }

  R = (unsigned char *)malloc(SOURCE_PIXELS*sizeof(unsigned char));
  if (R == NULL) return;
  G = (unsigned char *)malloc(SOURCE_PIXELS*sizeof(unsigned char));
  if (G == NULL) {
    free(R);
    return;
  }
  B = (unsigned char *)malloc(SOURCE_PIXELS*sizeof(unsigned char));
  if (B == NULL) {
    free(R);
    free(G);
    return;
  }
  
  writebuf = fopen(save_filename,"w");
  if (writebuf == NULL) {
    free(R);
    free(G);
    free(B);
    return;
  }
  fprintf(writebuf,"%d %d",source_wd,source_ht);

  tempbuf = ximage->data;
  convert_to_rgb(tempbuf,R,G,B);

  *(R+(source_ht*source_wd)) = *(G+(source_ht*source_wd)) = 
    *(B+(source_ht*source_wd)) = 0; /* guarantee legibility of header */

  for (y = source_ht - 1; y >= 0; y--) {
    for (x = 0; x < source_wd; x++) {
      fwrite(R+(y*source_wd)+x, sizeof(unsigned char), 1, writebuf);
      fwrite(G+(y*source_wd)+x, sizeof(unsigned char), 1, writebuf);
      fwrite(B+(y*source_wd)+x, sizeof(unsigned char), 1, writebuf);
    }
  }

  fclose (writebuf);
  if (ximage) {
    XDestroyImage(ximage);
    ximage = NULL;
  }
  free(R);
  free(G);
  free(B);
#ifndef SYSV
  cur_point = rindex(save_filename,'/');
  *cur_point = '\0';
  chdir(save_filename);
#endif SYSV
  if (forkval == -1) {
    XUnmapWindow(dpy, save_query_win);
    return;
  }
  if (forkval == 0)
    exit(0);
}

convert_to_rgb (ptr,red,green,blue)
unsigned char  *ptr,*red,*green,*blue;


{ unsigned char source [4], dest_r [4], dest_g [4], dest_b [4];
  int i, wh, videopix, bytes;
  double u_gain=0.7, v_gain=0.8, y_gain=4.0;
  
  
  for (videopix = 0; videopix < 77120; videopix++) {
    for (bytes = 0; bytes < 4; bytes++)
      source[bytes] = ptr [4 * videopix + bytes + 0];
    
    parallax_to_rgb (source, dest_r, dest_g, dest_b, y_gain,u_gain,v_gain);
    
    for (bytes = 0; bytes < 4; bytes++) {
      red[4*videopix+bytes]=dest_r[bytes+0];
      green[4*videopix+bytes]=dest_g[bytes+0];
      blue[4*videopix+bytes]=dest_b[bytes+0];
    }
  }
}


parallax_to_rgb(source_pix, dest_pix_r, dest_pix_g, dest_pix_b, y_gain, u_gain, v_gain)
unsigned char source_pix[4], dest_pix_r[4], dest_pix_g[4], dest_pix_b[4];
double u_gain, v_gain, y_gain;

{
  register double u, v, r, g, b;
  double Y[4]; /* IBM RT complains that it can't take the addr of register */
  register int I, temp;
  register char uu, vv;
  
  
  /* Unpack the bits - Y is the lower six bits of each pixel */
  for (I = 0; I < 4; I++) 
    {
      Y[I] = (float) (source_pix[I] & 0x3f);
      Y[I] *= y_gain;
    }
  
  /* chroma is spread out over the four pixels in the two upper bytes */
  /* u is the first two pixels, and v is the last two                 */
  
  u = (float) ((((source_pix[1]>>6) & 0x03) | ((source_pix[0] >>4) & 0x0c))) - 8.0;
  v = (float) ((((source_pix[3]>>6) & 0x03) | ((source_pix[2] >>4) & 0x0c))) - 8.0;
  
  u *= 32.0;
  v *= 32.0;
  
  u *= u_gain;
  v *= v_gain;
  
  /* Then use the Y,u(R-Y),v(B-Y) values to calculate R,G,B */
  for (I = 0; I < 4; I++) {
    temp = (int) (Y[I] + u);
    if (temp > 255)
      dest_pix_r[I] = 255;
    else if (temp < 0)
      dest_pix_r[I] = 0;
    else
      dest_pix_r[I] = (unsigned char) temp;
    
    temp = (int) (Y[I] + v);
    if (temp > 255)
      dest_pix_b[I] = 255;
    else if (temp < 0)
      dest_pix_b[I] = 0;
    else
      dest_pix_b[I] = (unsigned char) temp;
    
    temp = (int) (Y[I] - 0.509933 * u - 0.18543 * v);
    if (temp > 255)
      dest_pix_g[I] = 255;
    else if (temp < 0)
      dest_pix_g[I] = 0;
    else
      dest_pix_g[I] = (unsigned char) temp;
  }
}

XImage *get_a_still(vid_win)
     Drawable vid_win;

{
  XImage *tempimage;
  GC gc;
  extern Window root;
  gc = DefaultGC(dpy, screen);
#ifdef BAD_SERVER
  XGrabServer(dpy);
  XMapWindow(dpy, vid_win);
  XRaiseWindow(dpy, vid_win);
#endif
#ifdef DITHERCONTROL
  XPlxVideoDither(dpy, vid_win, gc, DitherNone);
#endif DITHERCONTROL
  XPlxVideoStill (dpy,vid_win,gc,0,0,0,0,640,482);
  XSync (dpy,0);
  tempimage = XGetImage(dpy,vid_win,0,0,640,482,AllPlanes,ZPixmap);
#ifdef DITHERCONTROL
  XPlxVideoDither(dpy, vid_win, gc, DitherChroma);
#endif DITHERCONTROL
#ifdef BAD_SERVER
  XUnmapWindow(dpy, vid_win);
  XUngrabServer(dpy);
#endif
  return(tempimage);
}
#endif PLX
