/* C code routines for dumping arrays as multiple PS images on a single page

  Alex Barnett Feb 2004
*/


/* -------------- postscript colormap: edit to taste ------------ */
   /* colour scale... not added wrap-around of out-of-[0,1] values */
float rc(float a) /* RED */
{
  float b = a; /* - floorf(a); */
  return min(1.0,max(0.0,5*b-1.0));
}

float gc(float a) /* GREEN */
{
  float b = a; /* - floorf(a); */
  return min(1.0,max(0.0,5*b-3.0));
}

float bc(float a) /* BLUE */
{
  float b = a; /* - floorf(a);*/
   if (b<0.2)
    return 5*b;
  else if (b<0.8)
    return min(1.0,max(0.0,3.0-5*b));
  else
    return 5*b - 4.0;
}

int byte(float a)
     /* clip & map float from 0-1 to integer in 0-255 range */
{
  return min(0xff, max(0, (int)(a*255.0 + 0.5)));
}


/* ----------------------------------------------- DUMP POSTSCRIPT ------ */
int dump_ps(int i_lo, int i_hi, int n_wid, double gapfrac, int encap, \
	    int colour, int val_label)
 /* Writes postscript output for range [i_lo,i_ho] of states, with n_wid
    images written across, gapfrac fractional gap between them.
    Aspect ratio preserved (square image pixels).
    encap    = true : EPS, otherwise PS.
    colour   = true : use colourmap in rc,gc,gb, otherwise grayscale
    val_label= true : include value labels to 6 digits below each image

    2/26/04 Barnett
    2/27/04 multiple images and value labels
 */
{
  int i, j, l, lx = 0, ly = 0, ne = i_hi - i_lo + 1, nh;
  double xs = 10.0;  /* x-size of one sta image in inches */
  double ys = (xs*ny)/nx;
  double pti = 72.0;   /* pts per inch in PS language */
  double g = gapfrac*xs; /* gap in inches -Roman findfont 0.03 scalefont setfont\n\n");

  /* Loop over images.................................................... */
  for (l=i_lo; l<=i_hi; ++l) {
    printf("l=%d: image array loc (%d,%d)\n", l, lx, ly);
    /* move and scale for current image... */
    fprintf(fp, "gsave\n%g i %g i translate %g i %g i scale\n", \
	    g + (g+xs)*lx, g + (g+ys)*ly, xs, ys);
    /* write type-1 image dictionary... */
    fprintf(fp, "<<\n /ImageType 1\n /Width %d\n /Height %d\n", nx, ny);
    /* data ordering: left-to right fast, then top to bottom slow... */
    fprintf(fp, " /BitsPerComponent 8\n /ImageMatrix [%d 0 0 %d 0 0]\n", \
	    nx, ny);
    if (colour)
      fprintf(fp, " /Decode [0 1 0 1 0 1]\n");
    else
      fprintf(fp, " /Decode [0 1]\n");
    fprintf(fp, " /Interpolate true\n");
    fprintf(fp, " /DataSource currentfile /ASCIIHexDecode filter\n>>\nimage\n");

    /* Write single image data from l'th vector in vec array... */
    dispvec = vec[l];
    for (j=1; j<=ny; ++j) {
      for (i=1; i<=nx; ++i) {
	/* Plot square of func, use current zscale... */
	a = zscale * (b=dispvec[nx*(j-1) + i])*b; /* put your own data array here! */
	/* write ASCII-hex data... (spaces, LF/CR irrelevant) */
	if (colour)
	  fprintf(fp, "%.2x%.2x%.2x", byte(rc(1-a)), byte(gc(1-a)), \
		  byte(bc(1-a))); /* a in range [0,1], and 1-a inverts the colormap */
	else
	  fprintf(fp, "%.2x", byte(1-a));
      }
      fprintf(fp, "\n");
    }

    /* write a > to close filter, then text label (must fit in BBOX!) */
    fprintf(fp, ">\n");
    if (val_label)
      fprintf(fp, "0.3 -0.05 moveto (k = %.6f) show\n", val[l]);
    fprintf(fp, "grestore\n\n");

    /* update location (lx, ly) in image array... */ 
    ++lx;
    if (lx==n_wid) {
      lx = 0;
      ++ly;
    }
  } /* end image loop ................................................ */
  

  /* Trailer... showpage should be ignored in EPS */
  fprintf(fp, "showpage\n%%EOF\n");
  fclose(fp);
  printf("done.\n");
}


