subroutine read_allmap(fd,array,nsize,nfill,bval,error)
  use gildas_def
  use gbl_message
  use gfits_interfaces
  use gfits_buf
  use gfits_types
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  ! Read a complete data set from FITS file.
  ! The code cannot be used by pieces. However, avoiding the fits_flush
  ! call at the beginning would make that possible.
  !
  ! Floating point values are read "as is". In particular NaN are
  ! transmitted without change, except for VAX which does not support
  ! NaN: in this case they are replaced by the 'bval' value passed here.
  !---------------------------------------------------------------------
  type(gfits_hdesc_t),       intent(in)    :: fd            !
  integer(kind=size_length), intent(in)    :: nsize         ! Size of array to read
  real(kind=4),              intent(out)   :: array(nsize)  ! Data array
  integer(kind=size_length), intent(out)   :: nfill         ! Number of items effectively read
  real(kind=4),              intent(in)    :: bval          ! Blanking value
  logical,                   intent(inout) :: error         ! Logical error flag
  ! Local
  integer(kind=size_length) :: nbyt
  character(len=message_length) :: mess
  !
100 nbyt = 2880
  call gfits_getbuf(buffer,nbyt,error)
  if ((nbyt.eq.0).or.error) then
    call gfits_message(seve%e,'READ','Error reading FITS file')
    error = .true.
    return
  endif
  if (fd%nbit.eq.8) then
    call byte_to_real(buffer,nbyt,array,nsize,nfill,fd%bscal,fd%bzero)
  elseif (fd%nbit.eq.16) then
    nbyt = nbyt/2
    call int2_to_real(buffer,nbyt,array,nsize,nfill,fd%bscal,fd%bzero)
  elseif (fd%nbit.eq.32) then
    nbyt = nbyt/4
    call int4_to_real(buffer,nbyt,array,nsize,nfill,fd%bscal,fd%bzero)
  elseif (fd%nbit.eq.-32) then
    nbyt = nbyt/4
    call ieee32_to_real(buffer,nbyt,array,nsize,nfill,fd%bscal,fd%bzero,bval)
  elseif (fd%nbit.eq.-64) then
    ! For the time being, degrade double precision FITS to single precision.
    nbyt = nbyt/8
    call ieee64_to_real(buffer,nbyt,array,nsize,nfill,fd%bscal,fd%bzero,bval)
  else
    write(mess,*) 'BITPIX = ',fd%nbit,' not yet supported'
    call gfits_message(seve%e,'FITS',mess)
    error = .true.
    return
  endif
  if (nfill.lt.nsize) goto 100
