C @(#)perspec.for	13.1.1.1 (ES0-DMD) 06/02/98 18:20:55
C===========================================================================
C Copyright (C) 1995 European Southern Observatory (ESO)
C
C This program is free software; you can redistribute it and/or 
C modify it under the terms of the GNU General Public License as 
C published by the Free Software Foundation; either version 2 of 
C the License, or (at your option) any later version.
C
C This program is distributed in the hope that it will be useful,
C but WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
C GNU General Public License for more details.
C
C You should have received a copy of the GNU General Public 
C License along with this program; if not, write to the Free 
C Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
C MA 02139, USA.
C
C Corresponding concerning ESO-MIDAS should be addressed as follows:
C	Internet e-mail: midas@eso.org
C	Postal address: European Southern Observatory
C			Data Management Division 
C			Karl-Schwarzschild-Strasse 2
C			D 85748 Garching bei Muenchen 
C			GERMANY
C===========================================================================
C
      PROGRAM PERSP
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  program PERSP 			version 1.00    920103
C  K. Banse                     	ESO - Garching
C  1.10  930512		2.00	940104
C
C.KEYWORDS
C  perspective, rebinning
C
C.INPUT/OUTPUT
C  the following keywords are used:
C
C  IN_A/C/1/60			input frame
C  OUT_A/C/1/60			output frame
C  INPUTR/1/2			rotation angle in degrees, in [0,360]
C				tilt angle in degrees in [0,90]
C
C.VERSIONS
C  1.00   creation
C  1.10   STKWRR had 1 param. too many !
C  2.00   add z-perspective plot
C	
C--------------------------------------------------
C
      IMPLICIT NONE
C
      INTEGER      IAV,N,NAXISA,NAXISC
      INTEGER*8    PNTRA,PNTRB,PNTRC
      INTEGER      IMNOA,IMNOB,IMNOC,STAT
      INTEGER      NPIXA(3),NPIXB(2),NPIXC(2),KZ,KNO
      INTEGER      N1,N2,NSIZ,NPERSP,DIM3C,KDIFF,PLANES(20)
      INTEGER      UNI(1),NULO,MADRID(1)
      INTEGER      ISCAL
C
      CHARACTER*60 FRAMEA,FRAMEB
      CHARACTER    CUNITA*64,IDENTA*72,STR*80
C
      DOUBLE PRECISION STEPA(3),STARTA(3),STARTB(2),STEPB(2),STEPC(2)
      DOUBLE PRECISION ST(2)
C
      REAL         RNULL
      REAL         ANGDEG,ANGLE,AC,AS,X1,X2,X3,Y1,Y2,Y3,X4,Y4
      REAL         PC, PCDEG
      REAL         PIXROT(2),ROTOFF(2),EN(2),RST(2)
      REAL         QUOT,RQUOT,R1,R2,RROT(4),CUTS(4)
      REAL         FACTO,RBUF(20),ZCUTS(2)
C
      COMMON   /VMR/  MADRID
C
      INCLUDE  'MID_INCLUDE:ST_DEF.INC'
C 
      EQUIVALENCE (X2,RBUF(1)),(Y2,RBUF(2)),(X4,RBUF(3)),(Y4,RBUF(4))
      EQUIVALENCE (X3,RBUF(5)),(Y3,RBUF(6)),(X1,RBUF(7)),(Y1,RBUF(8))
C
      DATA     FACTO  /0.0174533/               !  Pi / 180.
      DATA     NPIXA  /1,1,1/
      DATA     IDENTA /' '/, CUNITA /' '/       !necessary ... !!!
C
      INCLUDE  'MID_INCLUDE:ST_DAT.INC'
C 
C  get into MIDAS
      CALL STSPRO('PERSP')
C
C  get input frame + map it
      CALL STKRDC('IN_A',1,1,60,IAV,FRAMEA,UNI,NULO,STAT)
      CALL STIGET(FRAMEA,D_R4_FORMAT,F_I_MODE,F_IMA_TYPE,3,
     +            NAXISA,NPIXA,STARTA,STEPA,
     +            IDENTA,CUNITA,PNTRA,IMNOA,STAT)
      IF (NAXISA.EQ.1) 
     +   CALL STETER(1,'We need a 2-dim image ...')
      IF ((NPIXA(1).EQ.1) .OR. (NPIXA(2).EQ.1))
     +   CALL STETER(1,'We need a 2-dim image ...')
      CALL STDRDR(IMNOA,'LHCUTS',1,4,IAV,CUTS,UNI,NULO,STAT)
      ZCUTS(1) = CUTS(3)
      ZCUTS(2) = CUTS(4)
      RNULL = CUTS(3) - 0.01*(CUTS(4)-CUTS(3))                !null val < min
C 
      R1 = NPIXA(1) - 1.
      R2 = NPIXA(2) - 1.
      KDIFF = 12
      DIM3C = 1
C
C  get name of output frame + plane no.s (or action code)
      CALL STKRDC('OUT_A',1,1,60,IAV,FRAMEB,UNI,NULO,STAT)
      CALL STKRDC('INPUTC',1,1,80,IAV,STR,UNI,NULO,STAT)
C
C  get rotation angle + perspective angle + (scaling size)
      CALL STKRDR('INPUTR',1,4,IAV,RROT,UNI,NULO,STAT)
      IF (STR(1:4).EQ.'zper') THEN
         PLANES(1) = 1
         PLANES(2) = 0
         KNO = 0
         ISCAL = NINT(RROT(3))
         IF (ISCAL.LT.1) 
     +      CALL STETER(1,'Invalid scaling size (should be > 0)...')
         ZCUTS(2) = RROT(4)
         IF (ZCUTS(2).LE.ZCUTS(1)) CALL STETER(1,
     +      'Invalid scale limit (should be > LHCUTS(3))...')
C 
C  get planes to work on
      ELSE IF ((STR(1:1).EQ.'A') .OR. (STR(1:1).EQ.'a')) THEN
         PLANES(1) = -1                    !indicate all planes
         KNO = NPIXA(3) - 1                !no. of planes - 1
      ELSE
         CALL GENCNV(STR,1,20,PLANES,QUOT,STEPC,IAV)
         IF (IAV.LE.0)
     +      CALL STETER(5,'Invalid planes specified ...')
         IF ((PLANES(1).LE.0).OR.(PLANES(1).GT.NPIXA(3)))
     +      CALL STETER(6,'specified plane outside limits... ')
         N = PLANES(1) - 1                 !update pointer
         KNO = IAV - 1                     !no. of planes - 1
         PNTRA = PNTRA + N*NPIXA(1)*NPIXA(2)
         IAV = IAV + 1
         PLANES(IAV) = 0                   !mark the end
      ENDIF
C 
      ANGDEG = RROT(1)
      PCDEG = RROT(2)
C 
      ANGLE = ANGDEG * FACTO
      N = (NPIXA(1) + 1) / 2                  !use center pixel
      PIXROT(1) = N - 1
      N = (NPIXA(2) + 1) / 2                  !use center pixel
      PIXROT(2) = N - 1
C 
      AC = COS(ANGLE)
      AS = SIN(ANGLE)
      IF ((ANGDEG.LT.0.1).OR.(ANGDEG.GT.359.9)) THEN
         NPIXB(1) = NPIXA(1)                   !no rotation
         NPIXB(2) = NPIXA(2)
         STARTB(1) = STARTA(1)
         STARTB(2) = STARTA(2)
         STEPB(1) = STEPA(1)
         STEPB(2) = STEPA(2)
         N1 = 0
C 
         RBUF(1) = 0.
         RBUF(2) = R2
         RBUF(3) = 0.
         RBUF(4) = 0.
         RBUF(5) = R1
         RBUF(6) = 0.
         RBUF(7) = R1
         RBUF(8) = R2
C 
         GOTO 3000
      ELSE
         N1 = 1                                !yes. we do
      ENDIF
C
C  to get size of output frame, rotate corners around lower left corner
C  (assumed = 0,0)
C 
      CALL ROTA1(R1,R2,AC,AS,X1,Y1)         !(NX-1,NY-1)
      CALL ROTA1(0.,R2,AC,AS,X2,Y2)         !(0,NY-1)
      CALL ROTA1(R1,0.,AC,AS,X3,Y3)         !(NX-1,0)
      X4 = 0.
      Y4 = 0.                               !rotation point stays fixed
C
C  get result frame "corners"
      ST(1) = MIN(0.,X1,X2,X3)             !rotated x-start
      EN(1) = MAX(0.,X1,X2,X3)             !rotated x-end
      ST(2) = MIN(0.,Y1,Y2,Y3)             !rotated y-start
      EN(2) = MAX(0.,Y1,Y2,Y3)             !rotated y-end
C
C  from coords. of rotation point determine shift after rotation
      QUOT = 1. - AC
      ROTOFF(1) = PIXROT(1)*QUOT + PIXROT(2)*AS
      ROTOFF(2) = PIXROT(2)*QUOT - PIXROT(1)*AS
      CALL ROTA1(PIXROT(1),PIXROT(2),AC,AS,RROT(1),RROT(2))
C
C  choose corners such, that rotation point is hit ...
      DO 2000, N=1,2
         STEPB(N) = STEPA(N)
         QUOT =  RROT(N) - ST(N)           !distance of fixed p. to rotation p.
         RQUOT = FLOAT(INT(QUOT)) + 1.     !is forced to multiples of steps
         ST(N) = RROT(N) - RQUOT
         QUOT = EN(N) - ST(N)              !distance of start to end point
         RQUOT = FLOAT(INT(QUOT)) + 1.     !in multiples of steps
         EN(N) = ST(N) + RQUOT
         NPIXB(N) = NINT(RQUOT) + 1        !no. of points in new image
2000  CONTINUE
C
C  now update start of rotated image, so that rotation point stays fixed
      RST(1) = ST(1) + ROTOFF(1)
      RST(2) = ST(2) + ROTOFF(2)
      STARTB(1) = STARTA(1) + ( RST(1)*STEPA(1) )      !we work in 0,0 space
      STARTB(2) = STARTA(2) + ( RST(2)*STEPA(2) )
      DO 2200, N=1,7,2                       
         RBUF(N) = RBUF(N) - ST(1)              !relate to new frame
         RBUF(N+1) = RBUF(N+1) - ST(2)
2200  CONTINUE
C
C  create and map intermediate frame
C 
3000  NSIZ = NPIXB(1) * NPIXB(2)
C 
C  do the rotation
      IF (N1.EQ.1) THEN
         IF (DIM3C.EQ.1) THEN
            CALL STFCRE('midpersp',D_R4_FORMAT,F_X_MODE,1,NSIZ,
     +                  IMNOB,STAT)
            CALL STFMAP(IMNOB,F_X_MODE,1,NSIZ,IAV,PNTRB,STAT)
         ENDIF
         CALL ROTA2(MADRID(PNTRA),MADRID(PNTRB),NPIXA,NPIXB,
     +              ST,AC,AS,RNULL)
      ENDIF
C 
C  create result frame
      IF (DIM3C.EQ.1) THEN
         NPIXC(1) = NPIXB(1)
         STEPC(1) = STEPB(1)
         IF (PCDEG.LE.0.1) THEN                 !no tilt at all ...
            N2 = 0
            PC = 1
            NPIXC(2) = NPIXB(2)
         ELSE IF (PCDEG.GT.89.5) THEN           !total side view => single line
            N2 = 2
            NPIXC(2) = 1
            PC = 0
         ELSE
            N2 = 1
            PC = COS(PCDEG * FACTO)
            NPIXC(2) = INT (NPIXB(2) * PC)
            NPERSP = NPIXC(2)
            STEPC(2) = STEPB(2) * PC
         ENDIF
C
C  move corners to world coords.
         DO 4100, N=1,7,2
            RBUF(N) = STARTB(1) + (RBUF(N)*STEPC(1))
            IAV = INT (RBUF(N+1)*PC)
            IF (IAV.GE.NPIXC(2)) IAV = NPIXC(2) - 1
            RBUF(N+1) = STARTB(2) + (IAV*STEPC(2))
4100     CONTINUE
         IF (KNO.GT.0) THEN                      !if more than one plane
            QUOT = STEPC(2) * ((NPERSP+KDIFF)*KNO)
            RBUF(9) = RBUF(2) + QUOT
            RBUF(10) = RBUF(4) + QUOT
            RBUF(11) = RBUF(6) + QUOT
            RBUF(12) = RBUF(8) + QUOT
            RBUF(13) = KNO + 1                   !no. of planes
            RBUF(14) = KDIFF
            RBUF(15) = STEPC(2) * KDIFF
            RBUF(16) = STEPC(2) * (NPERSP+KDIFF)
C 
            NAXISC = 2
            NPIXC(2) = (KNO+1)*NPIXC(2) + KNO*KDIFF
            RQUOT = STARTB(2) + (NPIXC(2)-1)*STEPC(2)         !y-end
            IF (STEPC(2).GT.0.) THEN
               IF (RBUF(9).GT.RQUOT) RBUF(9) = RQUOT
               IF (RBUF(10).GT.RQUOT) RBUF(10) = RQUOT
               IF (RBUF(11).GT.RQUOT) RBUF(11) = RQUOT
               IF (RBUF(12).GT.RQUOT) RBUF(12) = RQUOT
            ELSE
               IF (RBUF(9).LT.RQUOT) RBUF(9) = RQUOT
               IF (RBUF(10).LT.RQUOT) RBUF(10) = RQUOT
               IF (RBUF(11).LT.RQUOT) RBUF(11) = RQUOT
               IF (RBUF(12).LT.RQUOT) RBUF(12) = RQUOT
            ENDIF
         ELSE
            NAXISC = NAXISA
         ENDIF
C 
         CALL STKWRR('OUTPUTR',RBUF,1,20,UNI,STAT)
         IF (STR(1:4).EQ.'zper') THEN
            IDENTA(1:) = 'perspective z-plot of input frame '
            NAXISC = 2
            NPIXC(2) = NPIXC(2)+ISCAL
            NPERSP = NPIXC(2)                     !in case we reset it later on
         ELSE
            IDENTA(1:) = 
     +      'perspective plot of selected planes of input frame '
         ENDIF
         CALL STIPUT(FRAMEB,D_R4_FORMAT,F_O_MODE,F_IMA_TYPE,
     +               NAXISC,NPIXC,STARTB,STEPC,
     +               IDENTA,CUNITA,PNTRC,IMNOC,STAT)
      ENDIF
C
C  and do the perspective rebinning
      IF (N2.EQ.1) THEN                         !real job
         NPIXC(2) = NPERSP                      !reset to original value (3-dim)
         IF (N1.EQ.1) THEN
            IF (STR(1:4).EQ.'zper') THEN
               CALL JPERSP(MADRID(PNTRB),MADRID(PNTRC),
     +                     NPIXB,NPIXC,PC,RNULL,ZCUTS,ISCAL)
               CALL STDWRI(IMNOC,'NPIX',NPIXC(2),2,1,UNI,STAT)
            ELSE
               CALL KPERSP(MADRID(PNTRB),MADRID(PNTRC),
     +                     NPIXB,NPIXC,PC)
            ENDIF
         ELSE
            IF (STR(1:4).EQ.'zper') THEN
               CALL JPERSP(MADRID(PNTRA),MADRID(PNTRC),
     +                     NPIXB,NPIXC,PC,RNULL,ZCUTS,ISCAL)
               CALL STDWRI(IMNOC,'NPIX',NPIXC(2),2,1,UNI,STAT)
            ELSE
               CALL KPERSP(MADRID(PNTRA),MADRID(PNTRC),
     +                     NPIXB,NPIXC,PC)
            ENDIF
         ENDIF
      ELSE IF (N2.EQ.0) THEN                    !just rotated image
         IF (N1.EQ.1) THEN
            CALL COPYF(MADRID(PNTRB),MADRID(PNTRC),NSIZ)
         ELSE
            CALL COPYF(MADRID(PNTRA),MADRID(PNTRC),NSIZ)
         ENDIF
      ELSE                                      !only sideline
         IF (N1.EQ.1) THEN
            CALL COPYF(MADRID(PNTRB),MADRID(PNTRC),NPIXB(1))
         ELSE
            CALL COPYF(MADRID(PNTRA),MADRID(PNTRC),NPIXB(1))
         ENDIF
      ENDIF
C 
C  check for 3-dim case
      DIM3C = DIM3C + 1
      IF (PLANES(1).EQ.-1) THEN
         IF (DIM3C.GT.NPIXA(3)) THEN
            GOTO 9000
         ELSE
            KZ = 1
         ENDIF
      ELSE
         IF (PLANES(DIM3C).EQ.0) THEN
            GOTO 9000
         ELSE
            IF ((PLANES(DIM3C).LE.0).OR.(PLANES(DIM3C).GT.NPIXA(3)))
     +         CALL STETER(6,'specified plane outside limits... ')
            KZ = PLANES(DIM3C) - PLANES(DIM3C-1)
         ENDIF
      ENDIF
      PNTRA = PNTRA + (NPIXA(1)*NPIXA(2))*KZ
      PNTRC = PNTRC + (NPIXC(1) * (NPIXC(2) + KDIFF))
      GOTO 3000
C
9000  CALL STDWRR(IMNOC,'LHCUTS',CUTS,1,4,UNI,STAT)
      CALL STSEPI
      END

      SUBROUTINE ROTA1(X,Y,AC,AS,XOUT,YOUT)
C
      IMPLICIT NONE
C
      REAL     X,Y,AC,AS,XOUT,YOUT
C
      XOUT = X*AC - Y*AS
      YOUT = X*AS + Y*AC
C
      RETURN
      END

      SUBROUTINE KPERSP(A,B,NPIXA,NPIXB,AC)
C
C  K. Banse            920103
C
C  do "backward" perspective
C 
C  XPERS = X
C  YPERS = Y/AC
C
      IMPLICIT NONE
C
      INTEGER      INDXB,KSTX,KY
      INTEGER      NO1,NO3
      INTEGER      NX,NY,SIZEA,XDIMA,YDIMA
      INTEGER      NPIXA(2),NPIXB(2)
C
      REAL         A(*),B(*)
      REAL         AC,YFRAC
C 
      DOUBLE PRECISION  RYAC,ACINV
C
C  init
      XDIMA = NPIXA(1)
      YDIMA = NPIXA(2)
      SIZEA = XDIMA * YDIMA
C
      ACINV = 1.D0 / AC
      INDXB = 0
      RYAC = ACINV
C
C  loop through result lines
      DO 3000, NY=1,NPIXB(2)
         DO 1000, NX=1,NPIXB(1)
            INDXB = INDXB + 1              !loop along result line
            KY = INT(RYAC)
            KSTX = XDIMA*KY                !get 1. pixel in this line - 1
            NO1 = NX + KSTX                !get pixel close to integer part of
            NO3 = NO1 + XDIMA               !get low pixel in next line up
            IF (NO3.GT.SIZEA) THEN          !are we out of grid in y?
               B(INDXB) = A(NO1)
            ELSE
               YFRAC = RYAC - KY
               B(INDXB) = A(NO1) + (YFRAC * (A(NO3) - A(NO1)))
            ENDIF
1000     CONTINUE
         RYAC = RYAC + ACINV
3000  CONTINUE
C 
      RETURN
      END

      SUBROUTINE JPERSP(A,B,NPIXA,NPIXB,AC,ZNULL,FMINMA,ISCAL)
C
C
C  do "backward" z-perspective
C
C  XPERS = X
C  YPERS = Y/AC 
C 
C  Z = YPERS * ISCAL  =>      XPERS,YPERS+n   = Z
C                             XPERS,YPERS+n-1 = ...
C                                  ...
C                             XPERS,YPERS     = Min
C
      IMPLICIT NONE
C
      INTEGER      INDXB,KSTX,KY,ISCAL
      INTEGER      NO1,NO3,N
      INTEGER      NX,NY,SIZEA,XDIMA,YDIMA,XDIMB
      INTEGER      NPIXA(2),NPIXB(2)
      INTEGER      KSCAL,IZ,KNDXB,KK
C
      REAL         A(*),B(*)
      REAL         AC,FMINMA(2),ZNULL
      REAL         YFRAC,RMIN,RMAX
      REAL         Z,DZ,SCALF,CMIN,FF
      REAL         VALU
C
      DOUBLE PRECISION  RYAC,ACINV
C
C  init
      XDIMA = NPIXA(1)
      YDIMA = NPIXA(2)
      SIZEA = XDIMA * YDIMA
      XDIMB = NPIXB(1)
C
      RMIN = FMINMA(1)
      RMAX = FMINMA(2)
      ACINV = 1.D0 / AC
      INDXB = NPIXB(1)*NPIXB(2)
      KSCAL = ISCAL - 1
      SCALF = KSCAL / (RMAX-RMIN)
      CMIN = RMIN*ISCAL
      KK = NPIXB(2)-ISCAL               !reserved space for spikes of last line
C
C  loop through result lines
      DO 300, NY=NPIXB(2),KK+1,-1
         DO 100, NX=1,XDIMB
            B(INDXB) = ZNULL
            INDXB = INDXB - 1              !loop along result line
100      CONTINUE
300   CONTINUE
C 
      RYAC = KK * ACINV
      DO 3000, NY=KK,1,-1
C
         DO 1000, NX=1,XDIMB
            KY = INT(RYAC)
            KSTX = XDIMA*KY                !get 1. pixel in this line - 1
            NO1 = NX + KSTX                !get pixel close to integer part of
            NO3 = NO1 + XDIMA              !get low pixel in next line up
            IF (NO3.GT.SIZEA) THEN         !are we out of grid in y?
               Z = A(NO1)
            ELSE
               YFRAC = RYAC - KY
               Z = A(NO1) + (YFRAC * (A(NO3) - A(NO1)))
            ENDIF
            IF (Z .GT. RMAX) Z = RMAX
C 
C  get height from intensity
            DZ = Z - RMIN
            IZ = NINT(DZ*SCALF)
            IF (IZ .GE. 1) THEN
               B(INDXB) = RMIN
               FF = DZ/IZ
               KNDXB = INDXB + XDIMB
               VALU = FF + RMIN
               DO 800, N=1,IZ
                  B(KNDXB) = VALU
                  VALU = VALU + FF
                  KNDXB = KNDXB + XDIMB
800            CONTINUE
            ELSE
               B(INDXB) = Z
            ENDIF
C
            INDXB = INDXB - 1              !loop along result line
1000     CONTINUE
C
         RYAC = RYAC - ACINV
3000  CONTINUE
C
C  get rid of superfluous lines in the end
      INDXB = NPIXB(1)*NPIXB(2)
      DO 4000, NY=NPIXB(2),KK+1,-1
         DO 3300, NX=1,XDIMB
            IF (B(INDXB) .GT. ZNULL) THEN
               NPIXB(2) = NY
               RETURN
            ENDIF
            INDXB = INDXB - 1
3300     CONTINUE
4000  CONTINUE
C 
      RETURN
      END

      SUBROUTINE ROTA2(A,B,NPIXA,NPIXB,START,AC,AS,ZNULL)
C
C  K. Banse            861029, 880902, 910204
C
C  do "backward" rotation, i.e. solve the system XROT = X*AC - Y*AS
C                                       YROT = X*AS + Y*AC for X,Y
C  to yield X = XROT*AC + YROT*AS
C          Y = YROT*AC - XROT*AS  which takes AC**2 + AS**2 = 1 into account....
C
      IMPLICIT NONE
C
      INTEGER      INDXB,KX,KY,KSTX
      INTEGER      NO1,NO2,NO3,NO4
      INTEGER      NX,NY,SIZEA,XDIMA,YDIMA
      INTEGER      NPIXA(2),NPIXB(2)
C
      REAL         A(*),B(*)
      REAL         AC,AS,ZNULL
      REAL         XT,YT,XFRAC,YFRAC,XLAST,YLAST
      REAL         XF,RX
C
      DOUBLE PRECISION  START(2)
      DOUBLE PRECISION  RYAC,RYAS
C
C  init
      XF = START(1)
      XDIMA = NPIXA(1)
      YDIMA = NPIXA(2)
      XLAST = XDIMA - 1.
      YLAST = YDIMA - 1.
      SIZEA = XDIMA * YDIMA
      INDXB = 0
C
      RYAS = START(2) * AS                 !init RYAS,RYAC according to start-y
      RYAC = START(2) * AC
C 
C  loop through result lines
      DO 3000, NY=1,NPIXB(2)
         RX = XF                           !init RX to start-x
C
         DO 1000, NX=1,NPIXB(1)
            INDXB = INDXB + 1              !loop along result line
            XT = RX*AC + RYAS
            IF ((XT.LT.0.).OR.(XT.GT.XLAST)) THEN
               B(INDXB) = ZNULL
               GOTO 1000
            ENDIF
            YT = RYAC - RX*AS
            IF ((YT.LT.0.).OR.(YT.GT.YLAST)) THEN
               B(INDXB) = ZNULL
               GOTO 1000
            ENDIF
C
C  interpolate...
            XT = XT + 1.                  !adjust 0,0 to 1,1 ...
            YT = YT + 1.
            KX = INT(XT)
            KY = INT(YT)
            KSTX = XDIMA*(KY-1)          !get 1. pixel in this line - 1
            NO1 = KX + KSTX          !get pixel close to int. part of real pixel
C
            NO2 = NO1 + 1                  !get next pixel in x-direction
CC            IF ((NO2-KSTX).GT.XDIMA) THEN  !are we out of grid in x?
            IF (KX.GE.XDIMA) THEN          !are we out of grid in x?
               IF (NO2.GT.SIZEA) THEN      !also out in y?
                  B(INDXB) = A(NO1)        !yes.
               ELSE
                  NO3 = NO1 + XDIMA        !no.
                  YFRAC = YT - KY
                  B(INDXB) = A(NO1) + ( YFRAC * (A(NO3) - A(NO1)) )
               ENDIF
            ELSE
               XFRAC = XT - KX
               NO3 = NO1 + XDIMA               !get low pixel in next line up
               IF (NO3.GT.SIZEA) THEN          !are we out of grid in y?
                  B(INDXB) = A(NO1) + ( XFRAC * (A(NO2) - A(NO1)) )
               ELSE
                  NO4 = NO3 + 1
                  YFRAC = YT - KY
                  B(INDXB) = A(NO1) +
     +              XFRAC * (A(NO2) - A(NO1)) +
     +              YFRAC * (A(NO3) - A(NO1)) +
     +              XFRAC * YFRAC * (A(NO1) - A(NO2) - A(NO3) + A(NO4))
               ENDIF
            ENDIF
C
1000     RX = RX + 1.0                        !move to next x-coord
C
         RYAS = RYAS + AS                     !move to next y-coord.
         RYAC = RYAC + AC       
3000  CONTINUE
C 
      RETURN
      END
