C
C Subroutines to linearly interpolate discrete colour maps in RGB space
C
C Version: 5.30
C Date: 1999, April 7
C
C Coded by: Ludek Klimes
C     Department of Geophysics, Charles University Prague,
C     Ke Karlovu 3, 121 16 Praha 2, Czech Republic,
C     E-mail: klimes@seis.karlov.mff.cuni.cz
C
C.......................................................................
C
C                                                    
C Description of the data file specifying the colour map:
C (1) N0,N1,N2,...,NK,/
C     Colour map is specified on the (K+1)-dimensional rectangular grid
C     of N0*N1*N2*...*Nk points situated within (K+1)-dimensional unit
C     cube.
C (2) (K+1) times (2.1), for J=0,1,...,K
C (2.1) CI(1),CI(2),...,CI(NJ)
C     Grid coordinates.  Must be 0.LE.CI(1).LE.CI(2).LE. ... .LE.CI(NI).
C (3) R(I0,I1,...,IK),G(I0,I1,...,IK),B(I0,I1,...,IK) for I0=1,2,...,N0;
C     for I1=1,2,...,N1; ...; for IK=1,2,...,NK
C     RGB components of grid values of the colour map.  The colours are
C     linearly (bilinearly, trilinearly, ...) interpolated between the
C     gridpoints and  are constant between the sides of the unit cube
C     and the nearest gridpoint.
C (4) (K+1) times (2.1), for J=0,1,...,K
C (4.1) REPL,REPR,CREF,VREFNORM
C     REPL,REPR... Colours of interval (0,1) are cyclically repeated
C             along the interval (-REPL,1+REPR).  Colours left to -REPL
C             are constant, colours right to 1+REPR are constant.
C     CREF... Default reference colour.  It may be changed by the input
C             SEP file using parameters CREF, CREF1, CREF2, ...
C     VREFNORM... Determines the default reference value.  The reference
C             value may be changed by the input SEP file using
C             parameters VREF, VREF1, VREF2, ...
C For an example refer to colour map hsv.dat
C
C                                                     
C Data file 'SEP' has the form of the SEP (Stanford Exploration Project)
C parameter file:
C     All the data are specified in the form of PARAMETER=VALUE, e.g.
C     N1=50, with PARAMETER directly preceding = without intervening
C     spaces and with VALUE directly following = without intervening
C     spaces.  The PARAMETER=VALUE couple must be delimited by a space
C     or comma from both sides.
C     The PARAMETER string is not case-sensitive.
C     PARAMETER= followed by a space resets the default parameter value.
C     All other text in the input files is ignored.  The file thus may
C     contain unused data or comments without leading comment character.
C     Everything between comment character # and the end of the
C     respective line is ignored, too.
C     The PARAMETER=VALUE couples may be specified in any order.
C     The last appearance takes precedence.
C Data specifying the colour scale:
C     VADD=real... Controls the default value of VPER.
C             Default: VADD=0.
C     VMUL=real... Controls the default value of VPER.
C             Default: VMUL=1.
C     VPER=real... Period of values corresponding to one period in the
C             colour map.
C             Default: VPER=VMUL*(GMAX-GMIN+VADD),
C             where GMIN and GMAX are the minimum and maximum values to
C             be displayed in colours.
C     VREF=real... Reference value.  It will be displayed in the
C             reference colour.
C             Default: VREF=GMIN+(GMAX-GMIN)*VREFNORM,
C             where VREFNORM is taken from the colour map file.
C             For COLORS='hsv.dat', default VREF=GMIN.
C     CREF=real...
C             Default value is taken from the colour map file.
C             For COLORS='hsv.dat', default CREF=0.666667 (blue).
C     VADD1=real, VADD2=real, ..., VMUL1=real, VMUL2=real, ...,
C     VPER1=real, VPER2=real, ..., VREF1=real, VREF2=real, ...,
C     CREF1=real, CREF2=real, etc... Analogous to VADD, VMUL, VPER, VREF
C             and CREF for multidimensional colour maps.
C             Default values are also analogous.
C             For COLORS='hsv.dat' (three-dimensional colour map),
C             defaults are determined by VREFNORM1=1., VREFNORM2=1.,
C             CREF1=1. (maximum saturation), CREF2=1. (maximum
C             brightness).
C
C=======================================================================
C
      SUBROUTINE COLOR1(LU,MRAM,IRAM,RAM,NVALUE,VALMIN,VALMAX)
