# include "Ximage.h"
# include "jpeglib.h"

int JPEGit (Graphic *graphic, Layout *layout) {
  
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
  JSAMPLE *image_buffer;	/* Points to data for current line */

  int j, k, m;
  unsigned char *buff;
  double Nchar, Npix, start, slope, frac;
  int quality;
  unsigned long pcolor;

  char filename[1024];
  int Nbytes, status;

  XImage *tmpimage;

  FILE *f;
  
  /* expect a line telling the number of bytes and a filename */
  status = read (layout[0].Ximage, filename, 16);
  filename[16] = 0;
  sscanf (filename, "%*s %d", &Nbytes);
  status = read (layout[0].Ximage, filename, Nbytes);
  filename[status] = 0; /* make the string easy to parse */

  /* 
  switch (graphic[0].Nbits) {
  case 8:
    break;
  case 16:
    fprintf (stderr, "converter to 16 bit not yet implemented\n");
    return (TRUE);
    break;
  case 24:
    fprintf (stderr, "converter to 24 bit not yet implemented\n");
    return (TRUE);
    break;
  case 32:
    fprintf (stderr, "converter to 32 bit not yet implemented\n");
    return (TRUE);
    break;
  }
  */

  /* set up the error handler , initialize the JPEG compression object. */
  cinfo.err = jpeg_std_error (&jerr);
  jpeg_create_compress (&cinfo);

  f = fopen (filename, "w");
  if (f == (FILE *) NULL) {
    fprintf (stderr, "failed to open %s for output\n", filename);
    return (TRUE);
  }
  jpeg_stdio_dest(&cinfo, f);
  
  quality = 75;
  cinfo.image_width = layout[0].picture.dx; 	/* image width and height, in pixels */
  cinfo.image_height = layout[0].picture.dy;
# ifdef GREYSCALE
  cinfo.input_components = 1;		        /* # of color components per pixel */
  cinfo.in_color_space = JCS_GRAYSCALE; 	/* colorspace of input image */
# else 
  cinfo.input_components = 3;		        
  cinfo.in_color_space = JCS_RGB; 	
# endif
  jpeg_set_defaults (&cinfo);
  jpeg_set_quality (&cinfo, quality, TRUE       /* limit to baseline-JPEG values */);
  jpeg_start_compress (&cinfo, TRUE);

  ALLOCATE (image_buffer, JSAMPLE, 3*layout[0].picture.dx);
  buff = (unsigned char *)layout[0].picture.data;
  slope = layout[0].slope;
  start = layout[0].start;
  Nchar = 255.0;                                /* range of output values */
  Npix = layout[0].Npixels;
  frac = Nchar / Npix;
  
  {
    XWindowAttributes WindowAttributes;
    Pixmap tmp_pixmap;
    Window tmp_window;
    
    XGetWindowAttributes (graphic[0].display, graphic[0].window, &WindowAttributes);
    
    tmp_pixmap = XCreatePixmap (graphic[0].display, graphic[0].window, graphic[0].dx, graphic[0].dy, WindowAttributes.depth);

    tmp_window = graphic[0].window;
    graphic[0].window = tmp_pixmap;

    Refresh (graphic, layout, 0);

    tmpimage = XGetImage (graphic[0].display, graphic[0].window, layout[0].picture.x+1, layout[0].picture.y+1, layout[0].picture.dx, layout[0].picture.dy, 0xffffffff, ZPixmap);

    for (j = 0; (j < layout[0].picture.dy) && (cinfo.next_scanline < cinfo.image_height); j++) {
      for (k = 0; k < layout[0].picture.dx; k++) {
	pcolor = XGetPixel (tmpimage, k, j);
	if (pcolor == layout[0].white) { 
	  image_buffer[3*k+0] = Nchar;
	  image_buffer[3*k+1] = Nchar;
	  image_buffer[3*k+2] = Nchar;
	  continue;
	}
	if (pcolor == layout[0].overlay[0].color) { 
	  image_buffer[3*k+0] = Nchar;
	  image_buffer[3*k+1] = 0;
	  image_buffer[3*k+2] = 0;
	  continue;
	}
	if (pcolor == layout[0].overlay[1].color) { 
	  image_buffer[3*k+0] = 0;
	  image_buffer[3*k+1] = Nchar;
	  image_buffer[3*k+2] = 0;
	  continue;
	}
	if (pcolor == layout[0].overlay[2].color) { 
	  image_buffer[3*k+0] = 0;
	  image_buffer[3*k+1] = 0;
	  image_buffer[3*k+2] = Nchar;
	  continue;
	}
	if (pcolor == layout[0].overlay[3].color) { 
	  image_buffer[3*k+0] = Nchar;
	  image_buffer[3*k+1] = Nchar;
	  image_buffer[3*k+2] = 0;
	  continue;
	}
	for (m = 0; (layout[0].cmap[m].pixel != pcolor) && (m < Npix); m++);
	/* val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix); */
	image_buffer[3*k+0] = layout[0].cmap[m].red / 256;
	image_buffer[3*k+1] = layout[0].cmap[m].green / 256;
	image_buffer[3*k+2] = layout[0].cmap[m].blue / 256;
      }
      row_pointer[0] = image_buffer;
      (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
    }
    graphic[0].window = tmp_window;
    XFreePixmap (graphic[0].display, tmp_pixmap);
  }

  XDestroyImage (tmpimage);

  jpeg_finish_compress (&cinfo);
  fclose (f);
  jpeg_destroy_compress (&cinfo);

  return (TRUE);

}
