/* @(#)bdf2ps.c	19.1 (ES0-DMD) 02/25/03 14:35:14 */
/*===========================================================================
  Copyright (C) 1995 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT  (c) 1997 European Southern Observatory
.LANGUAGE   C
.IDENT      bdf2ps.c
.AUTHOR     Preben J. Grosbol [ESO/IPG]
.KEYWORDS   MIDAS bdf format, PostScript, conversion
.PURPOSE    Convert MIDAS bdf files to PostScript format
.ENVIRON    UNIX, MIDAS
.VERSION    1.0  1992-Jun-23 : Creation,     PJG
.VERSION    1.1  1992-Oct-05 : Better LUT's,     PJG
.VERSION    1.2  1993-Apr-14 : LUT tables and true color,     PJG
.VERSION    1.3  1993-Jul-01 : add frame size and origin,     PJG
.VERSION    1.4  1993-Nov-12 : Correct error + add options,     PJG
.VERSION    1.5  1993-Nov-25 : Separate X/Y scales,     PJG
.VERSION    1.6  1994-Mar-18 : Correct error in scaling,     PJG
.VERSION    1.7  1994-May-03 : Add option for frame box,     PJG
.VERSION    1.8  1994-May-19 : Explicit check of SC error returns,  PJG
.VERSION    1.9  1994-Oct-09 : Write usage on wrong option,  PJG
.VERSION    1.91 1997-Feb-18 : Explicit cast in SCFMAP/GET,  PJG
.VERSION    1.95 1997-May-15 : Initiate pointers to NULL,  PJG
.VERSION    2.00 1998-Feb-27 : Use 'strtok' and add line/arc draw,  PJG
.VERSION    2.10 1998-Mar-03 : Correct algorithm for neg. step size,  PJG
------------------------------------------------------------------------*/
#include    <stdlib.h>                /* Standard Library definitions   */
#include    <stdio.h>                 /* Standard I/O definitions       */
#include    <math.h>                  /* Standard Mathmatical library   */
#include    <string.h>                /* Standard string definitions    */
#include    <time.h>                  /* Time library                   */
#include    <osparms.h>               /* MIDAS OS-definitions           */
#include    <midas_def.h>             /* MIDAS definitions              */
#include    <fitsfmt.h>               /* Data formats                   */
#include    <fitsdef.h>               /* FITS definitions               */
#include    <fitskwt.h>               /* FITS Table definitions         */

#define     MXPARM                32  /* Max. no. of parameters         */
#define     MXNAME                64  /* Max size of name string        */
#define     MXLINE               128  /* Max. size of print line        */
#define     MXITF                256  /* Max size of LUT/ITT tables     */
#define     PSPAGE             "A4P"  /* Default page format            */
#define     PSFONT       "Helvetica"  /* Standard PS font used          */
#define     PSNAME      "psimage.ps"  /* Default name for output file   */

typedef struct {
                 char         *name;  /* Name of page format            */
                 double       xsize;  /* Total size of page in X (cm)   */
                 double       ysize;  /* Total size of page in Y (cm)   */
		 double        xmar;  /* Page margin in X (cm)          */
		 double        ymar;  /* Page margin in Y (cm)          */
                 double       angle;  /* Angle of page ref. Portait     */
	       } PAGE;

static PAGE page[] = { {"A4P", 21.00, 29.73, 1.0, 1.0,   0.0},
		       {"A4L", 21.00, 29.73, 1.0, 1.0,  90.0},
		       {"A3P", 29.73, 42.00, 1.0, 1.0,   0.0},
		       {"A3L", 29.73, 42.00, 1.0, 1.0,  90.0},
		       {"S4P", 21.00, 29.73, 2.0, 3.0,   0.0},
		       {"S4L", 21.00, 29.73, 2.0, 3.0,  90.0},
		       {(char *) 0, 0.0, 0.0, 0.0, 0.0, 0.0} };

                                      /* Definition of parameter list   */
static char *plist[] = {"i+:Input file",
                        "o+:Output file",
                        "l+:File list",
                        "p+:Page format",
                        "r+:Resolution per cm",
                        "c+:Color LUT table",
                        "s+:Xscale,Yscale",
                        "z+:Z-cut levels (low,high)",
                        "w-:Wedge",
                        "b-:Background color",
                        "n-:Negative",
                        "e-:Exponential scale",
                        "a-:Autoscale",
                        "f-:Frame",
                        "E-:Encapsulated PostScript",
                        "N-:No Identifier",
                        "v-:Verbose", (char *) 0};