C
      INTEGER LU,MRAM,IRAM(0:MRAM-1),NVALUE
      REAL RAM(0:MRAM-1),VALMIN(NVALUE),VALMAX(NVALUE)
C
C-----------------------------------------------------------------------
C
C     External functions and subroutines:
      EXTERNAL RSEP3T,RSEP3R,ERROR
C
C     Storage in array (I)RAM:
C     IRAM(0)=K... Dimensionality of the colour map.
C     IRAM(1:K)=(L1,L2,...,LK)... Last indices of the grid coordinates
C             of the colour map.  L0=K, L(i)=L(i-1)+N(i) where
C             N1,N2,...,NK are the numbers of gridpoints of the colour
C             map.
C     RAM(K+1:LK)... Grid coordinates.
C     RAM(LK+1:LK+3*N1*N2*...*NK)... Gridpoint RGB colours.
C     RAM(LK+3*N1*N2*...*NK+1:LK+3*N1*N2*...*NK+NREF*K)... For each grid
C             coordinate: the left and right colour repetitions, the
C             reference colour, the reference normalized value switched
C             into the reference value, the period of values, auxiliary
C             storage locations.
C
C.......................................................................
C
      CHARACTER*80 FILE
      CHARACTER*5  TEXT
      REAL VADD,VMUL,VPER,VREF,CREF
      INTEGER NGRID,NREF,I1,I2,I
      PARAMETER (NREF=8)
C
C     NGRID=LK+3*N1*N2*...*NK... Location of the last grid colour in
C             array RAM.
C     NREF... Number of reference values for each grid coordinate.
C
C.......................................................................
C
      IF(10.GT.MRAM-1) THEN
C       COLORS-01
        CALL ERROR('COLORS-01: Too small array RAM')
      END IF
      CALL RSEP3T('COLORS',FILE,'hsv.dat' )
      OPEN(LU,FILE=FILE)
      DO 11 I=1,10
        IRAM(I)=0
   11 CONTINUE
      READ(LU,*) (IRAM(I),I=1,10)
      NGRID=1
      DO 12 I=1,10
        IF(IRAM(I).LE.0) THEN
          IRAM(0)=I-1
          GO TO 13
        END IF
        NGRID=NGRID*IRAM(I)
   12 CONTINUE
C       COLORS-02
        CALL ERROR('COLORS-02: More than 9 colour coordinates')
   13 CONTINUE
      DO 14 I=1,IRAM(0)
        IRAM(I)=IRAM(I-1)+IRAM(I)
   14 CONTINUE
      NGRID=IRAM(IRAM(0))+3*NGRID
      IF(NGRID+NREF*IRAM(0).GT.MRAM-1) THEN
C       COLORS-03
        CALL ERROR('COLORS-03: Too small array RAM')
      END IF
C     Reading grid coordinates
      DO 15 I2=1,IRAM(0)
        READ(LU,*) (RAM(I1),I1=IRAM(I2-1)+1,IRAM(I2))
   15 CONTINUE
C     Reading grid RGB values
      READ(LU,*) (RAM(I1),I1=IRAM(IRAM(0))+1,NGRID)
C     Reading repetitions, reference colours and reference values
      DO 17 I2=NGRID,NGRID+NREF*(IRAM(0)-1),NREF
        READ(LU,*) (RAM(I1),I1=I2+1,I2+4)
   17 CONTINUE
