# include "Ximage.h"
# include <png.h>
# define NPALETTE NGRAPHCOLORS

int PNGit () {

  FILE *f;
  png_structp png_ptr;
  png_infop info_ptr;
  png_color palette[NPALETTE];
  int pchoice[NPALETTE];
  XColor color;
  png_byte **rows;
  int dx, dy;
  int i, j, k, found;
  XImage *tmpimage;
  unsigned long pixel;
  char filename[1024];
  int Nbytes, status;

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

  ALLOCATE (rows, png_byte *, dy);
  for (i = 0; i < dy; i++) {
    ALLOCATE (rows[i], png_byte, 3*dx);
  }

  /* define the palette */
  for (i = 0; i < NPALETTE; i++) {
    color.pixel = graphic.color[i];
    XQueryColor (graphic.display, graphic.colormap, &color);
    palette[i].red = (0x100 * color.red / 0x10000);
    palette[i].green = (0x100 * color.green / 0x10000);
    palette[i].blue = (0x100 * color.blue / 0x10000);
    pchoice[i] = color.pixel;
  }

  f = fopen (filename, "w");
  if (f == (FILE *) NULL) {
    fprintf (stderr, "can't open output file %s\n", "Xgraph.png");
    return (TRUE);  /* true because otherwise it quits kapa! */
  }

  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_voidp) NULL, (png_voidp) NULL);
  if (!png_ptr) {
    fclose (f);
    fprintf (stderr, "can't get png structure\n");
    return (TRUE);
  }

  info_ptr = png_create_info_struct (png_ptr);
  if (!info_ptr) {
    png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
    fclose (f);
    fprintf (stderr, "can't get png info structure\n");
    return (TRUE);
  }

  if (setjmp (png_ptr[0].jmpbuf)) {
    png_destroy_write_struct (&png_ptr, &info_ptr);
    fclose (f);
    fprintf (stderr, "can't get png return\n");
    return (TRUE);
  }

  png_init_io (png_ptr, f);

  /* see docs for write-row-callback to provide progress info */

  png_set_IHDR (png_ptr, info_ptr, dx, dy, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 

  /* png_set_IHDR (png_ptr, info_ptr, dx, dy, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); */

  png_set_PLTE (png_ptr, info_ptr, palette, NPALETTE); 
 
  png_write_info (png_ptr, info_ptr);

  /* a new attempt... */

  {
    XWindowAttributes WindowAttributes;
    Pixmap tmp_pixmap;
    Window tmp_window;
    
    XGetWindowAttributes (graphic.display, graphic.window, &WindowAttributes);
    
    tmp_pixmap = XCreatePixmap (graphic.display, graphic.window, dx, dy, WindowAttributes.depth);

    tmp_window = graphic.window;
    graphic.window = tmp_pixmap;

    Refresh (1);

    tmpimage = XGetImage (graphic.display, graphic.window, 0, 0, dx, dy, 0xffffffff, ZPixmap);
    for (j = 0; j < dy; j++) {
      for (i = 0; i < dx; i++) {
	pixel = XGetPixel (tmpimage, i, j);
	for (found = k = 0; (k < NPALETTE) && !found; k++) {
	  if (pixel == pchoice[k]) {
	    found = TRUE;
	    rows[j][i] = k;
	    /*
	      rows[j][3*i+0] = palette[k].red;
	      rows[j][3*i+1] = palette[k].green;
	      rows[j][3*i+2] = palette[k].blue;
	    */
	  }
	}
      }
    }
    graphic.window = tmp_window;
    XFreePixmap (graphic.display, tmp_pixmap);
  }

  png_write_image (png_ptr, rows);
  png_write_end (png_ptr, info_ptr);
  png_destroy_write_struct (&png_ptr, &info_ptr);

  for (i = 0; i < dy; i++) {
    free (rows[i]);
  }
  free (rows);

  XDestroyImage (tmpimage);

  fclose (f);
  return (TRUE);

}