static char usage[] = 
"Usage: bdf2ps [-i bdf-file] [-o ps-file] [-l list-file] [-p page-format]\n\t\
[-r resolution] [-c LUT] [-s xscale,yscale] [-z lcut,hcut] [-wbneafENv]";

int main(argc,argv)
int        argc;          /* parameter count                            */
char     **argv;          /* pointers to parameters                     */
{
  unsigned char  *data, *px[3];
  char           c, *pc, *pl, *pfmt, *pfl, *pin, *pon, *text;
  char           pg[4], iname[MXNAME];
  char           *pval[MXPARM], line[MXLINE], ident[MXLINE];
  char           *gvparm(), *getenv();
  int            vmode, amode, bmode, wmode, nmode, fmode;
  int            nx, ny, mx, my, na, np, nxs, nys, nxe, nye;
  int            n, i, ip, iva, err, n1, n2, cmode, image, lok;
  int            msize, idf, ioff, idt, nr, ng, nb, gcmode;
  int            inull, lfsize, ipl, ixcen, iycen, ilc, ihc;
  int            *pbl, *pgl, *prl, npix[3], kunit[4];
  int            itt[MXITF], blut[MXITF], glut[MXITF], rlut[MXITF];
  int            dcparm(), pscolor(), psdraw();
  float          *buf, *pf, val, cuts[4];
  double         cl, ch, gcl, gch, gxscale, gyscale, xscale, yscale;
  double         ww, res[2], fac, xw, yw, pi, lcut, hcut;
  double         xorg, yorg, xsize, ysize, xend, yend, xcen, ycen;
  double         start[3], step[3], xstr, ystr, xo, xs, yo, ys;
  double         red, blue, green;
  struct tm      tms;
  PAGE           *pp;
  FILE           *pfd;

  SCSPRO("-1");                           /* initiate MIDAS environment */

  na = 1; iva = 0;
  SCECNT("PUT", &na, &iva, &iva);           /* disable SC errors        */

  if (dcparm(argc,argv,plist,pval)) {       /* decode parameter list    */
     fprintf(stdout,"%s\n",usage); SCSEPI();
   }

  pin = gvparm('i',plist,pval);
  pfl = gvparm('l',plist,pval);
  if ((pin && pfl) || !(pin || pfl)) {      /* If no file list/name     */
     fprintf(stderr,"Error: either file name OR list MUST be given!\n");
     SCSEPI();
   }

  if (pfl) {
     pfd = fopen(pfl,"r");
     if (!pfd) {
	fprintf(stderr,"Error: cannot open list file >%s<\n",pfl);
	SCSEPI();
      }
     pin = (char *) 0;
   }
  else pfd = NULL;

  pfmt = (pc=gvparm('p',plist,pval)) ? pc : PSPAGE;   /* Page format */
  for (n=0; n<4; n++) {
     c = (*pfmt) ? *pfmt : PSPAGE[n];
     pg[n] = ('a'<=c && c<='z') ? c+'A'-'a' : c;
     if (*pfmt) pfmt++;
   }
  for (pp=page; pp->name && strcmp(pp->name,pg); pp++);
  if (!(pp->name)) {
     fprintf(stderr,"Error: Unknown page format!\n");
     SCSEPI();
   }
  lfsize = 8;
  if (gvparm('e',plist,pval) != (char *) 0) {  /* ramp or log ITT      */
     fac = 255.0/log(256.0);
     for (n=0; n<MXITF; n++) itt[n] = fac*log(1.0+n);
   }
  else
    for (n=0; n<MXITF; n++) itt[n] = n;

  if (gvparm('n',plist,pval) != (char *) 0)    /* negative ITT         */
     for (n=0; n<MXITF/2; n++) {
	i = itt[n]; itt[n] = itt[MXITF-n-1]; itt[MXITF-n-1] = i;
      }

  amode = (gvparm('a',plist,pval) != (char *) 0);
  vmode = (gvparm('v',plist,pval) != (char *) 0);
  bmode = (gvparm('b',plist,pval) != (char *) 0);
  wmode = (gvparm('w',plist,pval) != (char *) 0);
  nmode = (gvparm('N',plist,pval) != (char *) 0);
  fmode = (gvparm('f',plist,pval) != (char *) 0) ? -1 : 0;

  ident[0] = '\0';
  iname[0] = '\0';
  px[0] = px[1] = px[2] = (unsigned char *) 0;

  cmode = 0;
  if ((pc=gvparm('c',plist,pval))) {            /* define LUTs          */
    cmode = 1;
    if (vmode) printf("Color table: >%s<\n",pc);
    i = MXITF-1;
    switch (*pc) {
        case '0' :                                 /* default LUT no. 0 */
          n1 = 0; n2 = 32;
          for (n=n1; n<n2; n++) {
	     blut[n] = 8*n; glut[n] = 0; rlut[n] = 0;
	   }
	  n1 = n2 ; n2 = 80;
          for (n=n1; n<n2; n++) {
	     blut[n] = 255; glut[n] = (255*(n-n1))/48; rlut[n] = 0;
	   }
	  n1 = n2 ; n2 = 128;
          for (n=n1; n<n2; n++) {
	     blut[n] = 255 - (255*(n-n1))/48; glut[n] = 255; rlut[n] = 0;
	   }
	  n1 = n2 ; n2 = 176;
          for (n=n1; n<n2; n++) {
	     blut[n] = 0; glut[n] = 255; rlut[n] = (255*(n-n1))/48;
	   }
	  n1 = n2 ; n2 = 224;
          for (n=n1; n<n2; n++) {
	     blut[n] = 0; glut[n] = 252 - (255*(n-n1))/48; rlut[n] = 255;
	   }
	  n1 = n2 ; n2 = MXITF;
          for (n=n1; n<n2; n++) {
	     blut[n] = 8*(n-n1); glut[n] = 8*(n-n1); rlut[n] = 255;
	   }
          break;
        case '1' :                                /* default LUT no. 1 */
          for (n=0; n<MXITF; n++) blut[n] = (n<MXITF/2) ? i-2*n : 0;
	  for (n=0; n<MXITF; n++) rlut[n] = (n<=MXITF/2) ? 0 : 2*n-MXITF;
	  for (n=0; n<MXITF; n++) glut[n] = i - blut[n] - rlut[n];
	  break;
	case '2' :                                /* default LUT no. 2 */
          for (n=0; n<MXITF; n++) blut[n] = i - n;
	  for (n=0; n<MXITF; n++) rlut[n] = n;
	  for (n=0; n<MXITF; n++) glut[n] = 128;
	  break;
	case '3' :                                /* default LUT no. 3 */
	  pi = 4.0*atan(1.0);
	  fac = pi/256.0;
          for (n=0; n<MXITF; n++) 
	    blut[n] = 0.5*i*(1.0+cos(fac*n));
	  for (n=0; n<MXITF; n++) 
	    rlut[n] = 0.5*i*(1.0+cos(5.0*fac*n-pi));
	  for (n=0; n<MXITF; n++) 
	    glut[n] = 0.5*i*(1.0+sin(9.0*fac*n));
	  break;
        default  :                                  /* read LUT table  */
	  err = TCTOPN(pc, F_I_MODE, &idt);
	  if (err != ERR_NORMAL) {
	     fprintf(stderr,"Error: Cannot open LUT table >%s<!\n",pc);
	     SCSEPI();
	   }
	  err = TCCSER(idt, "RED", &nr);
	  err = TCCSER(idt, "GREEN", &ng);
	  err = TCCSER(idt, "BLUE", &nb);
	  for (n=0; n<MXITF; n++) {
	     err = TCERDR(idt, n, nr, &val, &inull);
	     rlut[n] = (inull) ? 0 : i*val;
	     err = TCERDR(idt, n, ng, &val, &inull);
	     glut[n] = (inull) ? 0 : i*val;
	     err = TCERDR(idt, n, nb, &val, &inull);
	     blut[n] = (inull) ? 0 : i*val;
	   }
	  err = TCTCLO(idt);
	}
     prl = rlut; pgl = glut; pbl = blut;
   }
  else pbl = pgl = prl = (int *) 0;

  res[0] = (pc=gvparm('r',plist,pval)) ? atof(pc) : 0.0;    /* resolution */
  res[1] = 0.0;

  gxscale = gyscale = 0.0;                         /* Global X/Y scale */
  if ((pc=gvparm('s',plist,pval))) {
     gxscale = atof(pc);
     while (*pc && *pc!=',') pc++;
     gyscale = (*pc++ == ',') ? atof(pc) : gxscale;
   }

  gcl = gch = 0.0;                                   /* Global z-cuts */
  if ((pc=gvparm('z',plist,pval))) {
     gcl = atof(pc);
     while (*pc && *pc!=',') pc++;
     gch = (*pc++ == ',') ? atof(pc) : gcl;
   }

  pon = (pc=gvparm('o',plist,pval)) ? pc : PSNAME; /* get PS-file name */
  if(psopen(pon,iname,pp->xsize,pp->ysize,     /* open PS output file  */
	 pp->xmar,pp->ymar,pp->angle,res)) {
     fprintf(stderr,"Error: cannot open PostScript output file\n");
     SCSEPI();
   }
  psmode(bmode, 0.0, 0.0, 1.0);               /* set background color  */
  ww = 0.2;

  if (!(gvparm('E',plist,pval))) {
    if (oshdate(ident,&tms)) ident[0] = '\0';
    sprintf(line,"ESO-MIDAS; %s",ident);
    pslabel(0.0,0.0,PSFONT,5,line);
  }

  while (pin || (pfd && fgets(line,MXLINE,pfd))) { /* go through files */
     cl = gcl; ch = gch;
     xscale = gxscale; yscale = gyscale;
     xorg = 0.0; yorg = 1.0;
     if (pp->angle == 0.0) {
	xsize = pp->xsize - 2*(pp->xmar) - xorg - 2.0*ww;
	ysize = pp->ysize - 2*(pp->ymar) - yorg;
      }
     else {
	xsize = pp->ysize - 2*(pp->ymar) - xorg - 2.0*ww;
	ysize = pp->xsize - 2*(pp->xmar) - yorg;
      }

     ixcen = iycen = 0;                         /* no x/y-center given */
     xcen = ycen = 0.0;
     ilc = ihc = 0;
     lcut = 0.0; hcut = 1.0;

     if (!pin) {                                   /* decode file list */
       if (vmode) fprintf(stdout,"File line >%s",line);
       lok = 0;
       image = 0;
       pl = strtok(line, " \t:\n");
       if (!pl || *pl=='#' || *pl=='!') continue; /* comment line     */
       switch (*pl) {
       case 'I' :
       case 'i' :
	 if (!(pl=strtok(NULL, " \t:"))) break;
	 pc = strcpy(iname,pl);                   /* get file name    */
	 pin = iname;
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 yorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xscale = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 yscale = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xsize = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 ysize = atof(pl);
	 ixcen = ((pl=strtok(NULL, " \n\t,")) != 0);
	 if (ixcen) xcen = atof(pl);
	 iycen = ((pl=strtok(NULL, " \n\t,")) != 0);
	 if (iycen) ycen = atof(pl);
	 ilc = ((pl=strtok(NULL, " \n\t,")) != 0);
	 if (ilc) lcut = atof(pl);
	 ihc = ((pl=strtok(NULL, " \n\t,")) != 0);
	 if (ihc) hcut = atof(pl);
	 if (vmode) {
	   fprintf(stdout,"File >%s< %7.1f %7.1f %7.1f %7.1f %7.1f %7.1f\n"
		   ,pin,xorg,yorg,xscale,yscale,xsize,ysize);
	   fprintf(stdout,"     %7.1f %7.1f %7.1f %7.1f\n"
		   ,xcen,ycen,lcut,hcut);
	 }
	 lok = 1;
	 image = 1;
	 break;
       case 'T' :                                      /* write text  */
       case 't' :
	 if (!(pl=strtok(NULL, "\n"))) break;
	 while (*pl && (*pl==' ' || *pl=='\t')) pl++;
	 if (*pl=='"') c = '"', pl++; else c = ' ';
	 text = pl;
	 while (*pl && *pl!=c) pl++;
	 *pl++ = '\0';
	 if (!(pl=strtok(pl, " \n\t,"))) break;
	 xorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 yorg = atof(pl);
	 i = (pl=strtok(NULL, " \n\t,")) ? atol(pl) : 5;
	 red = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 green = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 gcmode = (pl==0) ? 0 : 1;
	 blue = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 pscolor(gcmode,red,green,blue);
	 if (vmode) {
	   fprintf(stdout,"Text >%s< %7.1f %7.1f, %d\n",text,xorg,yorg,i);
	 }
	 pslabel(xorg,yorg,PSFONT,i,text);
	 lok = 1;
	 break;
       case 'L' :                                        /* draw line   */
       case 'l' :
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 yorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xsize = atof(pl);
	 ysize = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 xscale = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.1;
	 red = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 green = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 gcmode = (pl==0) ? 0 : 1;
	 blue = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 pscolor(gcmode,red,green,blue);
	 if (vmode) {
	   fprintf(stdout,"Line %7.1f %7.1f,%7.1f %7.1f, %7.2f\n",
		   xorg,yorg,xsize,ysize,xscale);
	 }
	 psdraw(0,xorg,yorg,xscale,xsize,ysize,0.0,0.0);
	 lok = 1;
	 break;
       case 'C' :                                        /* draw circle  */
       case 'c' :
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 yorg = atof(pl);
	 if (!(pl=strtok(NULL, " \n\t,"))) break;
	 xsize = atof(pl);
	 xscale = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 yscale = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 360.0;
	 ysize = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.1;
	 red = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 green = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 gcmode = (pl==0) ? 0 : 1;
	 blue = (pl=strtok(NULL, " \n\t,")) ? atof(pl) : 0.0;
	 pscolor(gcmode,red,green,blue);
	 if (vmode) {
	   fprintf(stdout,"Circle %7.1f %7.1f,%7.1f %7.1f, %7.2f %7.2f\n",
		   xorg,yorg,ysize,xsize,xscale,yscale);
	 }
	 psdraw(1,xorg,yorg,ysize,xsize,xscale,yscale,0.0);
	 lok = 1;
	 break;
       default :
	 fprintf(stderr,"Warning: Unknown line type in input list file\n");
	 fprintf(stderr,"    >%32.32s<\n",line);
       }
       if (!lok) {
	 fprintf(stderr,"Error: wrong parameters in line\n");
	 fclose(pfd);
	 SCSEPI();
       }
       if (!image) continue;
     }

     if (vmode) fprintf(stdout,"Open image frame >%s<\n",pin);
     err = SCFOPN(pin, D_R4_FORMAT, 0, F_IMA_TYPE, &idf);
     if (err != ERR_NORMAL) {           /* check if frame exists       */  
	fprintf(stderr,"Warning: Image file >%s< not found\n", pin);
	pin = (char *) 0;
	continue;
      }
     err = SCDRDI(idf, "NAXIS", 1, 1, &iva, &na, kunit, &inull);
     if (na<2 || 3<na || err) {         /* check dimension of frame    */
	fprintf(stderr,"Error: Bad dimensions (%d) of image\n",na);
	SCFCLO(idf);
	pin = (char *) 0;
	continue;
      }
     err = SCDRDI(idf, "NPIX", 1, na, &iva, npix, kunit, &inull);
     mx = npix[0]; my = npix[1];
     msize = (na==3) ? mx*my : 0;
     np = (na==3) ? npix[2] : 1;
     if (na==3 && np!=3) {
	fprintf(stderr,"Error: 3-dimensional frame does NOT have 3 planes\n");
	SCFCLO(idf);
	pin = (char *) 0;
	continue;
      }
     err = SCDRDD(idf, "START",1, na, &iva, start, kunit, &inull);
     err = SCDRDD(idf, "STEP", 1, na, &iva, step, kunit, &inull);
     if (!ixcen) xcen = 0.5*(mx-1)*step[0] + start[0];
     if (!iycen) ycen = 0.5*(my-1)*step[1] + start[1];
     xw = fabs(step[0]*npix[0]);
     yw = fabs(step[1]*npix[1]);

     err = SCDGETC(idf, "IDENT", 1,MXLINE-1, &iva, ident);
     if (cl==ch) {                           /* read cuts from frame  */
	err = SCDRDR(idf, "LHCUTS", 1, 4, &iva, cuts, kunit, &inull);
	if (cuts[1]==cuts[0]) { ch = cuts[3]; cl = cuts[2]; }
	else { ch = cuts[1]; cl = cuts[0]; }
      }
     if (!ilc) lcut = cl;
     if (!ihc) hcut = ch;

/*   define image size and location   */

     if (xscale<=0.0 && yscale<=0.0) {
	xscale = xw/xsize; yscale = yw/ysize;
	if (yscale<xscale) yscale = xscale;
	else xscale = yscale;
      }
     else if (xscale<=0.0) xscale = yscale;
     else if (yscale<=0.0) yscale = xscale;

/*   range in X and Y                 */

     nxs = (xcen-start[0])/step[0] - 0.5*xsize*xscale/fabs(step[0]) + 1;
     if (nxs<1) nxs = 1;
     nxe = (xcen-start[0])/step[0] + 0.5*xsize*xscale/fabs(step[0]) + 1;
     if (mx<nxe) nxe = mx;
     nx = nxe - nxs + 1;

     nys = (ycen-start[1])/step[1] - 0.5*ysize*yscale/fabs(step[1]) + 1;
     if (nys<1) nys = 1;
     nye = (ycen-start[1])/step[1] + 0.5*ysize*yscale/fabs(step[1]) + 1;
     if (my<nye) nye = my;
     ny = nye - nys + 1;

     if (mx<nxs || nxe<1 || nx<2 || my<nys || nye<1 || ny<2) {
	fprintf(stderr,"Warning: frame not in display window!\n");
	SCFCLO(idf); pin = (char *) 0;
	continue;
      }

     xstr = start[0] + (nxs-1)*step[0];
     ystr = start[1] + (nys-1)*step[1];
     xend = start[0] + (nxe-1)*step[0];
     yend = start[1] + (nye-1)*step[1];

     xo = xorg + 0.5*xsize - fabs(xcen-xstr)/xscale;
     xs = fabs(xend-xstr)/xscale;
     yo = yorg + 0.5*ysize - fabs(ycen-ystr)/yscale;
     ys = fabs(yend-ystr)/yscale;

     if (na==3)                                  /* define ITT and LUT   */
       psitf(2,MXITF,itt,itt,itt,itt);
     else
       psitf(cmode,MXITF,itt,prl,pgl,pbl);

     psframe(fmode, xo, yo, xs, ys, PSFONT, lfsize, xstr, ystr, xend, yend);
     psimage(nx, ny, 0, 8);

     if (vmode) {
	fprintf(stdout,"Origin,size : %6.1f %6.1f, %6.1f %6.1f\n",
		xo,yo,xs,ys);
	fprintf(stdout,"  Scale,cuts: %6.1f %6.1f, %6.1f %6.1f\n",
		xscale,yscale,lcut,hcut);
	fprintf(stdout,"  Range: %d %d %d %d; %d %d %d %d\n",
		nxs,nxe,nx,mx,nys,nye,ny,my);
      }

/*   create internal buffer   */

     buf = (float *) calloc(2*nx, sizeof(float));
     if (!buf) {
	fprintf(stderr,"Error: Cannot open internal buffer!\n");
	SCSEPI();
      }
     fac = (MXITF-1) / (hcut - lcut);
     ioff = nxs + mx*(nys-1);

     for (n=0; n<ny; n++) {
	ipl = 0; 
	data = (unsigned char *) &buf[nx];
	for (ip=0; ip<np; ip++) {
	   err = SCFGET(idf, ioff+ipl, nx, &iva, (char *) buf);
	   pf = buf; px[ip] = data;
	   while (iva--) {
	      if (*pf<lcut)
		*data = 0;
	      else if (hcut<*pf)
		*data = MXITF-1;
	      else
		*data = fac * (*pf-lcut);
	      data++; pf++;
	    }
	   ipl += msize;
         }
	psline(px[0], px[1], px[2]);
	ioff += mx;
      }
     data = 0;
     psline(data, data, data);              /* flush internal buffer  */

     if (wmode) pswedge(1, xorg+xsize+0.05, yorg, ww, ysize, cl, ch);
     if (!nmode) pslabel(xorg,yorg-0.4,PSFONT,lfsize,ident);

     SCFCLO(idf);                                /* close bdf-file    */
     free(buf);
     pin = (char *) 0;
  }

  psclose();

  SCSEPI();
  exit(0);
}