end subroutine read_allmap
!
subroutine read_subset(fd,array,nsize,odim,iblc,itrc,error,bval)
  use gbl_message
  use image_def  ! for gdf_maxdims...
  use gfits_interfaces
  use gfits_types
  !---------------------------------------------------------------------
  ! @ no-interface (because of argument type mismatch)
  ! (Reasonably) efficient (but not optimal) way to read a subset of a
  ! FITS file:
  !      1) First define the smallest contiguous subset containing
  !         the desired result
  !      2) Read it at once...
  !      3) Extract the result
  !---------------------------------------------------------------------
  type(gfits_hdesc_t),        intent(inout) :: fd                 !
  integer(kind=size_length),  intent(in)    :: nsize              ! Size of array to read
  real(kind=4),               intent(out)   :: array(nsize)       ! Data array
  integer(kind=index_length), intent(in)    :: odim(gdf_maxdims)  ! Array shape
  integer(kind=index_length), intent(in)    :: iblc(gdf_maxdims)  ! Bottom Left Corner
  integer(kind=index_length), intent(in)    :: itrc(gdf_maxdims)  ! Top Left Corner
  logical,                    intent(inout) :: error              ! Logical error flag
  real(kind=4),               intent(in)    :: bval               ! Blanking value
  !
  ! Local
  integer(kind=size_length) :: nfill,ndata, ioffs
  integer(kind=index_length) :: jblc(gdf_maxdims), jtrc(gdf_maxdims), inof(gdf_maxdims), &
    dimin(gdf_maxdims), dimou(gdf_maxdims)
  integer :: ndim, i, j, ier
  real, allocatable :: myarray(:)
  !
  ! 1) Define smallest contiguous containing subset
  ndim = gdf_maxdims
  do i=1,ndim
    jblc(i) = max(iblc(i),1)
    jtrc(i) = itrc(i)
    if (jtrc(i).eq.0) jtrc(i) = max(odim(i),1)
    inof(i) = jblc(i)
    dimou(i) = jtrc(i)-jblc(i)+1
  enddo
  do i=ndim,1,-1
    if (jblc(i).ne.jtrc(i)) then
      do j=1,i-1
        jblc(j) = 1
        jtrc(j) = odim(j) 
      enddo
      inof(i) = 1
      exit ! Job is done now...
    endif
  enddo
  !
  do i=1,ndim
    dimin(i) = jtrc(i)-jblc(i)+1
  enddo
  !
  ! Get the offset of the subset
  ioffs = 0
  do i=ndim,1,-1
    ioffs = ioffs*odim(i)+jblc(i)-1
  enddo
  !
  ! Skip the number of items. Status of NB unclear ?...
  fd%nb = 2881 ! ?..
  call gfits_skidat(fd,ioffs,error)
  if (error) return
  !
  nfill = 0
  !
  ! Allocate the whole data space...
  ndata = 1
  do i=1,ndim
    ndata = ndata * dimin(i)
  enddo
  allocate (myarray(ndata), stat=ier)
  if (ier.ne.0) then
    error = .true.
    return
  endif
  !
  ! Read it. 
  call gfits_getreal(fd,ndata,myarray,fd%bscal,fd%bzero,error)
  !
  ! Now extract the desired subset...
  if (.not.error) then
    call gfits_extract_bytearray(myarray,ndim,dimin,inof,4, &
    array,ndim,dimou)
  endif
  !
  ! Cleanup
  deallocate(myarray,stat=ier)
  !
end subroutine read_subset
!
subroutine gfits_extract_bytearray(in,ndin,indim,inoff,size,out,ndout,outdim)
  use gildas_def
  !---------------------------------------------------------------------
  ! @ no-interface
  !   Extract a subarray variable with arbitrary bounds and element size
  !   Valid for a maximum of 4 dimensions
  !---------------------------------------------------------------------
  integer(kind=1),            intent(in)    :: in(*)       ! Input value array
  integer(kind=4),            intent(in)    :: ndin        ! Number of dimensions to input variable (unused)
  integer(kind=index_length), intent(in)    :: indim(4)    ! Dimensions of input array
  integer(kind=index_length), intent(in)    :: inoff(4)    ! Offsets of subarray within input array
  integer,                    intent(in)    :: size        ! Size (in bytes) of array elements
  integer(kind=1),            intent(out)   :: out(*)      ! Output buffer
  integer(kind=4)                           :: ndout       ! Number of dimensions of output array (unused)
  integer(kind=index_length), intent(in)    :: outdim(4)   ! Dimensions of output array
  ! Local
  integer(kind=index_length) :: i2,i3,i4
  integer(kind=size_length) :: off_in,off_out
  integer(kind=size_length) :: off_in2,off_out2
  integer(kind=size_length) :: off_in3,off_out3
  integer(kind=size_length) :: off_in4,off_out4
  !
  do i4=1,outdim(4)
    off_in4 = (i4+inoff(4)-2)*indim(3)
    off_out4 = (i4-1)*outdim(3)
    do i3=1,outdim(3)
      off_in3 = (off_in4+(i3+inoff(3)-2))*indim(2)
      off_out3 = (off_out4+(i3-1))*outdim(2)
      do i2=1,outdim(2)
        off_in2 = (off_in3+(i2+inoff(2)-2))*indim(1)
        off_out2 = (off_out3+(i2-1))*outdim(1)
        !
        ! Compress the inner loop
        off_in = (off_in2+(inoff(1)-1))*size+1
        off_out = off_out2*size+1
        out(off_out:off_out+outdim(1)*size-1) = in(off_in:off_in+outdim(1)*size-1)
      enddo
    enddo
  enddo
  !
end subroutine gfits_extract_bytearray