C
      TEXT=' '
      DO 21 I2=1,MIN0(IRAM(0),NVALUE)
        I=NGRID+NREF*(I2-1)
        IF(I2.GT.1) THEN
          TEXT(5:5)=CHAR(ICHAR('0')+I2-1)
        END IF
        TEXT(1:4)='CREF'
        CREF=RAM(I+3)
        CALL RSEP3R(TEXT,RAM(I+3),CREF)
        TEXT(1:4)='VREF'
        VREF=VALMIN(I2)+(VALMAX(I2)-VALMIN(I2))*RAM(I+4)
        CALL RSEP3R(TEXT,RAM(I+4),VREF)
        TEXT(1:4)='VADD'
        CALL RSEP3R(TEXT,VADD,0.)
        TEXT(1:4)='VMUL'
        CALL RSEP3R(TEXT,VMUL,1.)
        TEXT(1:4)='VPER'
        VPER=(VALMAX(I2)-VALMIN(I2)+VADD)*VMUL
        CALL RSEP3R(TEXT,RAM(I+5),VPER)
   21 CONTINUE
      DO 22 I2=MIN0(IRAM(0),NVALUE)+1,IRAM(0)
        I=NGRID+NREF*(I2-1)
        IF(I2.GT.1) THEN
          TEXT(5:5)=CHAR(ICHAR('0')+I2-1)
        END IF
        TEXT(1:4)='CREF'
        CREF=RAM(I+3)
        CALL RSEP3R(TEXT,RAM(I+3),CREF)
   22 CONTINUE
      RETURN
      END
C
C=======================================================================
C
      SUBROUTINE COLOR2(MRAM,IRAM,RAM,NVALUE,VALUE,R,G,B)
C
      INTEGER MRAM,IRAM(0:MRAM-1),NVALUE
      REAL RAM(0:MRAM-1),VALUE(NVALUE),R,G,B
C
C-----------------------------------------------------------------------
C
      REAL VPER,VREF,CREF,COLOR,W
      INTEGER NREF,NGRID,IGRID,I1,I2,I,J,N
      PARAMETER (NREF=8)
C
C     NREF... Number of reference values for each grid coordinate.
C     NGRID...Location of the last grid colour in array RAM.
C
C.......................................................................
C
C     Index of the grid origin = initial index of the cube origin
      IGRID=IRAM(IRAM(0))
C     Index of the last grid value
      NGRID=1
      DO 11 I=1,IRAM(0)
        NGRID=NGRID*(IRAM(I)-IRAM(I-1))
   11 CONTINUE
      NGRID=IGRID+3*NGRID
C
      N=3
C     N is the shift between indices of neighbouring gridpoints
      DO 39 I2=1,IRAM(0)
        I=NGRID+NREF*(I2-1)
        CREF=RAM(I+3)
        VREF=RAM(I+4)
        VPER=RAM(I+5)
        IF(I2.LE.NVALUE) THEN
          COLOR=(VALUE(I2)-VREF)/VPER+CREF
        ELSE
          COLOR=CREF
        END IF
        COLOR=AMAX1(COLOR,  -RAM(I+1))
        COLOR=AMIN1(COLOR,1.+RAM(I+2))
        IF(COLOR.LT.0.) THEN
          COLOR=COLOR-AINT(COLOR)+1.
        ELSE IF(COLOR.GT.1.) THEN
          COLOR=COLOR-AINT(COLOR)
          IF(COLOR.LE.0.) THEN
            COLOR=1.
          END IF
        END IF
        DO 31 I1=IRAM(I2-1)+1,IRAM(I2)
          IF(COLOR.LE.RAM(I1)) THEN
