	SUBROUTINE SAOLOAD(ARRAY,NCOLS,NROWS,IXFRAME,IYFRAME,
	1BRIGHTNESS_MIN,BRIGHTNESS_MAX,ARRAY_NAME,NPICTURE,MODE)
C
C  Note:  This is the UNIX version.
C
C       This subroutine sends data from an array to SAOimage.
C
C			Donald H. Gudehus, July, 1994
C			Version 1U, D. Gudehus, September 15, 1994
C			Changed code to work under UNIX
C                       Version 2, D. Gudehus, September 18, 1994
C                       Corrected setting of NPIC from NPICTURE
C			Version 3, D. Gudehus, October 29, 1994
C			Corrected index for colors
C			Version 4, D. Gudehus, June 9, 1995
C			Allowed for ARRAY_NAME to have spaces
C			Version 5, D. Gudehus, March 21, 2005
C			Adjusted BUFFER_TEMP for different endian
C			architectures.  This array is available through
C			the include file SAOFACT.FOR.
C			Version 6, D. Gudehus, July 25, 2006
C			Incorporated new saofacts.for
C			Version 7, D. Gudehus, Aug. 24, 2006
C			Added SYS_ENDIAN common block
C			Version 8, D. Gudehus, Sept. 2, 2006
C			Adjusted AMIN_SAO, AMAX_SAO, and IBUFFER_TEMP_SAO
C			for better display of intensity
C
C	ARRAY		(C)	The array containing the data to be loaded
C				into SAOimage
C	NCOLS		(C)	The number of columns in the image to be 
C				loaded, and the first dimension of ARRAY.
C	NROWS		(C)	The number of rows in the image to be 
C				loaded, and the second dimension of ARRAY.
C	IXFRAME		(C)	The X location on the frame of the lower left
C				corner of the array.  The frame's X coordinate
C				system begins at 0 at the left.
C	IYFRAME		(C)	The Y location on the frame of the lower left
C				corner of the array.  The frame's Y coordinate
C				system begins at 0 at the top.
C	BRIGHTNESS_MIN	(C)	The minimum intensity level in the image
C				which is desired to be represented in 
C				pseudocolor.  Values less than or equal to
C				this will all be assigned the same color.
C	BRIGHTNESS_MAX	(C)	The maximum intensity level in the image
C				which is desired to be represented in 
C				pseudocolor.  Values greater than or equal to
C				this will all be assigned the same color.
C	ARRAY_NAME	(C)	The name of the array or picture.  This will
C				be displayed on SAOimage.
C	NPICTURE	(C)	The number of the picture.  Since SAOimage
C				supports loading up to 16 independent pictures
C				the number must be specified.
C	MODE		(C)	The mode for loading an image.  If MODE=0
C				the entire frame buffer is used, and several
C				lines are loaded at a time.  If MODE=1
C				only one line at a time is loaded.  Although
C				this is slower, the line length can be less
C				the buffer width, and a picture can be
C				placed next to an existing picture without
C				that picture being erased.
C
	CHARACTER*(*) ARRAY_NAME
	REAL ARRAY(NCOLS,NROWS)
C
	INCLUDE 'saofacts.for' !  UNIX likes lower case
C
	CHARACTER*1 SYSTEM_ENDIAN
	COMMON /SYS_ENDIAN/ SYSTEM_ENDIAN
C
	INTEGER*2 I2,J2
C
	NFRAME_SAO=0 !  For now, there is only one frame
	NPIC_SAO=NPICTURE
	NPTSX_SAO(NPIC_SAO)=NCOLS
	NPTSY_SAO(NPIC_SAO)=NROWS
	IMIN=1 !  Starting location in array
	JMIN=1
	IMAX=NCOLS
	JMAX=NROWS
	TV_FILENAME(NPIC_SAO)=ARRAY_NAME
	INPIC_SAO=NPIC_SAO
C  Make sure XLOC_SAO and YLOC_SAO are within the frame
	XLOC_SAO(NPIC_SAO)=MIN(MAXFB_COLS_SAO-1,MAX(0,IXFRAME))
	YLOC_SAO(NPIC_SAO)=MIN(MAXFB_ROWS_SAO-1,MAX(0,IYFRAME))
C  Make sure enough room is available in the frame and if not, try to correct
C  XLOC_SAO by shifting left and lining up the right sides
	XLOC_SAO(NPIC_SAO)=MIN(MAXFB_COLS_SAO-NCOLS,XLOC_SAO(NPIC_SAO))
C  Make sure enough room is available in the frame and if not, try to correct
C  YLOC_SAO by shifting down and lining up the top sides
	YLOC_SAO(NPIC_SAO)=MAX(NROWS-1,YLOC_SAO(NPIC_SAO))
	IF (XLOC_SAO(NPIC_SAO).NE.IXFRAME.OR.YLOC_SAO(NPIC_SAO).NE.IYFRAME) 
	1CALL MESSAGE('Starting location in frame was changed')
C  Check that the possibly corrected XLOC_SAO is not off the left edge or that
C  the possibly corrected YLOC_SAO is not off the bottom edge of the 
C  frame
	IF (XLOC_SAO(NPIC_SAO).LT.0.OR.YLOC_SAO(NPIC_SAO).GT.
	1MAXFB_ROWS_SAO-1)
	1 CALL ERROR(-2,'Buffer not wide enough for image;  try again')
	IXLOC=XLOC_SAO(NPIC_SAO) !  Converts to I4
        IYLOC=YLOC_SAO(NPIC_SAO) !  Converts to I4
C  Compute the frame dependent intensity scale factor.  200 distinct values
C  can be displayed from the color lookup table;  2 values at the ends
C  of the range will display < and > before the values.
C  Testing of this algorithm can be done by loading tst0001.fits which 
C  contains integer values from 0 to 255.  Choose BRIGHTNESS_MIN=0 and
C  BRIGHTNESS_MAX=199 for display of the integer values.
	SCF_SAO(NFRAME_SAO)=(BRIGHTNESS_MAX-BRIGHTNESS_MIN)/199.0
C  Compute the values to set up SAOimage to define the clipping limits.
	AMIN_SAO(NFRAME_SAO)=BRIGHTNESS_MIN+SCF_SAO(NFRAME_SAO)
	AMAX_SAO(NFRAME_SAO)=BRIGHTNESS_MAX+SCF_SAO(NFRAME_SAO)
C
C  Prepare to load the array into frame NFRAME_SAO
C
C  Set up the new WCS header information
	I=LEN(ARRAY_NAME)
	DO WHILE(ARRAY_NAME(I:I).NE.' '.AND.I.GE.1)
	  I=I-1
	END DO
	LF=MAX(I,1) !  Length of file name
	IBUFFER_SAO(1)='40000'O !  PACKED and IMC_SAMPLE
	IBUFFER_SAO(2)=-(LF+59)
	IBUFFER_SAO(3)=17 !  imhead.subunit = WCS (World coordinate system)
        IBUFFER_SAO(4)=0
        IBUFFER_SAO(5)=0
        IBUFFER_SAO(6)=0
        IBUFFER_SAO(7)=1 !  Frame number
        IBUFFER_SAO(8)=IFB_SAO-1 !  Frame buffer configuration - 1
	CALL IMTOOLCHECKSUM(IBUFFER_SAO)
	NBYTES=16
C  Send the WCS header
	CALL SI_WRITE(BUFFER_SAO,NBYTES)
C  Set up the WCS data packet
	CBUFFER_SAO(1:LF)=ARRAY_NAME(1:LF)
	BUFFER_SAO(LF+1)=10
	CBUFFER_SAO(LF+2:LF+14)='1. 0. 0. -1. ' !  xx yx xy yy
	ENCODE (7,1000,CBUFFER_SAO(LF+15:LF+21)) IMIN+0.5-IXLOC !  xo =
	!  X Coordinate at left edge of buffer;  0.5 added to conform with 
	!  corner of pixel being x.0, y.0.
1000	FORMAT(F7.1)
	CBUFFER_SAO(LF+22:LF+22)=' '
	ENCODE (7,1000,CBUFFER_SAO(LF+23:LF+29)) IYLOC+JMIN+0.5 !  yo =
	!  Y Coordinate at top edge of buffer;  0.5 added to conform with 
	!  corner of pixel being x.0, y.0.
	CBUFFER_SAO(LF+30:LF+30)=' '
	ENCODE (12,2000,CBUFFER_SAO(LF+31:LF+42)) AMIN_SAO(NFRAME_SAO) !  low
2000	FORMAT(E12.5)
	CBUFFER_SAO(LF+43:LF+43)=' '
	ENCODE (12,2000,CBUFFER_SAO(LF+44:LF+55)) AMAX_SAO(NFRAME_SAO) !  high
	CBUFFER_SAO(LF+56:LF+57)=' 1' !  w_type (=linear)
	BUFFER_SAO(LF+58)=10
	BUFFER_SAO(LF+59)=0
	NBYTES=LF+59
C  Send the WCS data packet
	CALL SI_WRITE(BUFFER_SAO,NBYTES)
C  In IRAF at this point, the LUT header is sent.  Don't need it in MIIPS.
	IF (MODE.EQ.0) THEN !  A single map is loaded, many rows at a time
			    !  for highest speed
	  DO I=1,MAXNBYTES_SAO
	    BUFFER_SAO(I)=0.0
	  END DO
	  IOFF=IMIN-1
	  JOFF=JMIN+IYLOC
C  Get the initial row in the map to be read
	  JNEXT=JMIN
C  Find out how many rows can be sent at a time.
	  NROWS_AT_A_TIME=MAXNBYTES_SAO/MAXFB_COLS_SAO
C  Start loading several rows at a time into the buffer.  The full width
C  of the display buffer is used.
	  NROWS_REMAINING=NROWS
	  DO WHILE(NROWS_REMAINING.GT.0)