C           Colour is located left to the grid coordinate RAM(I1)
            IF(I1.LE.IRAM(I2-1)+1) THEN
              RAM(I+7)=1.
              RAM(I+8)=0.
              J=0
            ELSE
              J=I1-IRAM(I2-1)-2
              RAM(I+8)=(COLOR-RAM(I1-1))/(RAM(I1)-RAM(I1-1))
              RAM(I+7)=1.-RAM(I+8)
            END IF
            GO TO 32
          END IF
   31   CONTINUE
        J=IRAM(I2)-IRAM(I2-1)-2
        RAM(I+7)=0.
        RAM(I+8)=1.
   32   CONTINUE
        IGRID=IGRID+N*J
        IRAM(I+6)=N
        N=N*(IRAM(I2)-IRAM(I2-1))
   39 CONTINUE
C
      R=0.
      G=0.
      B=0.
C     Loop over the vertices of the IRAM(0)-dimensional cube:
      DO 49 I2=0,2**IRAM(0)-1
        N=IGRID
        W=1.
        J=I2
        DO 45 I1=0,IRAM(0)-1
          I=MOD(J,2)
          J=J/2
          N=N+I*IRAM(NGRID+NREF*I1+6)
          W=W*RAM(NGRID+NREF*I1+7+I)
   45   CONTINUE
        R=R+W*RAM(N+1)
        G=G+W*RAM(N+2)
        B=B+W*RAM(N+3)
   49 CONTINUE
      RETURN
      END
C
C=======================================================================
C
      SUBROUTINE COLOR3(MRAM,IRAM,RAM,NVALUE,IREF,IRGB)
C
      INTEGER MRAM,IRAM(0:MRAM-1),NVALUE,IREF,IRGB
      REAL RAM(0:MRAM-1)
C
C     IREF... Index of CREF in array RAM:
C             RAM(IREF  )=CREF,  RAM(IREF+1)=VREF,  RAM(IREF+2)=VPER,
C             RAM(IREF+8)=CREF1, RAM(IREF+9)=VREF1, RAM(IREF+10)=VPER1,
C             etc.
C     IRGB... Index of the first output grid value in array RAM:
C             RAM(IREF  )=CREF,  RAM(IREF+1)=VREF,  RAM(IREF+2)=VPER,
C             RAM(IREF+8)=CREF1, RAM(IREF+9)=VREF1, RAM(IREF+10)=VPER1,
C             etc.
C
C-----------------------------------------------------------------------
C
      INTEGER NREF,I1,I2,I,N
      PARAMETER (NREF=8)
C
C     NREF... Number of reference values for each grid coordinate.
C
C.......................................................................
C
C     Index of the first reference value:
      IREF=1
      DO 11 I1=1,IRAM(0)
        IREF=IREF*(IRAM(I1)-IRAM(I1-1))
   11 CONTINUE
      IREF=IRAM(IRAM(0))+3*IREF+3
C
C     Index of the first output grid value:
      IRGB=IREF-2+NREF*IRAM(0)
C
      N=1
      DO 21 I1=1,NVALUE
        N=N*(IRAM(I1)-IRAM(I1-1))
   21 CONTINUE
      IF(IRGB+3*N+NVALUE.GT.MRAM) THEN
C       COLORS-04
        CALL ERROR('COLORS-04: Too small array RAM')
      END IF
      DO 29 I2=0,N-1
        I=I2
        DO 28 I1=0,NVALUE-1
          RAM(IRGB+3*N+I1)=(RAM(IRAM(I1)+MOD(I,IRAM(I1+1)-IRAM(I1))+1)
     *                -RAM(IREF+8*I1))*RAM(IREF+8*I1+2)+RAM(IREF+8*I1+1)
          I=I/(IRAM(I1+1)-IRAM(I1))
   28   CONTINUE
        CALL COLOR2(MRAM,IRAM(0),RAM(0),NVALUE,RAM(IRGB+3*N),
     *                 RAM(IRGB+3*I2),RAM(IRGB+3*I2+1),RAM(IRGB+3*I2+2))
   29 CONTINUE
      RETURN
      END
C
C=======================================================================
C