C  Make sure this is not more than the remaining number of rows to be displayed
	    NROWS_AT_A_TIME=MIN(NROWS_REMAINING,NROWS_AT_A_TIME)
	    NBYTES=MAXFB_COLS_SAO*NROWS_AT_A_TIME
	    IHDBUFFER_SAO(1)='71000'O !  = 29184
	    IHDBUFFER_SAO(2)=-NBYTES !  imhead.thingct
	    IHDBUFFER_SAO(3)=1 !  imhead.subunit = MEMORY
	    IHDBUFFER_SAO(4)=0
	    I2=0 !  We always load from the beginning of the buffer
            IHDBUFFER_SAO(5)=IOR(I2,'100000'O) !  x
	    JNEXT_PLUS_DEL=JNEXT+NROWS_AT_A_TIME-1
	    J2=JOFF-JNEXT_PLUS_DEL
	    IHDBUFFER_SAO(6)=IOR(J2,'100000'O) !  y
	    IHDBUFFER_SAO(7)=1
	    IHDBUFFER_SAO(8)=IOR(63,'300'O)
	    CALL IMTOOLCHECKSUM(IHDBUFFER_SAO)
	    NBYTES_HEADER=16
	    CALL SI_WRITE(HDBUFFER_SAO,NBYTES_HEADER)
	    DO J=JNEXT,JNEXT_PLUS_DEL
C  Start the loop to increment the column number in the array
	      DO I=IMIN,IMAX
		IBUFFER_TEMP_SAO=
	1       NINT((ARRAY(I,J)-BRIGHTNESS_MIN)/SCF_SAO(NFRAME_SAO))
C  Don't let any address be too small
	        IF (IBUFFER_TEMP_SAO.LT.0) IBUFFER_TEMP_SAO=0
C  Address 200 is reserved for values >= the upper limit.  Don't let any
C  addresses be larger than this.
	        IF (IBUFFER_TEMP_SAO.GT.200) IBUFFER_TEMP_SAO=200
	        IF (SYSTEM_ENDIAN.EQ.'L') THEN
	          BUFFER_SAO(I-IMIN+IXLOC+1+(JNEXT_PLUS_DEL-J)*
	1       MAXFB_COLS_SAO)=BUFFER_TEMP_SAO(1)
	        ELSE !  Big endian
	          BUFFER_SAO(I-IMIN+IXLOC+1+(JNEXT_PLUS_DEL-J)*
	1         MAXFB_COLS_SAO)=BUFFER_TEMP_SAO(2)
	        END IF
	      END DO
	    END DO
C  Send the rows of data to SAOimage
	    CALL SI_WRITE(BUFFER_SAO,NBYTES)
C  Get the next row in the map to be read
	    JNEXT=JNEXT+NROWS_AT_A_TIME
	    NROWS_REMAINING=NROWS_REMAINING-NROWS_AT_A_TIME
	  END DO
	ELSE IF (MODE.EQ.1) THEN !  One row at a time.  Slower, but allows
C				 !  multiple images to be loaded
C  Start the loop to increment the row number in the array
	  IOFF=IMIN-1
	  JOFF=JMIN+IYLOC
C  We use the auxilliary buffer so that it doesn't have to be reloaded every
C  row.
	  IHDBUFFER_SAO(1)='71000'O !  = 29184
	  IHDBUFFER_SAO(2)=-NCOLS !  imhead.thingct
	  IHDBUFFER_SAO(3)=1 !  imhead.subunit = MEMORY
	  IHDBUFFER_SAO(4)=0
	  I2=IXLOC
          IHDBUFFER_SAO(5)=IOR(I2,'100000'O) !  x
	  IHDBUFFER_SAO(7)=1
	  IHDBUFFER_SAO(8)=IOR(63,'300'O)
	  DO J=JMIN,JMAX
	    J2=JOFF-J
	    IHDBUFFER_SAO(6)=IOR(J2,'100000'O) !  y
	    CALL IMTOOLCHECKSUM(IHDBUFFER_SAO)
	    NBYTES=16
	    CALL SI_WRITE(HDBUFFER_SAO,NBYTES)
	    NBYTES=MIN(MAXFB_COLS_SAO-I2,NCOLS)
C  Start the loop to increment the column number in the array
	    DO I=IMIN,IMAX
	      IBUFFER_TEMP_SAO=
	1     (ARRAY(I,J)-BRIGHTNESS_MIN)/SCF_SAO(NFRAME_SAO)
	      IF (IBUFFER_TEMP_SAO.LT.0) IBUFFER_TEMP_SAO=0
	      IF (IBUFFER_TEMP_SAO.GT.200) IBUFFER_TEMP_SAO=200
C  Take note of which endian this system is
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        BUFFER_SAO(I-IOFF)=BUFFER_TEMP_SAO(1)
	      ELSE !  Big endian
	        BUFFER_SAO(I-IOFF)=BUFFER_TEMP_SAO(2)
	      END IF
	    END DO
C  Send the row of data to SAOimage
	    CALL SI_WRITE(BUFFER_SAO,NBYTES)
	  END DO
	END IF
C  Exit
	RETURN
	END
