Revision: 76811
          http://sourceforge.net/p/brlcad/code/76811
Author:   starseeker
Date:     2020-08-17 01:55:50 +0000 (Mon, 17 Aug 2020)
Log Message:
-----------
I may be mistaken, but it looks like the Windows Ninja CMake setup can't handle 
super-long object lists - if I disable all of the formats the buidl will 
complete.  Try collapsing the frmts subdirs into a single object build and see 
if that helps.

Modified Paths:
--------------
    brlcad/trunk/src/other/CMakeLists.txt
    brlcad/trunk/src/other/gdal/CMakeLists.txt
    brlcad/trunk/src/other/gdal/alg/CMakeLists.txt
    brlcad/trunk/src/other/gdal/alg/gdalpansharpen.cpp
    brlcad/trunk/src/other/gdal/apps/CMakeLists.txt
    brlcad/trunk/src/other/gdal/frmts/CMakeLists.txt
    brlcad/trunk/src/other/gdal/gcore/CMakeLists.txt
    brlcad/trunk/src/other/gdal/gcore/gdaldataset.cpp
    brlcad/trunk/src/other/gdal/ogr/ogrsf_frmts/idrisi/CMakeLists.txt
    brlcad/trunk/src/other/gdal/ogr/ogrsf_frmts/pds/CMakeLists.txt
    brlcad/trunk/src/other/gdal/ogr/ogrsf_frmts/s57/CMakeLists.txt
    brlcad/trunk/src/other/gdal/progs/CMakeLists.txt
    brlcad/trunk/src/other/gdal.dist

Added Paths:
-----------
    brlcad/trunk/src/other/gdal/frmts/EnvisatFile.c
    brlcad/trunk/src/other/gdal/frmts/EnvisatFile.h
    brlcad/trunk/src/other/gdal/frmts/IdrisiDataset.cpp
    brlcad/trunk/src/other/gdal/frmts/IngrTypes.cpp
    brlcad/trunk/src/other/gdal/frmts/IngrTypes.h
    brlcad/trunk/src/other/gdal/frmts/IntergraphBand.cpp
    brlcad/trunk/src/other/gdal/frmts/IntergraphBand.h
    brlcad/trunk/src/other/gdal/frmts/IntergraphDataset.cpp
    brlcad/trunk/src/other/gdal/frmts/IntergraphDataset.h
    brlcad/trunk/src/other/gdal/frmts/JpegHelper.cpp
    brlcad/trunk/src/other/gdal/frmts/JpegHelper.h
    brlcad/trunk/src/other/gdal/frmts/README
    brlcad/trunk/src/other/gdal/frmts/TODO_Projections.txt
    brlcad/trunk/src/other/gdal/frmts/aaigriddataset.cpp
    brlcad/trunk/src/other/gdal/frmts/aaigriddataset.h
    brlcad/trunk/src/other/gdal/frmts/ace2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/adrgdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/adsrange.cpp
    brlcad/trunk/src/other/gdal/frmts/adsrange.hpp
    brlcad/trunk/src/other/gdal/frmts/aigccitt.c
    brlcad/trunk/src/other/gdal/frmts/aigdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/aigopen.c
    brlcad/trunk/src/other/gdal/frmts/aigrid.h
    brlcad/trunk/src/other/gdal/frmts/airsardataset.cpp
    brlcad/trunk/src/other/gdal/frmts/argdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/atlsci_spheroid.cpp
    brlcad/trunk/src/other/gdal/frmts/atlsci_spheroid.h
    brlcad/trunk/src/other/gdal/frmts/blx.c
    brlcad/trunk/src/other/gdal/frmts/blx.h
    brlcad/trunk/src/other/gdal/frmts/blxdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/bmpdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/bpgdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/btdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/calsdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ceos.c
    brlcad/trunk/src/other/gdal/frmts/ceos.h
    brlcad/trunk/src/other/gdal/frmts/ceosdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ceosopen.c
    brlcad/trunk/src/other/gdal/frmts/ceosopen.h
    brlcad/trunk/src/other/gdal/frmts/ceosrecipe.c
    brlcad/trunk/src/other/gdal/frmts/ceossar.c
    brlcad/trunk/src/other/gdal/frmts/coasp_dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/cosar_dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/cpgdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ctable2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ctgdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ddffield.cpp
    brlcad/trunk/src/other/gdal/frmts/ddffielddefn.cpp
    brlcad/trunk/src/other/gdal/frmts/ddfmodule.cpp
    brlcad/trunk/src/other/gdal/frmts/ddfrecord.cpp
    brlcad/trunk/src/other/gdal/frmts/ddfsubfielddefn.cpp
    brlcad/trunk/src/other/gdal/frmts/ddfutils.cpp
    brlcad/trunk/src/other/gdal/frmts/deriveddataset.cpp
    brlcad/trunk/src/other/gdal/frmts/derivedlist.c
    brlcad/trunk/src/other/gdal/frmts/derivedlist.h
    brlcad/trunk/src/other/gdal/frmts/dimapdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/dipxdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/doq1dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/doq2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/dted_api.c
    brlcad/trunk/src/other/gdal/frmts/dted_api.h
    brlcad/trunk/src/other/gdal/frmts/dted_create.c
    brlcad/trunk/src/other/gdal/frmts/dted_ptstream.c
    brlcad/trunk/src/other/gdal/frmts/dteddataset.cpp
    brlcad/trunk/src/other/gdal/frmts/e00compr.h
    brlcad/trunk/src/other/gdal/frmts/e00griddataset.cpp
    brlcad/trunk/src/other/gdal/frmts/e00read.c
    brlcad/trunk/src/other/gdal/frmts/ecrgtocdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ehdrdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ehdrdataset.h
    brlcad/trunk/src/other/gdal/frmts/eirdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/elasdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/envidataset.cpp
    brlcad/trunk/src/other/gdal/frmts/envidataset.h
    brlcad/trunk/src/other/gdal/frmts/envisatdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ersdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ershdrnode.cpp
    brlcad/trunk/src/other/gdal/frmts/ershdrnode.h
    brlcad/trunk/src/other/gdal/frmts/fastdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/fit.cpp
    brlcad/trunk/src/other/gdal/frmts/fit.h
    brlcad/trunk/src/other/gdal/frmts/fitdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/fujibasdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gdal_vrt.h
    brlcad/trunk/src/other/gdal/frmts/genbindataset.cpp
    brlcad/trunk/src/other/gdal/frmts/geotiff.cpp
    brlcad/trunk/src/other/gdal/frmts/gff_dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/grcdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/grddataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gridlib.c
    brlcad/trunk/src/other/gdal/frmts/gs7bgdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gsagdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gsbgdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gscdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gstEndian.h
    brlcad/trunk/src/other/gdal/frmts/gstTypes.h
    brlcad/trunk/src/other/gdal/frmts/gt_citation.cpp
    brlcad/trunk/src/other/gdal/frmts/gt_citation.h
    brlcad/trunk/src/other/gdal/frmts/gt_jpeg_copy.cpp
    brlcad/trunk/src/other/gdal/frmts/gt_jpeg_copy.h
    brlcad/trunk/src/other/gdal/frmts/gt_overview.cpp
    brlcad/trunk/src/other/gdal/frmts/gt_overview.h
    brlcad/trunk/src/other/gdal/frmts/gt_wkt_srs.cpp
    brlcad/trunk/src/other/gdal/frmts/gt_wkt_srs.h
    brlcad/trunk/src/other/gdal/frmts/gt_wkt_srs_for_gdal.h
    brlcad/trunk/src/other/gdal/frmts/gt_wkt_srs_priv.h
    brlcad/trunk/src/other/gdal/frmts/gtiff.h
    brlcad/trunk/src/other/gdal/frmts/gtxdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gxf_ogcwkt.c
    brlcad/trunk/src/other/gdal/frmts/gxf_proj4.c
    brlcad/trunk/src/other/gdal/frmts/gxfdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/gxfopen.c
    brlcad/trunk/src/other/gdal/frmts/gxfopen.h
    brlcad/trunk/src/other/gdal/frmts/hf2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/hfa.h
    brlcad/trunk/src/other/gdal/frmts/hfa_overviews.cpp
    brlcad/trunk/src/other/gdal/frmts/hfa_p.h
    brlcad/trunk/src/other/gdal/frmts/hfaband.cpp
    brlcad/trunk/src/other/gdal/frmts/hfacompress.cpp
    brlcad/trunk/src/other/gdal/frmts/hfadataset.cpp
    brlcad/trunk/src/other/gdal/frmts/hfadataset.h
    brlcad/trunk/src/other/gdal/frmts/hfadictionary.cpp
    brlcad/trunk/src/other/gdal/frmts/hfaentry.cpp
    brlcad/trunk/src/other/gdal/frmts/hfafield.cpp
    brlcad/trunk/src/other/gdal/frmts/hfaopen.cpp
    brlcad/trunk/src/other/gdal/frmts/hfatype.cpp
    brlcad/trunk/src/other/gdal/frmts/hkvdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/idadataset.cpp
    brlcad/trunk/src/other/gdal/frmts/idrisi.h
    brlcad/trunk/src/other/gdal/frmts/ilwiscoordinatesystem.cpp
    brlcad/trunk/src/other/gdal/frmts/ilwisdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ilwisdataset.h
    brlcad/trunk/src/other/gdal/frmts/irisdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/iscedataset.cpp
    brlcad/trunk/src/other/gdal/frmts/isis2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/isis3dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/iso8211.h
    brlcad/trunk/src/other/gdal/frmts/jaxapalsardataset.cpp
    brlcad/trunk/src/other/gdal/frmts/jdemdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/kmlsuperoverlaydataset.cpp
    brlcad/trunk/src/other/gdal/frmts/kmlsuperoverlaydataset.h
    brlcad/trunk/src/other/gdal/frmts/krodataset.cpp
    brlcad/trunk/src/other/gdal/frmts/l1bdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/landataset.cpp
    brlcad/trunk/src/other/gdal/frmts/lcpdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/levellerdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/libgeotiff/
    brlcad/trunk/src/other/gdal/frmts/libtiff/
    brlcad/trunk/src/other/gdal/frmts/link.c
    brlcad/trunk/src/other/gdal/frmts/loslasdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/mapdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/memdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/memdataset.h
    brlcad/trunk/src/other/gdal/frmts/mffdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/mgrs.c
    brlcad/trunk/src/other/gdal/frmts/mgrs.h
    brlcad/trunk/src/other/gdal/frmts/nasakeywordhandler.cpp
    brlcad/trunk/src/other/gdal/frmts/nasakeywordhandler.h
    brlcad/trunk/src/other/gdal/frmts/ndfdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ngsgeoiddataset.cpp
    brlcad/trunk/src/other/gdal/frmts/nitf_gcprpc.cpp
    brlcad/trunk/src/other/gdal/frmts/nitfaridpcm.cpp
    brlcad/trunk/src/other/gdal/frmts/nitfbilevel.cpp
    brlcad/trunk/src/other/gdal/frmts/nitfdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/nitfdataset.h
    brlcad/trunk/src/other/gdal/frmts/nitfdes.c
    brlcad/trunk/src/other/gdal/frmts/nitffile.c
    brlcad/trunk/src/other/gdal/frmts/nitfimage.c
    brlcad/trunk/src/other/gdal/frmts/nitflib.h
    brlcad/trunk/src/other/gdal/frmts/nitfrasterband.cpp
    brlcad/trunk/src/other/gdal/frmts/nitfwritejpeg.cpp
    brlcad/trunk/src/other/gdal/frmts/nitfwritejpeg_12.cpp
    brlcad/trunk/src/other/gdal/frmts/northwood.cpp
    brlcad/trunk/src/other/gdal/frmts/northwood.h
    brlcad/trunk/src/other/gdal/frmts/ntv2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/ozidataset.cpp
    brlcad/trunk/src/other/gdal/frmts/pauxdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/pdsdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/phprfdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/pixelfunctions.cpp
    brlcad/trunk/src/other/gdal/frmts/pngdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/pnmdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rawdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rawdataset.h
    brlcad/trunk/src/other/gdal/frmts/rcreatecopy.cpp
    brlcad/trunk/src/other/gdal/frmts/rdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rdataset.h
    brlcad/trunk/src/other/gdal/frmts/rdc.txt
    brlcad/trunk/src/other/gdal/frmts/readme.txt
    brlcad/trunk/src/other/gdal/frmts/records.c
    brlcad/trunk/src/other/gdal/frmts/records.h
    brlcad/trunk/src/other/gdal/frmts/rikdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rmfdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rmfdataset.h
    brlcad/trunk/src/other/gdal/frmts/rmfdem.cpp
    brlcad/trunk/src/other/gdal/frmts/rmflzw.cpp
    brlcad/trunk/src/other/gdal/frmts/roipacdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rpftocdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rpftocfile.cpp
    brlcad/trunk/src/other/gdal/frmts/rpftoclib.h
    brlcad/trunk/src/other/gdal/frmts/rrasterdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rs2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/rst.txt
    brlcad/trunk/src/other/gdal/frmts/safedataset.cpp
    brlcad/trunk/src/other/gdal/frmts/sagadataset.cpp
    brlcad/trunk/src/other/gdal/frmts/sar_ceosdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/sentinel2dataset.cpp
    brlcad/trunk/src/other/gdal/frmts/sgidataset.cpp
    brlcad/trunk/src/other/gdal/frmts/snodasdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/srpdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/srtmhgtdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/terragendataset.cpp
    brlcad/trunk/src/other/gdal/frmts/tif_float.c
    brlcad/trunk/src/other/gdal/frmts/tif_float.h
    brlcad/trunk/src/other/gdal/frmts/tifvsi.cpp
    brlcad/trunk/src/other/gdal/frmts/tifvsi.h
    brlcad/trunk/src/other/gdal/frmts/tildataset.cpp
    brlcad/trunk/src/other/gdal/frmts/timedelta.hpp
    brlcad/trunk/src/other/gdal/frmts/tsxdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/unwrapgcps.cpp
    brlcad/trunk/src/other/gdal/frmts/usgsdem_create.cpp
    brlcad/trunk/src/other/gdal/frmts/usgsdemdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/vicardataset.cpp
    brlcad/trunk/src/other/gdal/frmts/vicarkeywordhandler.cpp
    brlcad/trunk/src/other/gdal/frmts/vicarkeywordhandler.h
    brlcad/trunk/src/other/gdal/frmts/vrtdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtdataset.h
    brlcad/trunk/src/other/gdal/frmts/vrtderivedrasterband.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtdriver.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtfilters.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtpansharpened.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtrasterband.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtrawrasterband.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtsourcedrasterband.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtsources.cpp
    brlcad/trunk/src/other/gdal/frmts/vrtwarped.cpp
    brlcad/trunk/src/other/gdal/frmts/xpmdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/xyzdataset.cpp
    brlcad/trunk/src/other/gdal/frmts/zmapdataset.cpp

Removed Paths:
-------------
    brlcad/trunk/src/other/gdal/frmts/aaigrid/
    brlcad/trunk/src/other/gdal/frmts/adrg/
    brlcad/trunk/src/other/gdal/frmts/aigrid/
    brlcad/trunk/src/other/gdal/frmts/airsar/
    brlcad/trunk/src/other/gdal/frmts/arg/
    brlcad/trunk/src/other/gdal/frmts/blx/
    brlcad/trunk/src/other/gdal/frmts/bmp/
    brlcad/trunk/src/other/gdal/frmts/bpg/
    brlcad/trunk/src/other/gdal/frmts/cals/
    brlcad/trunk/src/other/gdal/frmts/ceos/
    brlcad/trunk/src/other/gdal/frmts/ceos2/
    brlcad/trunk/src/other/gdal/frmts/coasp/
    brlcad/trunk/src/other/gdal/frmts/cosar/
    brlcad/trunk/src/other/gdal/frmts/ctg/
    brlcad/trunk/src/other/gdal/frmts/derived/
    brlcad/trunk/src/other/gdal/frmts/dimap/
    brlcad/trunk/src/other/gdal/frmts/dted/
    brlcad/trunk/src/other/gdal/frmts/e00grid/
    brlcad/trunk/src/other/gdal/frmts/elas/
    brlcad/trunk/src/other/gdal/frmts/envisat/
    brlcad/trunk/src/other/gdal/frmts/ers/
    brlcad/trunk/src/other/gdal/frmts/fit/
    brlcad/trunk/src/other/gdal/frmts/gff/
    brlcad/trunk/src/other/gdal/frmts/gsg/
    brlcad/trunk/src/other/gdal/frmts/gtiff/
    brlcad/trunk/src/other/gdal/frmts/gxf/
    brlcad/trunk/src/other/gdal/frmts/hf2/
    brlcad/trunk/src/other/gdal/frmts/hfa/
    brlcad/trunk/src/other/gdal/frmts/idrisi/
    brlcad/trunk/src/other/gdal/frmts/ilwis/
    brlcad/trunk/src/other/gdal/frmts/ingr/
    brlcad/trunk/src/other/gdal/frmts/iris/
    brlcad/trunk/src/other/gdal/frmts/iso8211/
    brlcad/trunk/src/other/gdal/frmts/jaxapalsar/
    brlcad/trunk/src/other/gdal/frmts/jdem/
    brlcad/trunk/src/other/gdal/frmts/kmlsuperoverlay/
    brlcad/trunk/src/other/gdal/frmts/l1b/
    brlcad/trunk/src/other/gdal/frmts/leveller/
    brlcad/trunk/src/other/gdal/frmts/map/
    brlcad/trunk/src/other/gdal/frmts/mem/
    brlcad/trunk/src/other/gdal/frmts/ngsgeoid/
    brlcad/trunk/src/other/gdal/frmts/nitf/
    brlcad/trunk/src/other/gdal/frmts/northwood/
    brlcad/trunk/src/other/gdal/frmts/ozi/
    brlcad/trunk/src/other/gdal/frmts/pds/
    brlcad/trunk/src/other/gdal/frmts/png/
    brlcad/trunk/src/other/gdal/frmts/prf/
    brlcad/trunk/src/other/gdal/frmts/r/
    brlcad/trunk/src/other/gdal/frmts/raw/
    brlcad/trunk/src/other/gdal/frmts/rik/
    brlcad/trunk/src/other/gdal/frmts/rmf/
    brlcad/trunk/src/other/gdal/frmts/rs2/
    brlcad/trunk/src/other/gdal/frmts/safe/
    brlcad/trunk/src/other/gdal/frmts/saga/
    brlcad/trunk/src/other/gdal/frmts/sentinel2/
    brlcad/trunk/src/other/gdal/frmts/sgi/
    brlcad/trunk/src/other/gdal/frmts/srtmhgt/
    brlcad/trunk/src/other/gdal/frmts/terragen/
    brlcad/trunk/src/other/gdal/frmts/til/
    brlcad/trunk/src/other/gdal/frmts/tsx/
    brlcad/trunk/src/other/gdal/frmts/usgsdem/
    brlcad/trunk/src/other/gdal/frmts/vrt/
    brlcad/trunk/src/other/gdal/frmts/xpm/
    brlcad/trunk/src/other/gdal/frmts/xyz/
    brlcad/trunk/src/other/gdal/frmts/zmap/

Modified: brlcad/trunk/src/other/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/other/CMakeLists.txt       2020-08-16 19:09:56 UTC (rev 
76810)
+++ brlcad/trunk/src/other/CMakeLists.txt       2020-08-17 01:55:50 UTC (rev 
76811)
@@ -946,7 +946,7 @@
     "${BRLCAD_SOURCE_DIR}/src/other/gdal/ogr/ogrsf_frmts"
     "${BRLCAD_SOURCE_DIR}/src/other/gdal/gnm"
     "${BRLCAD_SOURCE_DIR}/src/other/gdal/apps"
-    "${BRLCAD_SOURCE_DIR}/src/other/gdal/frmts/vrt"
+    "${BRLCAD_SOURCE_DIR}/src/other/gdal/frmts"
     )
   set(GDAL_INCLUDE_DIR "${GDAL_INCLUDE_DIR}" CACHE STRING "libgdal includes" 
FORCE)
   DISTCLEAN("${CMAKE_CURRENT_BINARY_DIR}/gdal/cpl_config.h")

Modified: brlcad/trunk/src/other/gdal/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/other/gdal/CMakeLists.txt  2020-08-16 19:09:56 UTC (rev 
76810)
+++ brlcad/trunk/src/other/gdal/CMakeLists.txt  2020-08-17 01:55:50 UTC (rev 
76811)
@@ -341,7 +341,7 @@
   $<TARGET_OBJECTS:gdal_mdreader_obj>
   $<TARGET_OBJECTS:gdal_gcore_obj>
   $<TARGET_OBJECTS:gdal_alg_obj>
-  $<TARGET_OBJECTS:gdal_allreg_obj>
+  $<TARGET_OBJECTS:gdal_frmts_obj>
   $<TARGET_OBJECTS:libtiff_obj>
   $<TARGET_OBJECTS:libgeotiff_obj>
   $<TARGET_OBJECTS:json_obj>
@@ -349,10 +349,6 @@
   $<TARGET_OBJECTS:gdal_gnm_obj>
   $<TARGET_OBJECTS:gdal_apps_obj>
   )
-foreach(frmt ${GDAL_FORMATS})
-  set(gdal_srcs ${gdal_srcs} $<TARGET_OBJECTS:frmt_${frmt}>)
-  set_target_properties(frmt_${frmt} PROPERTIES FOLDER "Third Party 
Libraries/GDAL")
-endforeach(frmt ${GDAL_FORMATS})
 foreach(frmt ${OGR_FORMATS})
   set(gdal_srcs ${gdal_srcs} $<TARGET_OBJECTS:ogr_frmt_${frmt}>)
   set_target_properties(ogr_frmt_${frmt} PROPERTIES FOLDER "Third Party 
Libraries/GDAL")

Modified: brlcad/trunk/src/other/gdal/alg/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/other/gdal/alg/CMakeLists.txt      2020-08-16 19:09:56 UTC 
(rev 76810)
+++ brlcad/trunk/src/other/gdal/alg/CMakeLists.txt      2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -1,6 +1,6 @@
 
 include_directories(
-       ${CMAKE_CURRENT_SOURCE_DIR}/../frmts/vrt
+       ${CMAKE_CURRENT_SOURCE_DIR}/../frmts
        )
 
 add_definitions(-DINTERNAL_QHULL)

Modified: brlcad/trunk/src/other/gdal/alg/gdalpansharpen.cpp
===================================================================
--- brlcad/trunk/src/other/gdal/alg/gdalpansharpen.cpp  2020-08-16 19:09:56 UTC 
(rev 76810)
+++ brlcad/trunk/src/other/gdal/alg/gdalpansharpen.cpp  2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -41,8 +41,8 @@
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
 #include "cpl_vsi.h"
-#include "../frmts/mem/memdataset.h"
-#include "../frmts/vrt/vrtdataset.h"
+#include "../frmts/memdataset.h"
+#include "../frmts/vrtdataset.h"
 #include "gdal_priv.h"
 #include "gdal_priv_templates.hpp"
 // #include "gdalsse_priv.h"

Modified: brlcad/trunk/src/other/gdal/apps/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/other/gdal/apps/CMakeLists.txt     2020-08-16 19:09:56 UTC 
(rev 76810)
+++ brlcad/trunk/src/other/gdal/apps/CMakeLists.txt     2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -1,7 +1,7 @@
 
 include_directories(
        ${CMAKE_CURRENT_SOURCE_DIR}
-       ${CMAKE_CURRENT_SOURCE_DIR}/../frmts/vrt
+       ${CMAKE_CURRENT_SOURCE_DIR}/../frmts
        ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/geojson/libjson
        ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/geojson
        ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/generic

Modified: brlcad/trunk/src/other/gdal/frmts/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/other/gdal/frmts/CMakeLists.txt    2020-08-16 19:09:56 UTC 
(rev 76810)
+++ brlcad/trunk/src/other/gdal/frmts/CMakeLists.txt    2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -1,20 +1,192 @@
+add_subdirectory(libtiff)
+add_subdirectory(libgeotiff)
 
 include_directories(
-       ${CMAKE_CURRENT_SOURCE_DIR}/../gnm/gnm_frmts
-       )
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/../gnm/gnm_frmts
+  ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/avc
+  ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/geojson
+  ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/geojson/libjson
+  ${CMAKE_CURRENT_SOURCE_DIR}/../ogr/ogrsf_frmts/shape
+  ${CMAKE_CURRENT_SOURCE_DIR}/gtiff
+  ${CMAKE_CURRENT_SOURCE_DIR}/gtiff/libtiff
+  ${CMAKE_CURRENT_SOURCE_DIR}/iso8211
+  ${CMAKE_CURRENT_SOURCE_DIR}/libgeotiff
+  ${CMAKE_CURRENT_SOURCE_DIR}/libtiff
+  ${CMAKE_CURRENT_SOURCE_DIR}/mem
+  ${CMAKE_CURRENT_SOURCE_DIR}/raw
+  ${CMAKE_CURRENT_SOURCE_DIR}/vrt
+  )
 
-set(frmts_srcs frmts/gdalallregister.cpp)
+add_definitions(-DGDALDRIVER)
+add_definitions(-DINTERNAL_LIBGEOTIFF)
+add_definitions(-DINTERNAL_LIBTIFF)
+add_definitions(-DBIGTIFF_SUPPORT)
 
 foreach(frmt ${GDAL_FORMATS})
-       add_definitions(-DFRMT_${frmt})
-       set(GDAL_LIST "${GDAL_LIST} ${frmt}")
+  add_definitions(-DFRMT_${frmt})
+  set(GDAL_LIST "${GDAL_LIST} ${frmt}")
 endforeach(frmt ${GDAL_FORMATS})
-
 add_definitions(-DGDAL_FORMATS=${GDAL_LIST})
 
-add_library(gdal_allreg_obj OBJECT gdalallregister.cpp)
-set_target_properties(gdal_allreg_obj PROPERTIES FOLDER "Third Party 
Libraries/GDAL")
+set(gdal_frmt_srcs
+  gdalallregister.cpp
+  aaigriddataset.cpp
+  adrgdataset.cpp srpdataset.cpp
+  aigdataset.cpp gridlib.c aigopen.c aigccitt.c
+  airsardataset.cpp
+  argdataset.cpp
+  blxdataset.cpp blx.c
+  bmpdataset.cpp
+  calsdataset.cpp
+  sar_ceosdataset.cpp ceosrecipe.c ceossar.c ceos.c link.c
+  ceosopen.c ceosdataset.cpp
+  coasp_dataset.cpp
+  cosar_dataset.cpp
+  ctgdataset.cpp
+  deriveddataset.cpp derivedlist.c
+  dimapdataset.cpp
+  dted_api.c dteddataset.cpp dted_create.c dted_ptstream.c
+  e00griddataset.cpp
+  elasdataset.cpp
+  EnvisatFile.c records.c adsrange.cpp unwrapgcps.cpp envisatdataset.cpp
+  ersdataset.cpp ershdrnode.cpp
+  fitdataset.cpp fit.cpp
+  gff_dataset.cpp
+  gsagdataset.cpp gsbgdataset.cpp gs7bgdataset.cpp
+  geotiff.cpp
+  gt_wkt_srs.cpp
+  gt_citation.cpp
+  gt_overview.cpp
+  tif_float.c
+  tifvsi.cpp
+  gt_jpeg_copy.cpp
+  gxfdataset.cpp gxfopen.c gxf_proj4.c gxf_ogcwkt.c
+  hf2dataset.cpp
+  hfaopen.cpp
+  hfaentry.cpp
+  hfadictionary.cpp
+  hfafield.cpp
+  hfatype.cpp
+  hfaband.cpp
+  hfacompress.cpp
+  hfadataset.cpp
+  hfa_overviews.cpp
+  IdrisiDataset.cpp
+  ilwisdataset.cpp ilwiscoordinatesystem.cpp
+  IntergraphDataset.cpp IntergraphBand.cpp IngrTypes.cpp JpegHelper.cpp
+  irisdataset.cpp
+  ddfmodule.cpp
+  ddfutils.cpp
+  ddffielddefn.cpp
+  ddfrecord.cpp
+  ddffield.cpp
+  ddfsubfielddefn.cpp
+  jaxapalsardataset.cpp
+  jdemdataset.cpp
+  kmlsuperoverlaydataset.cpp
+  l1bdataset.cpp
+  levellerdataset.cpp
+  mapdataset.cpp
+  memdataset.cpp
+  ngsgeoiddataset.cpp
+  nitfdataset.cpp
+  rpftocdataset.cpp
+  nitfwritejpeg.cpp
+  nitfwritejpeg_12.cpp
+  nitfrasterband.cpp
+  ecrgtocdataset.cpp
+  nitffile.c
+  nitfimage.c
+  mgrs.c
+  nitfaridpcm.cpp
+  nitfbilevel.cpp
+  rpftocfile.cpp
+  nitfdes.c
+  nitf_gcprpc.cpp
+  grddataset.cpp grcdataset.cpp northwood.cpp
+  ozidataset.cpp
+  pdsdataset.cpp
+  isis2dataset.cpp
+  isis3dataset.cpp
+  vicardataset.cpp
+  nasakeywordhandler.cpp
+  vicarkeywordhandler.cpp
+  pngdataset.cpp
+  phprfdataset.cpp
+  rawdataset.cpp
+  ehdrdataset.cpp
+  pauxdataset.cpp
+  doq1dataset.cpp
+  doq2dataset.cpp
+  mffdataset.cpp
+  hkvdataset.cpp
+  pnmdataset.cpp
+  fujibasdataset.cpp
+  envidataset.cpp
+  gscdataset.cpp
+  fastdataset.cpp
+  atlsci_spheroid.cpp
+  btdataset.cpp
+  landataset.cpp
+  cpgdataset.cpp
+  idadataset.cpp
+  ndfdataset.cpp
+  dipxdataset.cpp
+  genbindataset.cpp
+  lcpdataset.cpp
+  eirdataset.cpp
+  gtxdataset.cpp
+  loslasdataset.cpp
+  ntv2dataset.cpp
+  ace2dataset.cpp
+  snodasdataset.cpp
+  ctable2dataset.cpp
+  krodataset.cpp
+  roipacdataset.cpp
+  iscedataset.cpp
+  rrasterdataset.cpp
+  rdataset.cpp rcreatecopy.cpp
+  rikdataset.cpp
+  rmfdataset.cpp rmflzw.cpp rmfdem.cpp
+  rs2dataset.cpp
+  safedataset.cpp
+  sagadataset.cpp
+  sentinel2dataset.cpp
+  sgidataset.cpp
+  srtmhgtdataset.cpp
+  terragendataset.cpp
+  tildataset.cpp
+  tsxdataset.cpp
+  usgsdemdataset.cpp usgsdem_create.cpp
+  vrtdataset.cpp
+  vrtrasterband.cpp
+  vrtdriver.cpp
+  vrtsources.cpp
+  vrtfilters.cpp
+  vrtsourcedrasterband.cpp
+  vrtrawrasterband.cpp
+  vrtwarped.cpp
+  vrtderivedrasterband.cpp
+  vrtpansharpened.cpp
+  pixelfunctions.cpp
+  xpmdataset.cpp
+  xyzdataset.cpp
+  zmapdataset.cpp
+  )
 
-foreach(frmt ${GDAL_FORMATS})
-       add_subdirectory(${frmt})
-endforeach(frmt ${GDAL_FORMATS})
+add_library(gdal_frmts_obj OBJECT ${gdal_frmt_srcs})
+set_target_properties(gdal_frmts_obj PROPERTIES FOLDER "Third Party 
Libraries/GDAL")
+
+if (TARGET png)
+  add_dependencies(gdal_frmts_obj png)
+endif (TARGET png)
+
+
+# Local Variables:
+# tab-width: 8
+# mode: cmake
+# indent-tabs-mode: t
+# End:
+# ex: shiftwidth=2 tabstop=8
+

Copied: brlcad/trunk/src/other/gdal/frmts/EnvisatFile.c (from rev 76810, 
brlcad/trunk/src/other/gdal/frmts/envisat/EnvisatFile.c)
===================================================================
--- brlcad/trunk/src/other/gdal/frmts/EnvisatFile.c                             
(rev 0)
+++ brlcad/trunk/src/other/gdal/frmts/EnvisatFile.c     2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -0,0 +1,1967 @@
+/******************************************************************************
+ * $Id: EnvisatFile.c 36380 2016-11-21 10:21:20Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  Low Level Envisat file access (read/write) API.
+ * Author:   Frank Warmerdam, [email protected]
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, Atlantis Scientific, Inc.
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot 
org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+
+#ifndef APP_BUILD
+#  define GDAL_BUILD
+#  include "cpl_conv.h"
+#  include "EnvisatFile.h"
+
+CPL_CVSID("$Id: EnvisatFile.c 36380 2016-11-21 10:21:20Z rouault $");
+
+#else
+#  include "APP/app.h"
+#  include "util/Files/EnvisatFile.h"
+#endif
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused) {}
+
+typedef struct
+{
+    char       *ds_name;
+    char       *ds_type;
+    char       *filename;
+    int                ds_offset;
+    int                ds_size;
+    int                num_dsr;
+    int                dsr_size;
+} EnvisatDatasetInfo;
+
+typedef struct
+{
+    char       *key;
+    char       *value;
+    size_t      value_len;
+    char       *units;
+    char       *literal_line;
+    int         value_offset;
+} EnvisatNameValue;
+
+struct EnvisatFile_tag
+{
+    VSILFILE   *fp;
+    char        *filename;
+    int                updatable;
+    int         header_dirty;
+    int                dsd_offset;
+
+    int                mph_count;
+    EnvisatNameValue **mph_entries;
+
+    int                sph_count;
+    EnvisatNameValue **sph_entries;
+
+    int                ds_count;
+    EnvisatDatasetInfo **ds_info;
+};
+
+#ifdef GDAL_BUILD
+#  define SUCCESS 0
+#  define FAILURE 1
+#  define SendError( text )   CPLError( CE_Failure, CPLE_AppDefined, "%s", 
text )
+#endif
+
+#define MPH_SIZE 1247
+
+/*
+ * API For handling name/value lists.
+ */
+int S_NameValueList_Parse( const char *text, int text_offset,
+                           int *entry_count,
+                           EnvisatNameValue ***entries );
+void S_NameValueList_Destroy( int *entry_count,
+                             EnvisatNameValue ***entries );
+int S_NameValueList_FindKey( const char *key,
+                             int entry_count,
+                             EnvisatNameValue **entries );
+const char *S_NameValueList_FindValue( const char *key,
+                                       int entry_count,
+                                       EnvisatNameValue **entries,
+                                       const char * default_value );
+
+int S_NameValueList_Rewrite( VSILFILE *fp, int entry_count,
+                             EnvisatNameValue **entries );
+
+EnvisatNameValue *
+    S_EnivsatFile_FindNameValue( EnvisatFile *self,
+                                 EnvisatFile_HeaderFlag mph_or_sph,
+                                 const char * key );
+
+
+
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    Envisat_SetupLevel0
+
+Purpose:
+    Patch up missing information about SPH, and datasets for incomplete
+    level 0 signal datasets.
+
+Description:
+
+Inputs:
+    self -- Envisat file handle.
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+static int EnvisatFile_SetupLevel0( EnvisatFile *self )
+
+{
+    int        file_length;
+    unsigned char header[68];
+    EnvisatDatasetInfo *ds_info;
+
+    self->dsd_offset = 0;
+    self->ds_count = 1;
+    self->ds_info = (EnvisatDatasetInfo **)
+        CPLCalloc(sizeof(EnvisatDatasetInfo*),self->ds_count);
+
+    if( self->ds_info == NULL )
+        return FAILURE;
+
+    /*
+     * Figure out how long the file is.
+     */
+
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( self->fp, 0, SEEK_END ));
+    file_length = (int) VSIFTellL( self->fp );
+
+    /*
+     * Read the first record header, and verify the well known values.
+     */
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( self->fp, 3203, SEEK_SET ));
+    CPL_IGNORE_RET_VAL_SIZET(VSIFReadL( header, 68, 1, self->fp ));
+
+    if( header[38] != 0 || header[39] != 0x1d
+        || header[40] != 0 || header[41] != 0x54 )
+    {
+        SendError( "Didn't get expected Data Field Header Length, or Mode ID\n"
+                   "values for the first data record." );
+        return FAILURE;
+    }
+
+    /*
+     * Then build the dataset into structure from that.
+     */
+    ds_info = (EnvisatDatasetInfo *) CPLCalloc(sizeof(EnvisatDatasetInfo),1);
+
+    ds_info->ds_name = CPLStrdup( "ASAR SOURCE PACKETS         " );
+    ds_info->ds_type = CPLStrdup("M");
+    ds_info->filename = CPLStrdup("                                            
                  ");
+    ds_info->ds_offset = 3203;
+    ds_info->dsr_size = -1;
+    ds_info->num_dsr = 0;
+    ds_info->ds_size = file_length - ds_info->ds_offset;
+
+    self->ds_info[0] = ds_info;
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    Envisat_Open
+
+Purpose:
+    Open an ENVISAT formatted file, and read all headers.
+
+Description:
+
+Inputs:
+    filename -- name of Envisat file.
+    mode -- either "r" for read access, or "r+" for read/write access.
+
+Outputs:
+    self -- file handle, NULL on FAILURE.
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_Open( EnvisatFile **self_ptr,
+                      const char *filename,
+                      const char *mode )
+
+{
+    VSILFILE   *fp;
+    EnvisatFile        *self;
+    char       mph_data[1248];
+    char       *sph_data, *ds_data;
+    int                sph_size, num_dsd, dsd_size, i;
+
+    *self_ptr = NULL;
+
+    /*
+     * Check for legal mode argument.  Force to be binary for correct
+     * operation on DOS file systems.
+     */
+    if( strcmp(mode,"r") == 0 )
+        mode = "rb";
+    else if( strcmp(mode,"r+") == 0 )
+        mode = "rb+";
+    else
+    {
+        SendError( "Illegal mode value used in EnvisatFile_Open(), only "
+                   "\"r\" and \"r+\" are supported." );
+        return FAILURE;
+    }
+
+    /*
+     * Try to open the file, and report failure.
+     */
+
+    fp = VSIFOpenL( filename, mode );
+
+    if( fp == NULL )
+    {
+        char   error_buf[2048];
+
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to open file \"%s\" in EnvisatFile_Open().",
+                 filename );
+
+        SendError( error_buf );
+        return FAILURE;
+    }
+
+    /*
+     * Create, and initialize the EnvisatFile structure.
+     */
+    self = (EnvisatFile *) CPLCalloc(sizeof(EnvisatFile),1);
+    if( self == NULL )
+        return FAILURE;
+
+    self->fp = fp;
+    self->filename = CPLStrdup(filename);
+    self->header_dirty = 0;
+    self->updatable = (strcmp(mode,"rb+") == 0);
+
+    /*
+     * Read the MPH, and process it as a group of name/value pairs.
+     */
+
+    if( VSIFReadL( mph_data, 1, MPH_SIZE, fp ) != MPH_SIZE )
+    {
+        CPLFree( self );
+        SendError( "VSIFReadL() for mph failed." );
+        return FAILURE;
+    }
+
+    mph_data[MPH_SIZE] = '\0';
+    if( S_NameValueList_Parse( mph_data, 0,
+                               &(self->mph_count),
+                               &(self->mph_entries) ) == FAILURE )
+    {
+        CPLFree( self );
+        return FAILURE;
+    }
+
+    /*
+     * Is this an incomplete level 0 file?
+     */
+    if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0
+        && STARTS_WITH(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", 
""), "ASA_IM__0P") )
+    {
+
+        if( EnvisatFile_SetupLevel0( self ) == FAILURE )
+        {
+            EnvisatFile_Close( self );
+            return FAILURE;
+        }
+        else
+        {
+            *self_ptr = self;
+            return SUCCESS;
+        }
+    }
+
+    /*
+     * Read the SPH, and process it as a group of name/value pairs.
+     */
+    sph_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
+
+    if( sph_size == 0 )
+    {
+        SendError( "File does not appear to have SPH,"
+                   " SPH_SIZE not set, or zero." );
+        CPLFree( self );
+        return FAILURE;
+    }
+
+    sph_data = (char *) CPLMalloc(sph_size + 1 );
+    if( sph_data == NULL )
+        return FAILURE;
+
+    if( (int) VSIFReadL( sph_data, 1, sph_size, fp ) != sph_size )
+    {
+        CPLFree( self );
+        SendError( "VSIFReadL() for sph failed." );
+        return FAILURE;
+    }
+
+    sph_data[sph_size] = '\0';
+    ds_data = strstr(sph_data,"DS_NAME");
+    if( ds_data != NULL )
+    {
+        self->dsd_offset = (int) (ds_data - sph_data) + MPH_SIZE;
+        *(ds_data-1) = '\0';
+    }
+
+    if( S_NameValueList_Parse( sph_data, MPH_SIZE,
+                               &(self->sph_count),
+                               &(self->sph_entries) ) == FAILURE )
+    {
+        CPLFree( self );
+        return FAILURE;
+    }
+
+    /*
+     * Parse the Dataset Definitions.
+     */
+    num_dsd = EnvisatFile_GetKeyValueAsInt( self, MPH, "NUM_DSD", 0 );
+    dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
+
+    if( num_dsd > 0 && ds_data == NULL )
+    {
+        SendError( "DSDs indicated in MPH, but not found in SPH." );
+        CPLFree( self );
+        return FAILURE;
+    }
+
+    self->ds_info = (EnvisatDatasetInfo **)
+        CPLCalloc(sizeof(EnvisatDatasetInfo*),num_dsd);
+    if( self->ds_info == NULL )
+    {
+        CPLFree( self );
+        return FAILURE;
+    }
+
+    for( i = 0; i < num_dsd; i++ )
+    {
+        int    dsdh_count = 0;
+        EnvisatNameValue **dsdh_entries = NULL;
+        char   *dsd_data;
+        EnvisatDatasetInfo *ds_info;
+
+        /*
+         * We parse each DSD grouping into a name/value list.
+         */
+        dsd_data = ds_data + i * dsd_size;
+        dsd_data[dsd_size-1] = '\0';
+
+        if( S_NameValueList_Parse( dsd_data, 0,
+                                   &dsdh_count, &dsdh_entries ) == FAILURE )
+        {
+            CPLFree( self );
+            return FAILURE;
+        }
+
+        /*
+         * Then build the dataset into structure from that.
+         */
+        ds_info = (EnvisatDatasetInfo *) 
CPLCalloc(sizeof(EnvisatDatasetInfo),1);
+
+        ds_info->ds_name = CPLStrdup(
+            S_NameValueList_FindValue( "DS_NAME",
+                                       dsdh_count, dsdh_entries, "" ));
+        ds_info->ds_type = CPLStrdup(
+            S_NameValueList_FindValue( "DS_TYPE",
+                                       dsdh_count, dsdh_entries, "" ));
+        ds_info->filename = CPLStrdup(
+            S_NameValueList_FindValue( "FILENAME",
+                                       dsdh_count, dsdh_entries, "" ));
+        ds_info->ds_offset = atoi(
+            S_NameValueList_FindValue( "DS_OFFSET",
+                                       dsdh_count, dsdh_entries, "0" ));
+        ds_info->ds_size = atoi(
+            S_NameValueList_FindValue( "DS_SIZE",
+                                       dsdh_count, dsdh_entries, "0" ));
+        ds_info->num_dsr = atoi(
+            S_NameValueList_FindValue( "NUM_DSR",
+                                       dsdh_count, dsdh_entries, "0" ));
+        ds_info->dsr_size = atoi(
+            S_NameValueList_FindValue( "DSR_SIZE",
+                                       dsdh_count, dsdh_entries, "0" ));
+
+        S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
+
+        self->ds_info[i] = ds_info;
+        self->ds_count++;
+    }
+
+    CPLFree( sph_data );
+
+    /*
+     * Return successfully.
+     */
+    *self_ptr = self;
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_Create
+
+Purpose:
+    Create a new ENVISAT formatted file based on a template file.
+
+Description:
+
+Inputs:
+    filename -- name of Envisat file.
+    template_file -- name of envisat file header to utilize as template.
+
+Outputs:
+    self -- file handle, NULL on FAILURE.
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_Create( EnvisatFile **self_ptr,
+                        const char *filename,
+                        const char *template_file )
+
+{
+    int                template_size;
+    char       *template_data;
+    VSILFILE   *fp;
+
+    /*
+     * Try to open the template file, and read it into memory.
+     */
+
+    fp = VSIFOpenL( template_file, "rb" );
+
+    if( fp == NULL )
+    {
+        char   error_buf[2048];
+
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to open file \"%s\" in EnvisatFile_Create().",
+                 template_file );
+
+        SendError( error_buf );
+        return FAILURE;
+    }
+
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( fp, 0, SEEK_END ));
+    template_size = (int) VSIFTellL( fp );
+
+    template_data = (char *) CPLMalloc(template_size);
+
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( fp, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL_SIZET(VSIFReadL( template_data, template_size, 1, fp ));
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+
+    /*
+     * Try to write the template out to the new filename.
+     */
+
+    fp = VSIFOpenL( filename, "wb" );
+    if( fp == NULL )
+    {
+        char   error_buf[2048];
+
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to open file \"%s\" in EnvisatFile_Create().",
+                 filename );
+
+        SendError( error_buf );
+        return FAILURE;
+    }
+
+    CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL( template_data, template_size, 1, fp 
));
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+
+    CPLFree( template_data );
+
+    /*
+     * Now just open the file normally.
+     */
+
+    return EnvisatFile_Open( self_ptr, filename, "r+" );
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetCurrentLength
+
+Purpose:
+    Fetch the current file length.
+
+Description:
+    The length is computed by scanning the dataset definitions, not the
+    physical file length.
+
+Inputs:
+    self -- the file to operate on.
+
+Outputs:
+
+Returns:
+    Returns length or -1 on failure.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_GetCurrentLength( EnvisatFile *self )
+
+{
+    int                length;
+    int                ds;
+    int                ds_offset;
+    int         ds_size;
+
+    length = MPH_SIZE
+        + EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
+
+    for( ds = 0;
+         EnvisatFile_GetDatasetInfo( self, ds, NULL, NULL, NULL,
+                                     &ds_offset, &ds_size, NULL, NULL )
+             != FAILURE;
+         ds++ )
+    {
+        if( ds_offset != 0 && (ds_offset+ds_size) > length )
+            length = ds_offset + ds_size;
+    }
+
+    return length;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_RewriteHeader
+
+Purpose:
+    Update the envisat file header on disk to match the in-memory image.
+
+Description:
+
+Inputs:
+    self -- handle for file to close.
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE.
+
+-----------------------------------------------------------------------------*/
+
+static int EnvisatFile_RewriteHeader( EnvisatFile *self )
+
+{
+    int                dsd, dsd_size;
+
+    /*
+     * Rewrite MPH and SPH headers.
+     */
+    if( S_NameValueList_Rewrite( self->fp,
+                        self->mph_count, self->mph_entries ) == FAILURE )
+        return FAILURE;
+
+    if( S_NameValueList_Rewrite( self->fp,
+                        self->sph_count, self->sph_entries ) == FAILURE )
+        return FAILURE;
+
+    /*
+     * Rewrite DSDs.  We actually have to read each, and reparse to set
+     * the individual parameters properly.
+     */
+    dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
+    if( dsd_size == 0 )
+        return FAILURE;
+
+    for( dsd = 0; dsd < self->ds_count; dsd++ )
+    {
+        char   *dsd_text;
+        int    dsdh_count = 0, key_index;
+        EnvisatNameValue **dsdh_entries = NULL;
+
+        dsd_text = (char *) CPLCalloc(1,dsd_size+1);
+        if( VSIFSeekL( self->fp, self->dsd_offset + dsd * dsd_size,
+                   SEEK_SET ) != 0 )
+        {
+            SendError( "VSIFSeekL() failed in EnvisatFile_RewriteHeader()" );
+            CPLFree(dsd_text);
+            return FAILURE;
+        }
+
+        if( (int) VSIFReadL( dsd_text, 1, dsd_size, self->fp ) != dsd_size )
+        {
+            SendError( "VSIFReadL() failed in EnvisatFile_RewriteHeader()" );
+            return FAILURE;
+        }
+
+        if( S_NameValueList_Parse( dsd_text, self->dsd_offset + dsd*dsd_size,
+                                   &dsdh_count, &dsdh_entries ) == FAILURE )
+            return FAILURE;
+
+        CPLFree( dsd_text );
+
+        key_index = S_NameValueList_FindKey( "DS_OFFSET",
+                                             dsdh_count, dsdh_entries );
+        if( key_index == -1 )
+            continue;
+
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+021d",
+                 self->ds_info[dsd]->ds_offset );
+
+        key_index = S_NameValueList_FindKey( "DS_SIZE",
+                                             dsdh_count, dsdh_entries );
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+021d",
+                 self->ds_info[dsd]->ds_size );
+
+        key_index = S_NameValueList_FindKey( "NUM_DSR",
+                                             dsdh_count, dsdh_entries );
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+011d",
+                 self->ds_info[dsd]->num_dsr );
+
+        key_index = S_NameValueList_FindKey( "DSR_SIZE",
+                                             dsdh_count, dsdh_entries );
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+011d",
+                 self->ds_info[dsd]->dsr_size );
+
+        if( S_NameValueList_Rewrite( self->fp, dsdh_count, dsdh_entries )
+            == FAILURE )
+            return FAILURE;
+
+        S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
+    }
+
+    self->header_dirty = 0;
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_Close
+
+Purpose:
+    Close an ENVISAT formatted file, releasing all associated resources.
+
+Description:
+
+Inputs:
+    self -- handle for file to close.
+
+Outputs:
+
+Returns:
+
+
+-----------------------------------------------------------------------------*/
+
+void EnvisatFile_Close( EnvisatFile *self )
+
+{
+    int                i;
+
+    /*
+     * Do we need to write out the header information?
+     */
+    if( self->header_dirty )
+        EnvisatFile_RewriteHeader( self );
+
+    /*
+     * Close file.
+     */
+    if( self->fp != NULL )
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( self->fp ));
+
+    /*
+     * Clean up data structures.
+     */
+    S_NameValueList_Destroy( &(self->mph_count), &(self->mph_entries) );
+    S_NameValueList_Destroy( &(self->sph_count), &(self->sph_entries) );
+
+    for( i = 0; i < self->ds_count; i++ )
+    {
+        if( self->ds_info != NULL && self->ds_info[i] != NULL )
+        {
+            CPLFree( self->ds_info[i]->ds_name );
+            CPLFree( self->ds_info[i]->ds_type );
+            CPLFree( self->ds_info[i]->filename );
+            CPLFree( self->ds_info[i] );
+        }
+    }
+    if( self->ds_info != NULL )
+        CPLFree( self->ds_info );
+    if( self->filename != NULL )
+        CPLFree( self->filename );
+
+    CPLFree( self );
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetFilename
+
+Purpose:
+    Fetch name of this Envisat file.
+
+Description:
+
+Inputs:
+    self -- handle for file to get name of.
+
+Outputs:
+
+Returns:
+    const pointer to internal copy of the filename.  Do not alter or free.
+
+
+-----------------------------------------------------------------------------*/
+
+const char *EnvisatFile_GetFilename( EnvisatFile *self )
+
+{
+    return self->filename;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetKeyByIndex()
+
+Purpose:
+    Fetch the key with the indicated index.
+
+Description:
+    This function can be used to "discover" the set of available keys by
+    by scanning with index values starting at zero and ending when a NULL
+    is returned.
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key_index -- key index, from zero to number of keys-1.
+
+Outputs:
+
+Returns:
+    pointer to key name or NULL on failure.
+
+-----------------------------------------------------------------------------*/
+
+const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self,
+                                       EnvisatFile_HeaderFlag mph_or_sph,
+                                       int key_index )
+
+{
+    int        entry_count;
+    EnvisatNameValue **entries;
+
+    /*
+     * Select source list.
+     */
+    if( mph_or_sph == MPH )
+    {
+        entry_count = self->mph_count;
+        entries = self->mph_entries;
+    }
+    else
+    {
+        entry_count = self->sph_count;
+        entries = self->sph_entries;
+    }
+
+    if( key_index < 0 || key_index >= entry_count )
+        return NULL;
+    else
+        return entries[key_index]->key;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetKeyValueAsString()
+
+Purpose:
+    Fetch the value associated with the indicated key as a string.
+
+Description:
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key -- the key (name) to be searched for.
+    default_value -- the value to return if the key is not found.
+
+Outputs:
+
+Returns:
+    pointer to value string, or default_value if not found.
+
+-----------------------------------------------------------------------------*/
+
+const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
+                                             EnvisatFile_HeaderFlag mph_or_sph,
+                                             const char *key,
+                                             const char *default_value )
+
+{
+    int        entry_count, key_index;
+    EnvisatNameValue **entries;
+
+    /*
+     * Select source list.
+     */
+    if( mph_or_sph == MPH )
+    {
+        entry_count = self->mph_count;
+        entries = self->mph_entries;
+    }
+    else
+    {
+        entry_count = self->sph_count;
+        entries = self->sph_entries;
+    }
+
+    /*
+     * Find and return the value.
+     */
+    key_index = S_NameValueList_FindKey( key, entry_count, entries );
+    if( key_index == -1 )
+        return default_value;
+    else
+        return entries[key_index]->value;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_SetKeyValueAsString()
+
+Purpose:
+    Set the value associated with the indicated key as a string.
+
+Description:
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key -- the key (name) to be searched for.
+    value -- the value to assign.
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
+                                     EnvisatFile_HeaderFlag mph_or_sph,
+                                     const char *key,
+                                     const char *value )
+
+{
+    int        entry_count, key_index;
+    EnvisatNameValue **entries;
+
+    if( !self->updatable )
+    {
+        SendError( "File not opened for update access." );
+        return FAILURE;
+    }
+
+    /*
+     * Select source list.
+     */
+    if( mph_or_sph == MPH )
+    {
+        entry_count = self->mph_count;
+        entries = self->mph_entries;
+    }
+    else
+    {
+        entry_count = self->sph_count;
+        entries = self->sph_entries;
+    }
+
+    /*
+     * Find and return the value.
+     */
+    key_index = S_NameValueList_FindKey( key, entry_count, entries );
+    if( key_index == -1 )
+    {
+        char   error_buf[2048];
+
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to set header field \"%s\", field not found.",
+                 key );
+
+        SendError( error_buf );
+        return FAILURE;
+    }
+
+    self->header_dirty = 1;
+    if( strlen(value) > strlen(entries[key_index]->value) )
+    {
+        strncpy( entries[key_index]->value, value,
+                 strlen(entries[key_index]->value) );
+    }
+    else
+    {
+        memset( entries[key_index]->value, ' ',
+                strlen(entries[key_index]->value) );
+        strncpy( entries[key_index]->value, value, strlen(value) );
+    }
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetKeyValueAsInt()
+
+Purpose:
+    Fetch the value associated with the indicated key as an integer.
+
+Description:
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key -- the key (name) to be searched for.
+    default_value -- the value to return if the key is not found.
+
+Outputs:
+
+Returns:
+    key value, or default_value if key not found.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
+                                  EnvisatFile_HeaderFlag mph_or_sph,
+                                  const char *key,
+                                  int default_value )
+
+{
+    int        entry_count, key_index;
+    EnvisatNameValue **entries;
+
+    /*
+     * Select source list.
+     */
+    if( mph_or_sph == MPH )
+    {
+        entry_count = self->mph_count;
+        entries = self->mph_entries;
+    }
+    else
+    {
+        entry_count = self->sph_count;
+        entries = self->sph_entries;
+    }
+
+    /*
+     * Find and return the value.
+     */
+    key_index = S_NameValueList_FindKey( key, entry_count, entries );
+    if( key_index == -1 )
+        return default_value;
+    else
+        return atoi(entries[key_index]->value);
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_SetKeyValueAsInt()
+
+Purpose:
+    Set the value associated with the indicated key as an integer.
+
+Description:
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key -- the key (name) to be searched for.
+    value -- the value to assign.
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
+                                  EnvisatFile_HeaderFlag mph_or_sph,
+                                  const char *key,
+                                  int value )
+
+{
+    char format[32], string_value[128];
+    const char *prototype_value;
+
+
+    prototype_value = EnvisatFile_GetKeyValueAsString( self, mph_or_sph, key, 
NULL);
+    if( prototype_value == NULL )
+    {
+        char   error_buf[2048];
+
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to set header field \"%s\", field not found.",
+                 key );
+
+        SendError( error_buf );
+        return FAILURE;
+    }
+
+    snprintf( format, sizeof(format), "%%+0%dd", (int) strlen(prototype_value) 
);
+    snprintf( string_value, sizeof(string_value), format, value );
+
+    return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, 
string_value );
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetKeyValueAsDouble()
+
+Purpose:
+    Fetch the value associated with the indicated key as a double.
+
+Description:
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key -- the key (name) to be searched for.
+    default_value -- the value to return if the key is not found.
+
+Outputs:
+
+Returns:
+    key value, or default_value if key not found.
+
+-----------------------------------------------------------------------------*/
+
+double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
+                                        EnvisatFile_HeaderFlag mph_or_sph,
+                                        const char *key,
+                                        double default_value )
+
+{
+    int        entry_count, key_index;
+    EnvisatNameValue **entries;
+
+    /*
+     * Select source list.
+     */
+    if( mph_or_sph == MPH )
+    {
+        entry_count = self->mph_count;
+        entries = self->mph_entries;
+    }
+    else
+    {
+        entry_count = self->sph_count;
+        entries = self->sph_entries;
+    }
+
+    /*
+     * Find and return the value.
+     */
+    key_index = S_NameValueList_FindKey( key, entry_count, entries );
+    if( key_index == -1 )
+        return default_value;
+    else
+        return atof(entries[key_index]->value);
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_SetKeyValueAsDouble()
+
+Purpose:
+    Set the value associated with the indicated key as a double.
+
+Description:
+    Note that this function attempts to format the new value similarly to
+    the previous value.  In some cases (especially exponential values) this
+    may not work out well.  In case of problems the caller is encourage to
+    format the value themselves, and use the EnvisatFile_SetKeyValueAsString
+    function, but taking extreme care about the string length.
+
+Inputs:
+    self -- the file to be searched.
+    mph_or_sph -- Either MPH or SPH depending on the header to be searched.
+    key -- the key (name) to be searched for.
+    value -- the value to assign.
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
+                                     EnvisatFile_HeaderFlag mph_or_sph,
+                                     const char *key,
+                                     double value )
+
+{
+    char format[32], string_value[128];
+    const char *prototype_value;
+    int                length;
+
+    prototype_value = EnvisatFile_GetKeyValueAsString( self, mph_or_sph, key, 
NULL);
+    if( prototype_value == NULL )
+    {
+        char   error_buf[2048];
+
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to set header field \"%s\", field not found.",
+                 key );
+
+        SendError( error_buf );
+        return FAILURE;
+    }
+
+    length = (int)strlen(prototype_value);
+    if( prototype_value[length-4] == 'E' )
+    {
+        snprintf( format, sizeof(format), "%%+%dE", length-4 );
+        snprintf( string_value, sizeof(string_value), format, value );
+    }
+    else
+    {
+        int    decimals = 0, i;
+        for( i = length-1; i > 0; i-- )
+        {
+            if( prototype_value[i] == '.' )
+                break;
+
+            decimals++;
+        }
+
+        snprintf( format, sizeof(format), "%%+0%d.%df", length, decimals );
+        CPLsnprintf( string_value, sizeof(string_value), format, value );
+
+        if( (int)strlen(string_value) > length )
+            string_value[length] = '\0';
+    }
+
+    return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, 
string_value );
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetDatasetIndex()
+
+Purpose:
+    Fetch the dataset index given a dataset name.
+
+Description:
+    The provided name is extended with spaces, so it isn't necessary for the
+    application to pass all the passing spaces.
+
+Inputs:
+    self -- the file to be searched.
+    ds_name -- the name (DS_NAME) of the dataset to find.
+
+Outputs:
+
+Returns:
+    Dataset index that matches, or -1 if none found.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
+
+{
+    int                i;
+    char       padded_ds_name[100];
+
+    /*
+     * Padd the name.  While the normal product spec says the DS_NAME will
+     * be 28 characters, I try to pad more than this in case the specification
+     * is changed.
+     */
+    strncpy( padded_ds_name, ds_name, sizeof(padded_ds_name) );
+    padded_ds_name[sizeof(padded_ds_name)-1] = 0;
+    for( i = (int)strlen(padded_ds_name); (size_t)i < 
sizeof(padded_ds_name)-1; i++ )
+    {
+        padded_ds_name[i] = ' ';
+    }
+    padded_ds_name[i] = '\0';
+
+    /*
+     * Compare only for the full length of DS_NAME we have saved.
+     */
+    for( i = 0; i < self->ds_count; i++ )
+    {
+        if( strncmp( padded_ds_name, self->ds_info[i]->ds_name,
+                     strlen(self->ds_info[i]->ds_name) ) == 0 )        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_GetDatasetInfo()
+
+Purpose:
+    Fetch the information associated with a dataset definition.
+
+Description:
+    The returned strings are pointers to internal copies, and should not be
+    modified, or freed.  Note, any of the "output" parameters can safely be
+    NULL if it is not needed.
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the dataset index to fetch
+
+Outputs:
+    ds_name -- the dataset symbolic name, i.e 'MDS1 SQ ADS              '.
+    ds_type -- the dataset type, i.e. 'A', not sure of valid values.
+    filename -- dataset filename, normally spaces, or 'NOT USED          '.
+    ds_offset -- the byte offset in the whole file to the first byte of
+                 dataset data.  This is 0 for unused datasets.
+    ds_size -- the size, in bytes, of the whole dataset.
+    num_dsr -- the number of records in the dataset.
+    dsr_size -- the size of one record in the dataset in bytes, -1 if
+                records are variable sized.
+
+Returns:
+    SUCCESS if dataset exists, or FAILURE if ds_index is out of range.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_GetDatasetInfo( EnvisatFile *self,
+                                int ds_index,
+                                char **ds_name,
+                                char **ds_type,
+                                char **filename,
+                                int  *ds_offset,
+                                int  *ds_size,
+                                int  *num_dsr,
+                                int  *dsr_size )
+
+{
+    if( ds_index < 0 || ds_index >= self->ds_count )
+        return FAILURE;
+
+    if( ds_name != NULL )
+        *ds_name = self->ds_info[ds_index]->ds_name;
+    if( ds_type != NULL )
+        *ds_type = self->ds_info[ds_index]->ds_type;
+    if( filename != NULL )
+        *filename = self->ds_info[ds_index]->filename;
+    if( ds_offset != NULL )
+        *ds_offset = self->ds_info[ds_index]->ds_offset;
+    if( ds_size != NULL )
+        *ds_size = self->ds_info[ds_index]->ds_size;
+    if( num_dsr != NULL )
+        *num_dsr = self->ds_info[ds_index]->num_dsr;
+    if( dsr_size != NULL )
+        *dsr_size = self->ds_info[ds_index]->dsr_size;
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_SetDatasetInfo()
+
+Purpose:
+    Update the information associated with a dataset definition.
+
+Description:
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the dataset index to fetch
+    ds_offset -- the byte offset in the whole file to the first byte of
+                 dataset data.  This is 0 for unused datasets.
+    ds_size -- the size, in bytes, of the whole dataset.
+    num_dsr -- the number of records in the dataset.
+    dsr_size -- the size of one record in the dataset in bytes, -1 if
+                records are variable sized.
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE.
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
+                                int ds_index,
+                                int ds_offset,
+                                int ds_size,
+                                int num_dsr,
+                                int dsr_size )
+
+{
+    if( ds_index < 0 || ds_index >= self->ds_count )
+        return FAILURE;
+
+    self->ds_info[ds_index]->ds_offset = ds_offset;
+    self->ds_info[ds_index]->ds_size = ds_size;
+    self->ds_info[ds_index]->num_dsr = num_dsr;
+    self->ds_info[ds_index]->dsr_size = dsr_size;
+    self->header_dirty = 1;
+
+    return SUCCESS;
+}
+
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_ReadDatasetChunk()
+
+Purpose:
+    Read an arbitrary chunk of a dataset.
+
+Description:
+    Note that no range checking is made on offset and size, and data may be
+    read from outside the dataset if they are inappropriate.
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the index of dataset to access.
+    offset -- byte offset within database to read.
+    size -- size of buffer to fill in bytes.
+    buffer -- buffer to load data into
+
+Outputs:
+    buffer is updated on SUCCESS.
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
+                                  int ds_index,
+                                  int offset,
+                                  int size,
+                                  void * buffer )
+
+{
+    if( ds_index < 0 || ds_index >= self->ds_count )
+    {
+        SendError( "Attempt to read non-existent dataset in "
+                   "EnvisatFile_ReadDatasetChunk()" );
+        return FAILURE;
+    }
+
+    if( offset < 0
+        || offset + size > self->ds_info[ds_index]->ds_size )
+    {
+        SendError( "Attempt to read beyond end of dataset in "
+                   "EnvisatFile_ReadDatasetChunk()" );
+        return FAILURE;
+    }
+
+    if( VSIFSeekL( self->fp, self->ds_info[ds_index]->ds_offset+offset, 
SEEK_SET )
+        != 0 )
+    {
+        SendError( "seek failed in EnvisatFile_ReadChunk()" );
+        return FAILURE;
+    }
+
+    if( (int) VSIFReadL( buffer, 1, size, self->fp ) != size )
+    {
+        SendError( "read failed in EnvisatFile_ReadChunk()" );
+        return FAILURE;
+    }
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_WriteDatasetRecord()
+
+Purpose:
+    Write an arbitrary dataset record.
+
+Description:
+    Note that no range checking is made on offset and size, and data may be
+    read from outside the dataset if they are inappropriate.
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the index of dataset to access.
+    record_index -- the record to write.
+    record_buffer -- buffer to load data into
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
+                                    int ds_index,
+                                    int record_index,
+                                    void *buffer )
+
+{
+    int                absolute_offset;
+    int         result;
+
+    if( ds_index < 0 || ds_index >= self->ds_count )
+    {
+        SendError( "Attempt to write non-existent dataset in "
+                   "EnvisatFile_WriteDatasetRecord()" );
+        return FAILURE;
+    }
+
+    if( record_index < 0
+        || record_index >=  self->ds_info[ds_index]->num_dsr )
+    {
+        SendError( "Attempt to write beyond end of dataset in "
+                   "EnvisatFile_WriteDatasetRecord()" );
+        return FAILURE;
+    }
+
+    absolute_offset = self->ds_info[ds_index]->ds_offset
+        + record_index * self->ds_info[ds_index]->dsr_size;
+
+    if( VSIFSeekL( self->fp, absolute_offset, SEEK_SET ) != 0 )
+    {
+        SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
+        return FAILURE;
+    }
+
+    result = (int)VSIFWriteL( buffer, 1, self->ds_info[ds_index]->dsr_size, 
self->fp );
+    if( result != self->ds_info[ds_index]->dsr_size )
+    {
+        SendError( "write failed in EnvisatFile_WriteDatasetRecord()" );
+        return FAILURE;
+    }
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_ReadDatasetRecord()
+
+Purpose:
+    Read an arbitrary dataset record.
+
+Description:
+    Note that no range checking is made on offset and size, and data may be
+    read from outside the dataset if they are inappropriate.
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the index of dataset to access.
+    record_index -- the record to write.
+    record_buffer -- buffer to load data into
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_ReadDatasetRecordChunk(EnvisatFile*,int,int,void*,int,int);
+
+int EnvisatFile_ReadDatasetRecord( EnvisatFile *self,
+                                    int ds_index,
+                                    int record_index,
+                                    void *buffer )
+{
+    return EnvisatFile_ReadDatasetRecordChunk( self,
+                ds_index, record_index, buffer, 0 , -1 ) ;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_ReadDatasetRecordChunk()
+
+Purpose:
+    Read a part of an arbitrary dataset record.
+
+Description:
+    Note that no range checking is made on dataset's offset and size,
+    and data may be read from outside the dataset if they are inappropriate.
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the index of dataset to access.
+    record_index -- the record to write.
+    record_buffer -- buffer to load data into
+    offset -- chunk offset relative to the record start (zerro offset)
+    size -- chunk size (set -1 to read from offset to the records' end)
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self,
+                                    int ds_index,
+                                    int record_index,
+                                    void *buffer,
+                                    int offset, int size )
+{
+    int                absolute_offset;
+    int         result;
+    int     dsr_size = self->ds_info[ds_index]->dsr_size ;
+
+    if (( offset < 0 )||(offset > dsr_size))
+    {
+        SendError( "Invalid chunk offset in "
+                   "EnvisatFile_ReadDatasetRecordChunk()" );
+        return FAILURE;
+    }
+
+    if ( size < 0 )
+        size = dsr_size - offset ;
+
+    if( ds_index < 0 || ds_index >= self->ds_count )
+    {
+        SendError( "Attempt to read non-existent dataset in "
+                   "EnvisatFile_ReadDatasetRecordChunk()" );
+        return FAILURE;
+    }
+
+    if( record_index < 0
+        || record_index >=  self->ds_info[ds_index]->num_dsr )
+    {
+        SendError( "Attempt to read beyond end of dataset in "
+                   "EnvisatFile_ReadDatasetRecordChunk()" );
+        return FAILURE;
+    }
+
+    if( (offset + size) > dsr_size )
+    {
+        SendError( "Attempt to read beyond the record's boundary"
+                   "EnvisatFile_ReadDatasetRecord()" );
+        return FAILURE;
+    }
+
+    absolute_offset = self->ds_info[ds_index]->ds_offset
+        + record_index * dsr_size + offset ;
+
+    if( VSIFSeekL( self->fp, absolute_offset, SEEK_SET ) != 0 )
+    {
+        SendError( "seek failed in EnvisatFile_ReadDatasetRecordChunk()" );
+        return FAILURE;
+    }
+
+    result = (int)VSIFReadL( buffer, 1, size, self->fp );
+    if( result != size )
+    {
+        SendError( "read failed in EnvisatFile_ReadDatasetRecord()" );
+        return FAILURE;
+    }
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    S_NameValueList_FindKey()
+
+Purpose:
+    Search for given key in list of name/value pairs.
+
+Description:
+    Scans list looking for index of EnvisatNameValue where the key matches
+    (case sensitive) the passed in name.
+
+Inputs:
+    key -- the key, such as "SLICE_POSITION" being searched for.
+    entry_count -- the number of items in the entries array.
+    entries -- array of name/value structures to search.
+
+Outputs:
+
+Returns:
+    array index into entries, or -1 on failure.
+
+-----------------------------------------------------------------------------*/
+
+int S_NameValueList_FindKey( const char *key,
+                             int entry_count,
+                             EnvisatNameValue **entries )
+
+{
+    int                i;
+
+    for( i = 0; i < entry_count; i++ )
+    {
+        if( strcmp(entries[i]->key,key) == 0 )
+            return i;
+    }
+
+    return -1;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    S_NameValueList_FindValue()
+
+Purpose:
+    Search for given key in list of name/value pairs, and return value.
+
+Description:
+    Returns value string or default if key not found.
+
+Inputs:
+    key -- the key, such as "SLICE_POSITION" being searched for.
+    entry_count -- the number of items in the entries array.
+    entries -- array of name/value structures to search.
+    default_value -- value to use if key not found.
+
+Outputs:
+
+Returns:
+    value string, or default if key not found.
+
+-----------------------------------------------------------------------------*/
+
+const char *S_NameValueList_FindValue( const char *key,
+                                       int entry_count,
+                                       EnvisatNameValue **entries,
+                                       const char *default_value )
+
+{
+    int                i;
+
+    i = S_NameValueList_FindKey( key, entry_count, entries );
+    if( i == -1 )
+        return default_value;
+    else
+        return entries[i]->value;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    S_NameValueList_Parse()
+
+Purpose:
+    Parse a block of envisat style name/value pairs into an
+    EnvisatNameValue structure list.
+
+Description:
+    The passed in text block should be zero terminated.  The entry_count,
+    and entries should be pre-initialized (normally to 0 and NULL).
+
+Inputs:
+    text -- the block of text, multiple lines, to be processed.
+
+Outputs:
+    entry_count -- returns with the updated number of entries in the
+                   entries array.
+    entries -- returns with updated array info structures.
+
+Returns:
+    SUCCESS or FAILURE
+
+-----------------------------------------------------------------------------*/
+
+int S_NameValueList_Parse( const char *text, int text_offset,
+                           int *entry_count,
+                           EnvisatNameValue ***entries )
+
+{
+    const char  *next_text = text;
+
+    /*
+     * Loop over each input line in the text block.
+     */
+    while( *next_text != '\0' )
+    {
+        char   line[1024];
+        int     line_len = 0;
+        int     equal_index = 0;
+        int     src_char = 0;
+        int     line_offset = 0;
+        EnvisatNameValue *entry = NULL;
+        /* workaround cppcheck false positive by using a pointer */
+        char* pszLine = line;
+
+        /*
+         * Extract one line of text into the "line" buffer, and remove the
+         * newline character.  Eat leading spaces.
+         */
+        while( *next_text == ' ' )
+        {
+            next_text++;
+        }
+        line_offset = (int) (next_text - text) + text_offset;
+        while( *next_text != '\0' && *next_text != '\n' )
+        {
+          if( line_len > ((int)sizeof(line) - 2) )
+            {
+                SendError( "S_NameValueList_Parse(): "
+                           "Corrupt line, longer than 1024 characters." );
+                return FAILURE;
+            }
+
+            pszLine[line_len++] = *(next_text++);
+        }
+
+        pszLine[line_len] = '\0';
+        if( *next_text == '\n' )
+            next_text++;
+
+        /*
+         * Blank lines are permitted.  We will skip processing of any line
+         * that doesn't have an equal sign, under the assumption it is
+         * white space.
+         */
+        if( strstr( line, "=") == NULL )
+            continue;
+
+        /*
+         * Create the name/value info structure.
+         */
+        entry = (EnvisatNameValue *) CPLCalloc(sizeof(EnvisatNameValue),1);
+        entry->literal_line = CPLStrdup(line);
+
+        /*
+         * Capture the key.  We take everything up to the equal sign.  There
+         * should not be any white space, but if so, we take it as part of the
+         * key.
+         */
+        equal_index = (int)(strstr(line, "=") - line);
+        entry->key = (char *) CPLMalloc(equal_index+1);
+        strncpy( entry->key, line, equal_index );
+        entry->key[equal_index] = '\0';
+        entry->value_offset = line_offset + equal_index + 1;
+
+        /*
+         * If the next character after the equal sign is a double quote, then
+         * the value is a string.  Suck out the text between the double quotes.
+         */
+        if( line[equal_index+1] == '"' )
+        {
+            for( src_char = equal_index + 2;
+                 line[src_char] != '\0' && line[src_char] != '"';
+                 src_char++ ) {}
+
+            line[src_char] = '\0';
+            entry->value = CPLStrdup(line + equal_index + 2);
+            entry->value_len = strlen(entry->value)+1;
+            entry->value_offset += 1;
+        }
+
+        /*
+         * The value is numeric, and may include a units field.
+         */
+        else
+        {
+            for( src_char = equal_index + 1;
+                 line[src_char] != '\0' && line[src_char] != '<'
+                     && line[src_char] != ' ';
+                 src_char++ ) {}
+
+            /* capture units */
+            if( line[src_char] == '<' )
+            {
+                int dst_char;
+
+                for( dst_char = src_char+1;
+                     line[dst_char] != '>' && line[dst_char] != '\0';
+                     dst_char++ ) {}
+
+                line[dst_char] = '\0';
+                entry->units = CPLStrdup( line + src_char + 1 );
+            }
+
+            line[src_char] = '\0';
+            entry->value = CPLStrdup( line + equal_index + 1 );
+            entry->value_len = strlen(entry->value)+1;
+        }
+
+        /*
+         * Add the entry to the name/value list.
+         */
+        (*entry_count)++;
+        *entries = (EnvisatNameValue **)
+            CPLRealloc( *entries, *entry_count * sizeof(EnvisatNameValue*) );
+
+        if( *entries == NULL )
+        {
+            *entry_count = 0;
+            CPLFree(entry);
+            return FAILURE;
+        }
+
+        (*entries)[*entry_count-1] = entry;
+    }
+
+    return SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    S_NameValueList_Rewrite()
+
+Purpose:
+    Rewrite the values of a name/value list in the file.
+
+Description:
+
+Inputs:
+    fp -- the VSILFILE to operate on.
+    entry_count -- number of entries to write.
+    entries -- array of entry descriptions.
+
+Returns:
+    SUCCESS or FAILURE
+
+
+-----------------------------------------------------------------------------*/
+
+int S_NameValueList_Rewrite( VSILFILE * fp, int entry_count,
+                              EnvisatNameValue **entries )
+
+{
+    int                i;
+
+    for( i = 0; i < entry_count; i++ )
+    {
+        EnvisatNameValue       *entry = entries[i];
+
+        if( VSIFSeekL( fp, entry->value_offset, SEEK_SET ) != 0 )
+        {
+            SendError( "VSIFSeekL() failed writing name/value list." );
+            return FAILURE;
+        }
+
+        if( VSIFWriteL( entry->value, 1, strlen(entry->value), fp ) !=
+            strlen(entry->value) )
+        {
+            SendError( "VSIFWriteL() failed writing name/value list." );
+            return FAILURE;
+        }
+    }
+
+    return SUCCESS;
+}
+
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    S_NameValueList_Destroy()
+
+Purpose:
+    Free resources associated with a name/value list.
+
+Description:
+    The count, and name/value list pointers are set to 0/NULL on completion.
+
+Inputs:
+    entry_count -- returns with the updated number of entries in the
+                   entries array.
+    entries -- returns with updated array info structures.
+
+Outputs:
+    entry_count -- Set to zero.
+    entries -- Sett o NULL.
+
+Returns:
+
+
+-----------------------------------------------------------------------------*/
+
+void S_NameValueList_Destroy( int *entry_count,
+                              EnvisatNameValue ***entries )
+
+{
+    int                i;
+
+    for( i = 0; i < *entry_count; i++ )
+    {
+        CPLFree( (*entries)[i]->key );
+        CPLFree( (*entries)[i]->value );
+        CPLFree( (*entries)[i]->units );
+        CPLFree( (*entries)[i]->literal_line );
+        CPLFree( (*entries)[i] );
+    }
+
+    CPLFree( *entries );
+
+    *entry_count = 0;
+    *entries = NULL;
+}
+
+/* EOF */

Copied: brlcad/trunk/src/other/gdal/frmts/EnvisatFile.h (from rev 76810, 
brlcad/trunk/src/other/gdal/frmts/envisat/EnvisatFile.h)
===================================================================
--- brlcad/trunk/src/other/gdal/frmts/EnvisatFile.h                             
(rev 0)
+++ brlcad/trunk/src/other/gdal/frmts/EnvisatFile.h     2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -0,0 +1,132 @@
+/******************************************************************************
+ * $Id: EnvisatFile.h 34521 2016-07-02 21:26:43Z goatbar $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  Low Level Envisat file access (read/write) API.
+ * Author:   Frank Warmerdam, [email protected]
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, Atlantis Scientific, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef ENVISAT_FILE_H_
+#define ENVISAT_FILE_H_
+
+typedef struct EnvisatFile_tag EnvisatFile;
+
+typedef enum
+{
+    MPH = 0,
+    SPH = 1
+} EnvisatFile_HeaderFlag;
+
+int EnvisatFile_Open( EnvisatFile **self, const char *filename,
+                      const char *mode );
+void EnvisatFile_Close( EnvisatFile *self );
+const char *EnvisatFile_GetFilename( EnvisatFile *self );
+int EnvisatFile_Create( EnvisatFile **self, const char *filename,
+                        const char *template_file );
+int EnvisatFile_GetCurrentLength( EnvisatFile *self );
+
+const char* EnvisatFile_GetKeyByIndex(  EnvisatFile *self,
+                                        EnvisatFile_HeaderFlag mph_or_sph,
+                                        int key_index );
+
+int EnvisatFile_TestKey(  EnvisatFile *self,
+                          EnvisatFile_HeaderFlag mph_or_sph,
+                          const char *key );
+
+const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
+                                             EnvisatFile_HeaderFlag mph_or_sph,
+                                             const char *key,
+                                             const char *default_value );
+
+int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
+                                     EnvisatFile_HeaderFlag mph_or_sph,
+                                     const char *key,
+                                     const char *value );
+
+int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
+                                  EnvisatFile_HeaderFlag mph_or_sph,
+                                  const char *key,
+                                  int default_value );
+
+int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
+                                  EnvisatFile_HeaderFlag mph_or_sph,
+                                  const char *key,
+                                  int value );
+
+double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
+                                        EnvisatFile_HeaderFlag mph_or_sph,
+                                        const char *key,
+                                        double default_value );
+int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
+                                     EnvisatFile_HeaderFlag mph_or_sph,
+                                     const char *key,
+                                     double value );
+
+int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name );
+
+int EnvisatFile_GetDatasetInfo( EnvisatFile *self,
+                                int ds_index,
+                                char **ds_name,
+                                char **ds_type,
+                                char **filename,
+                                int  *ds_offset,
+                                int  *ds_size,
+                                int  *num_dsr,
+                                int  *dsr_size );
+int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
+                                int ds_index,
+                                int ds_offset,
+                                int ds_size,
+                                int num_dsr,
+                                int dsr_size );
+
+int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self,
+                                    int ds_index,
+                                    int record_index,
+                                    void *buffer,
+                                    int offset, int size ) ;
+int EnvisatFile_ReadDatasetRecord( EnvisatFile *self,
+                                   int ds_index,
+                                   int record_index,
+                                   void *record_buffer );
+int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
+                                    int ds_index,
+                                    int record_index,
+                                    void *record_buffer );
+int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
+                                  int ds_index,
+                                  int offset,
+                                  int size,
+                                  void *buffer );
+
+#ifndef FAILURE
+#  define FAILURE 1
+#endif
+#ifndef SUCCESS
+#  define SUCCESS 0
+#endif
+
+#endif /* ENVISAT_FILE_H_ */
+
+/* EOF */

Copied: brlcad/trunk/src/other/gdal/frmts/IdrisiDataset.cpp (from rev 76810, 
brlcad/trunk/src/other/gdal/frmts/idrisi/IdrisiDataset.cpp)
===================================================================
--- brlcad/trunk/src/other/gdal/frmts/IdrisiDataset.cpp                         
(rev 0)
+++ brlcad/trunk/src/other/gdal/frmts/IdrisiDataset.cpp 2020-08-17 01:55:50 UTC 
(rev 76811)
@@ -0,0 +1,3309 @@
+/*****************************************************************************
+*
+* Project:  Idrisi Raster Image File Driver
+* Purpose:  Read/write Idrisi Raster Image Format RST
+* Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
+*
+* Revised by Hongmei Zhu, February, 2013
+* [email protected]
+* Clark Labs/Clark University
+*
+******************************************************************************
+* Copyright( c ) 2006, Ivan Lucena
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot 
org>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files( the "Software" ),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "cpl_csv.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_alg.h"
+#include "gdal_priv.h"
+#include "gdal_rat.h"
+#include "ogr_spatialref.h"
+#include "idrisi.h"
+
+#include <cmath>
+
+CPL_CVSID( "$Id: IdrisiDataset.cpp 38148 2017-04-26 20:18:07Z rouault $" );
+
+#ifdef WIN32
+#  define PATHDELIM       '\\'
+#else
+#  define PATHDELIM       '/'
+#endif
+
+//----- Safe numeric conversion, NULL as zero
+#define atoi_nz(s) (s == NULL ? (int)      0 : atoi(s))
+#define CPLAtof_nz(s) (s == NULL ? (double) 0.0 : CPLAtof(s))
+
+//----- file extensions:
+static const char * const extRST = "rst";
+static const char * const extRDC         = "rdc";
+static const char * const extSMP         = "smp";
+static const char * const extREF         = "ref";
+// static const char * const extRSTu        = "RST";
+static const char * const extRDCu        = "RDC";
+static const char * const extSMPu        = "SMP";
+static const char * const extREFu        = "REF";
+
+//----- field names on rdc file:
+static const char * const rdcFILE_FORMAT  = "file format ";
+static const char * const rdcFILE_TITLE   = "file title  ";
+static const char * const rdcDATA_TYPE    = "data type   ";
+static const char * const rdcFILE_TYPE    = "file type   ";
+static const char * const rdcCOLUMNS      = "columns     ";
+static const char * const rdcROWS         = "rows        ";
+static const char * const rdcREF_SYSTEM   = "ref. system ";
+static const char * const rdcREF_UNITS    = "ref. units  ";
+static const char * const rdcUNIT_DIST    = "unit dist.  ";
+static const char * const rdcMIN_X        = "min. X      ";
+static const char * const rdcMAX_X        = "max. X      ";
+static const char * const rdcMIN_Y        = "min. Y      ";
+static const char * const rdcMAX_Y        = "max. Y      ";
+static const char * const rdcPOSN_ERROR   = "pos'n error ";
+static const char * const rdcRESOLUTION   = "resolution  ";
+static const char * const rdcMIN_VALUE    = "min. value  ";
+static const char * const rdcMAX_VALUE    = "max. value  ";
+static const char * const rdcDISPLAY_MIN  = "display min ";
+static const char * const rdcDISPLAY_MAX  = "display max ";
+static const char * const rdcVALUE_UNITS  = "value units ";
+static const char * const rdcVALUE_ERROR  = "value error ";
+static const char * const rdcFLAG_VALUE   = "flag value  ";
+static const char * const rdcFLAG_DEFN    = "flag def'n  ";
+static const char * const rdcFLAG_DEFN2   = "flag def`n  ";
+static const char * const rdcLEGEND_CATS  = "legend cats ";
+static const char * const rdcLINEAGES     = "lineage     ";
+static const char * const rdcCOMMENTS     = "comment     ";
+static const char * const rdcCODE_N       = "code %6d ";
+
+//----- ".ref" file field names:
+static const char * const refREF_SYSTEM   = "ref. system ";
+static const char * const refREF_SYSTEM2  = "ref.system  ";
+static const char * const refPROJECTION   = "projection  ";
+static const char * const refDATUM        = "datum       " ;
+static const char * const refDELTA_WGS84  = "delta WGS84 " ;
+static const char * const refELLIPSOID    = "ellipsoid   ";
+static const char * const refMAJOR_SAX    = "major s-ax  " ;
+static const char * const refMINOR_SAX    = "minor s-ax  ";
+static const char * const refORIGIN_LONG  = "origin long ";
+static const char * const refORIGIN_LAT   = "origin lat  ";
+static const char * const refORIGIN_X     = "origin X    ";
+static const char * const refORIGIN_Y     = "origin Y    ";
+static const char * const refSCALE_FAC    = "scale fac   ";
+static const char * const refUNITS        = "units       ";
+static const char * const refPARAMETERS   = "parameters  ";
+static const char * const refSTANDL_1     = "stand ln 1  ";
+static const char * const refSTANDL_2     = "stand ln 2  ";
+
+//----- standard values:
+static const char * const rstVERSION      = "Idrisi Raster A.1";
+static const char * const rstBYTE         = "byte";
+static const char * const rstINTEGER      = "integer";
+static const char * const rstREAL         = "real";
+static const char * const rstRGB24        = "rgb24";
+static const char * const rstDEGREE       = "deg";
+static const char * const rstMETER        = "m";
+static const char * const rstLATLONG      = "latlong";
+static const char * const rstLATLONG2     = "lat/long";
+static const char * const rstPLANE        = "plane";
+static const char * const rstUTM          = "utm-%d%c";
+static const char * const rstSPC          = "spc%2d%2s%d";
+
+//----- palette file( .smp ) header size:
+static const int smpHEADERSIZE = 18;
+
+//----- check if file exists:
+bool FileExists( const char *pszPath );
+
+//----- Reference Table
+struct ReferenceTab {
+    int nCode;
+    const char *pszName;
+};
+
+//----- USA State's reference table to USGS PCS Code
+static const ReferenceTab aoUSStateTable[] = {
+    {101,     "al"},
+    {201,     "az"},
+    {301,     "ar"},
+    {401,     "ca"},
+    {501,     "co"},
+    {600,     "ct"},
+    {700,     "de"},
+    {901,     "fl"},
+    {1001,    "ga"},
+    {1101,    "id"},
+    {1201,    "il"},
+    {1301,    "in"},
+    {1401,    "ia"},
+    {1501,    "ks"},
+    {1601,    "ky"},
+    {1701,    "la"},
+    {1801,    "me"},
+    {1900,    "md"},
+    {2001,    "ma"},
+    {2111,    "mi"},
+    {2201,    "mn"},
+    {2301,    "ms"},
+    {2401,    "mo"},
+    {2500,    "mt"},
+    {2600,    "ne"},
+    {2701,    "nv"},
+    {2800,    "nh"},
+    {2900,    "nj"},
+    {3001,    "nm"},
+    {3101,    "ny"},
+    {3200,    "nc"},
+    {3301,    "nd"},
+    {3401,    "oh"},
+    {3501,    "ok"},
+    {3601,    "or"},
+    {3701,    "pa"},
+    {3800,    "ri"},
+    {3900,    "sc"},
+    {4001,    "sd"},
+    {4100,    "tn"},
+    {4201,    "tx"},
+    {4301,    "ut"},
+    {4400,    "vt"},
+    {4501,    "va"},
+    {4601,    "wa"},
+    {4701,    "wv"},
+    {4801,    "wv"},
+    {4901,    "wy"},
+    {5001,    "ak"},
+    {5101,    "hi"},
+    {5200,    "pr"}
+};
+
+//---- The origin table for USA State Plane Systems
+struct OriginTab83 {
+    double longitude;
+    double latitude;
+    const char *spcs;
+};
+
+static const int ORIGIN_COUNT = 148;
+
+//---- USA State plane coordinate system in IDRISI
+static const OriginTab83 SPCS83Origin[] = {
+        {85.83,   30.50,    "SPC83AL1"},
+        {87.50,   30.00,    "SPC83AL2"},
+        {176.00,  51.00,    "SPC83AK0"},
+        {142.00,  54.00,    "SPC83AK2"},
+        {146.00,  54.00,    "SPC83AK3"},
+        {150.00,  54.00,    "SPC83AK4"},
+        {154.00,  54.00,    "SPC83AK5"},
+        {158.00,  54.00,    "SPC83AK6"},
+        {162.00,  54.00,    "SPC83AK7"},
+        {166.00,  54.00,    "SPC83AK8"},
+        {170.00,  54.00,    "SPC83AK9"},
+        {110.17,  31.00,    "SPC83AZ1"},
+        {111.92,  31.00,    "SPC83AZ2"},
+        {113.75,  31.00,    "SPC83AZ3"},
+        {92.00,   34.33,    "SPC83AR1"},
+        {92.00,   32.67,    "SPC83AR2"},
+        {122.00,  39.33,    "SPC83CA1"},
+        {122.00,  37.67,    "SPC83CA2"},
+        {120.50,  36.50,    "SPC83CA3"},
+        {119.00,  35.33,    "SPC83CA4"},
+        {118.00,  33.50,    "SPC83CA5"},
+        {116.25,  32.17,    "SPC83CA6"},
+        {105.50,  39.33,    "SPC83CO1"},
+        {105.50,  37.83,    "SPC83CO2"},
+        {105.50,  36.67,    "SPC83CO3"},
+        {72.75,   40.83,    "SPC83CT1"},
+        {75.42,   38.00,    "SPC83DE1"},
+        {81.00,   24.33,    "SPC83FL1"},
+        {82.00,   24.33,    "SPC83FL2"},
+        {84.50,   29.00,    "SPC83FL3"},
+        {82.17,   30.00,    "SPC83GA1"},
+        {84.17,   30.00,    "SPC83GA2"},
+        {155.50,  18.83,    "SPC83HI1"},
+        {156.67,  20.33,    "SPC83HI2"},
+        {158.00,  21.17,    "SPC83HI3"},
+        {159.50,  21.83,    "SPC83HI4"},
+        {160.17,  21.67,    "SPC83HI5"},
+        {112.17,  41.67,    "SPC83ID1"},
+        {114.00,  41.67,    "SPC83ID2"},
+        {115.75,  41.67,    "SPC83ID3"},
+        {88.33,   36.67,    "SPC83IL1"},
+        {90.17,   36.67,    "SPC83IL1"},
+        {85.67,   37.50,    "SPC83IN1"},
+        {87.08,   37.50,    "SPC83IN2"},
+        {93.50,   41.50,    "SPC83IA1"},
+        {93.50,   40.00,    "SPC83IA1"},
+        {98.00,   38.33,    "SPC83KS1"},
+        {98.50,   36.67,    "SPC83KS2"},
+        {84.25,   37.50,    "SPC83KY1"},
+        {85.75,   36.33,    "SPC83KY2"},
+        {92.50,   30.50,    "SPC83LA1"},
+        {91.33,   28.50,    "SPC83LA2"},
+        {91.33,   25.50,    "SPC83LA3"},
+        {92.50,   30.67,    "SPC27LA1"},//NAD27 system
+        {91.33,   28.67,    "SPC27LA2"},
+        {91.33,   25.67,    "SPC27LA3"},//
+        {68.50,   43.67,    "SPC83ME1"},
+        {68.50,   43.83,    "SPC27ME1"},//NAD27
+        {70.17,   42.83,    "SPC83ME2"},
+        {77.00,   37.67,    "SPC83MD1"},//
+        {77.00,   37.83,    "SPC27MD1"},//NAD27
+        {71.50,   41.00,    "SPC83MA1"},
+        {70.50,   41.00,    "SPC83MA2"},
+        {87.00,   44.78,    "SPC83MI1"},
+        {84.37,   43.32,    "SPC83MI2"},
+        {84.37,   41.50,    "SPC83MI3"},
+        {84.33,   43.32,    "SPC27MI2"},//NAD27 L
+        {84.33,   41.50,    "SPC27MI3"},//NAD27 L
+        {83.67,   41.50,    "SPC27MI4"},//NAD27 TM
+        {85.75,   41.50,    "SPC27MI5"},//NAD27 TM
+        {88.75,   41.50,    "SPC27MI6"},//NAD27 TM
+        {93.10,   46.50,    "SPC83MN1"},
+        {94.25,   45.00,    "SPC83MN2"},
+        {94.00,   43.00,    "SPC83MN3"},
+        {88.83,   29.50,    "SPC83MS1"},
+        {90.33,   29.50,    "SPC83MS2"},
+        {88.83,   29.67,    "SPC83MS1"},//NAD27
+        {90.33,   30.50,    "SPC83MS2"},//
+        {90.50,   35.83,    "SPC83MO1"},
+        {92.50,   35.83,    "SPC83MO2"},
+        {94.50,   36.17,    "SPC83MO3"},
+        {109.50,  44.25,    "SPC83MT1"},
+        {109.50,  47.00,    "SPC27MT1"},//NAD27
+        {109.50,  45.83,    "SPC27MT2"},
+        {109.50,  44.00,    "SPC27MT3"},//
+        {100.00,  39.83,    "SPC83NE1"},
+        {115.58,  34.75,    "SPC83NV1"},
+        {116.67,  34.75,    "SPC83NV2"},
+        {118.58,  34.75,    "SPC83NV3"},
+        {71.67,   42.50,    "SPC83NH1"},
+        {74.50,   38.83,    "SPC83NJ1"},
+        {74.67,   38.83,    "SPC27NJ1"},//NAD27
+        {104.33,  31.00,    "SPC83NM1"},
+        {106.25,  31.00,    "SPC83NM2"},
+        {107.83,  31.00,    "SPC83NM3"},
+        {74.50,   38.83,    "SPC83NY1"},
+        {76.58,   40.00,    "SPC83NY2"},
+        {78.58,   40.00,    "SPC83NY3"},
+        {74.00,   40.17,    "SPC83NY4"},
+        {74.33,   40.00,    "SPC27NY1"},//NAD27
+        {74.00,   40.50,    "SPC27NY4"},//
+        {79.00,   33.75,    "SPC83NC1"},
+        {100.50,  47.00,    "SPC83ND1"},
+        {100.50,  45.67,    "SPC83ND2"},
+        {82.50,   39.67,    "SPC83OH1"},
+        {82.50,   38.00,    "SPC83OH2"},
+        {98.00,   35.00,    "SPC83OK1"},
+        {98.00,   33.33,    "SPC83OK2"},
+        {120.50,  43.67,    "SPC83OR1"},
+        {120.50,  41.67,    "SPC83OR2"},
+        {77.75,   40.17,    "SPC83PA1"},
+        {77.75,   39.33,    "SPC83PA2"},
+        {71.50,   41.08,    "SPC83RI1"},
+        {81.00,   31.83,    "SPC83SC1"},
+        {81.00,   33.00,    "SPC27SC1"},//NAD27
+        {81.00,   31.83,    "SPC27SC2"},//NAD27
+        {100.00,  43.83,    "SPC83SD1"},
+        {100.33,  42.33,    "SPC83SD2"},
+        {86.00,   34.33,    "SPC83TN1"},
+        {86.00,   34.67,    "SPC27TN1"},//NAD27
+        {101.50,  34.00,    "SPC83TX1"},//
+        {98.50,   31.67,    "SPC83TX2"},
+        {100.33,  29.67,    "SPC83TX3"},
+        {99.00,   27.83,    "SPC83TX4"},
+        {98.50,   25.67,    "SPC83TX5"},
+        {97.50,   31.67,    "SPC27TX2"},//NAD27
+        {111.50,  40.33,    "SPC83UT1"},
+        {111.50,  38.33,    "SPC83UT2"},
+        {111.50,  36.67,    "SPC83UT3"},
+        {72.50,   42.50,    "SPC83VT1"},
+        {78.50,   37.67,    "SPC83VA1"},
+        {78.50,   36.33,    "SPC83VA2"},
+        {120.83,  47.00,    "SPC83WA1"},
+        {120.50,  45.33,    "SPC83WA2"},
+        {79.50,   38.50,    "SPC83WV1"},
+        {81.00,   37.00,    "SPC83WV2"},
+        {90.00,   45.17,    "SPC83WI1"},
+        {90.00,   43.83,    "SPC83WI2"},
+        {90.00,   42.00,    "SPC83WI3"},
+        {105.17,  40.50,    "SPC83WY1"},
+        {107.33,  40.50,    "SPC83WY2"},
+        {108.75,  40.50,    "SPC83WY3"},
+        {110.08,  40.50,    "SPC83WY4"},
+        {105.17,  40.67,    "SPC27WY1"},//NAD27
+        {105.33,  40.67,    "SPC27WY2"},
+        {108.75,  40.67,    "SPC27WY3"},
+        {110.08,  40.67,    "SPC27WY4"},//
+        {66.43,   17.83,    "SPC83PR1"}
+};
+
+//Get IDRISI State Plane name by origin
+char *GetSpcs(double dfLon, double dfLat);
+
+//change NAD from 83 to 27
+void NAD83to27( char *pszOutRef, char *pszInRef);
+
+#define US_STATE_COUNT ( sizeof( aoUSStateTable ) / sizeof( ReferenceTab ) )
+
+//----- Get the Code of a US State
+int GetStateCode ( const char *pszState );
+
+//----- Get the state name of a Code
+const char *GetStateName( int nCode );
+
+//----- Conversion Table definition
+struct ConversionTab {
+    const char *pszName;
+    int nDefaultI;
+    int nDefaultG;
+    double dfConv;
+};
+
+//----- Linear Unit Conversion Table
+static const ConversionTab aoLinearUnitsConv[] = {
+    {"m",            /*  0 */  0,   1,  1.0},
+    {SRS_UL_METER,   /*  1 */  0,   1,  1.0},
+    {"meters",       /*  2 */  0,   1,  1.0},
+    {"metre",        /*  3 */  0,   1,  1.0},
+
+    {"ft",           /*  4 */  4,   5,  0.3048},
+    {SRS_UL_FOOT,    /*  5 */  4,   5,  0.3048},
+    {"feet",         /*  6 */  4,   5,  0.3048},
+    {"foot_us",      /*  7 */  4,   5,  0.3048006},
+    {"u.s. foot",    /*  8 */  4,   5,  0.3048006},
+
+    {"mi",           /*  9 */  9,  10,  1612.9},
+    {"mile",         /* 10 */  9,  10,  1612.9},
+    {"miles",        /* 11 */  9,  10,  1612.9},
+
+    {"km",           /* 12 */ 12,  13,  1000.0},
+    {"kilometers",   /* 13 */ 12,  13,  1000.0},
+    {"kilometer",    /* 14 */ 12,  13,  1000.0},
+    {"kilometre",    /* 15 */ 12,  13,  1000.0},
+
+    {"deg",          /* 16 */ 16,  17,  0.0},
+    {SRS_UA_DEGREE,  /* 17 */ 16,  17,  0.0},
+    {"degrees",      /* 18 */ 16,  17,  0.0},
+
+    {"rad",          /* 19 */ 19,  20,  0.0},
+    {SRS_UA_RADIAN,  /* 20 */ 19,  20,  0.0},
+    {"radians",      /* 21 */ 19,  20,  0.0}
+};
+#define LINEAR_UNITS_COUNT (sizeof(aoLinearUnitsConv) / sizeof(ConversionTab))
+
+//----- Get the index of a given linear unit
+int GetUnitIndex( const char *pszUnitName );
+
+//----- Get the default name
+char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter = NULL );
+
+//----- Get the "to meter"
+int GetToMeterIndex( const char *pszToMeter );
+
+//----- CSLSaveCRLF
+int  SaveAsCRLF(char **papszStrList, const char *pszFname);
+
+//----- Classes pre-definition:
+class IdrisiRasterBand;
+
+//  
----------------------------------------------------------------------------
+//        Idrisi GDALDataset
+//  
----------------------------------------------------------------------------
+
+class IdrisiDataset : public GDALPamDataset
+{
+    friend class IdrisiRasterBand;
+
+private:
+    VSILFILE *fp;
+
+    char *pszFilename;
+    char *pszDocFilename;
+    char **papszRDC;
+    double adfGeoTransform[6];
+
+    char *pszProjection;
+    char **papszCategories;
+    char *pszUnitType;
+    // Move GeoReference2Wkt() into header file.
+    CPLErr Wkt2GeoReference( const char *pszProjString,
+        char **pszRefSystem,
+        char **pszRefUnit );
+
+protected:
+    GDALColorTable *poColorTable;
+
+public:
+    IdrisiDataset();
+    virtual ~IdrisiDataset();
+
+    static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
+    static GDALDataset *Create( const char *pszFilename,
+        int nXSize,
+        int nYSize,
+        int nBands,
+        GDALDataType eType,
+        char **papszOptions );
+    static GDALDataset *CreateCopy( const char *pszFilename,
+        GDALDataset *poSrcDS,
+        int bStrict,
+        char **papszOptions,
+        GDALProgressFunc pfnProgress,
+        void * pProgressData );
+    virtual char **GetFileList(void) override;
+    virtual CPLErr GetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double *padfTransform ) override;
+    virtual const char *GetProjectionRef( void ) override;
+    virtual CPLErr SetProjection( const char *pszProjString ) override;
+};
+
+//  
----------------------------------------------------------------------------
+//        Idrisi GDALPamRasterBand
+//  
----------------------------------------------------------------------------
+
+class IdrisiRasterBand : public GDALPamRasterBand
+{
+    friend class IdrisiDataset;
+
+    GDALRasterAttributeTable *poDefaultRAT;
+
+private:
+    int     nRecordSize;
+    GByte *pabyScanLine;
+
+public:
+    IdrisiRasterBand( IdrisiDataset *poDS,
+        int nBand,
+        GDALDataType eDataType );
+    virtual ~IdrisiRasterBand();
+
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) 
override;
+    virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage ) 
override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual char **GetCategoryNames() override;
+    virtual const char *GetUnitType() override;
+
+    virtual CPLErr SetCategoryNames( char **papszCategoryNames ) override;
+    virtual CPLErr SetNoDataValue( double dfNoDataValue ) override;
+    virtual CPLErr SetColorTable( GDALColorTable *poColorTable ) override;
+    virtual CPLErr SetUnitType( const char *pszUnitType ) override;
+    virtual CPLErr SetStatistics( double dfMin, double dfMax,
+                                  double dfMean, double dfStdDev ) override;
+    CPLErr SetMinMax( double dfMin, double dfMax );
+    virtual GDALRasterAttributeTable *GetDefaultRAT() override;
+    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * ) override;
+
+    float  fMaximum;
+    float  fMinimum;
+    bool   bFirstVal;
+};
+
+//  ------------------------------------------------------------------------  
//
+//                        Implementation of IdrisiDataset                     
//
+//  ------------------------------------------------------------------------  
//
+
+/************************************************************************/
+/*                           IdrisiDataset()                            */
+/************************************************************************/
+
+IdrisiDataset::IdrisiDataset() :
+    fp(NULL),
+    pszFilename(NULL),
+    pszDocFilename(NULL),
+    papszRDC(NULL),
+    pszProjection(NULL),
+    papszCategories(NULL),
+    pszUnitType(NULL),
+    poColorTable(new GDALColorTable())
+{
+
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+}
+
+/************************************************************************/
+/*                           ~IdrisiDataset()                           */
+/************************************************************************/
+
+IdrisiDataset::~IdrisiDataset()
+{
+    FlushCache();
+
+    if( papszRDC != NULL && eAccess == GA_Update  )
+    {
+        //int bSuccessMin = FALSE;
+        //int bSuccessMax = FALSE;
+
+        double dfMin = 0.0;
+        double dfMax = 0.0;
+        double dfMean = 0.0;
+        double dfStdDev = 0.0;
+
+        for( int i = 0; i < nBands; i++ )
+        {
+            IdrisiRasterBand *poBand = (IdrisiRasterBand*) GetRasterBand( i + 
1 );
+            poBand->ComputeStatistics( false, &dfMin, &dfMax, &dfMean, 
&dfStdDev, NULL, NULL);
+            /*
+              dfMin = poBand->GetMinimum( &bSuccessMin );
+              dfMax = poBand->GetMaximum( &bSuccessMax );
+
+              if( ! ( bSuccessMin && bSuccessMax ) )
+              {
+              poBand->GetStatistics( false, true, &dfMin, &dfMax, NULL, NULL );
+              }
+            */
+            poBand->SetMinMax( dfMin, dfMax);
+        }
+
+        CSLSetNameValueSeparator( papszRDC, ": " );
+        SaveAsCRLF( papszRDC, pszDocFilename );
+        CSLDestroy( papszRDC );
+    }
+
+    if( poColorTable )
+    {
+        delete poColorTable;
+    }
+    CPLFree( pszFilename );
+    CPLFree( pszDocFilename );
+    CPLFree( pszProjection );
+    CSLDestroy( papszCategories );
+    CPLFree( pszUnitType );
+
+    if( fp != NULL )
+        VSIFCloseL( fp );
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
+{
+    if(  ( poOpenInfo->fpL == NULL ) || (EQUAL( CPLGetExtension( 
poOpenInfo->pszFilename ), extRST ) == FALSE ))//modified
+        return NULL;
+
+    // --------------------------------------------------------------------
+    //      Check the documentation file .rdc
+    // --------------------------------------------------------------------
+
+    const char *pszLDocFilename = CPLResetExtension( poOpenInfo->pszFilename, 
extRDC );
+
+    if( ! FileExists( pszLDocFilename ) )
+    {
+        pszLDocFilename = CPLResetExtension( poOpenInfo->pszFilename, extRDCu 
);
+
+        if( ! FileExists( pszLDocFilename ) )
+        {
+            return NULL;
+        }
+    }
+
+    char **papszLRDC = CSLLoad( pszLDocFilename );
+
+    CSLSetNameValueSeparator( papszLRDC, ":" );
+
+    const char *pszVersion = CSLFetchNameValue( papszLRDC, rdcFILE_FORMAT );
+
+    if( pszVersion == NULL || !EQUAL( pszVersion, rstVERSION ) )
+    {
+        CSLDestroy( papszLRDC );
+        return NULL;
+    }
+
+    // --------------------------------------------------------------------
+    //      Create a corresponding GDALDataset
+    // --------------------------------------------------------------------
+
+    IdrisiDataset *poDS = new IdrisiDataset();
+    poDS->eAccess = poOpenInfo->eAccess;
+    poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
+
+    if( poOpenInfo->eAccess == GA_ReadOnly )
+    {
+        poDS->fp = VSIFOpenL( poDS->pszFilename, "rb" );
+    }
+    else
+    {
+        poDS->fp = VSIFOpenL( poDS->pszFilename, "r+b" );
+    }
+
+    if( poDS->fp == NULL )
+    {
+        CSLDestroy( papszLRDC );
+        delete poDS;
+        return NULL;
+    }
+
+    poDS->pszDocFilename = CPLStrdup( pszLDocFilename );
+    poDS->papszRDC = CSLDuplicate( papszLRDC );
+    CSLDestroy( papszLRDC );
+
+    // --------------------------------------------------------------------
+    //      Load information from rdc
+    // --------------------------------------------------------------------
+
+    poDS->nRasterXSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, 
rdcCOLUMNS ) );
+    poDS->nRasterYSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcROWS ) 
);
+    if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    // --------------------------------------------------------------------
+    //      Create band information
+    // --------------------------------------------------------------------
+
+    const char *pszDataType = CSLFetchNameValue( poDS->papszRDC, rdcDATA_TYPE 
);
+    if( pszDataType == NULL )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    if( EQUAL( pszDataType, rstBYTE ) )
+    {
+        poDS->nBands = 1;
+        poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Byte ) );
+    }
+    else if( EQUAL( pszDataType, rstINTEGER ) )
+    {
+        poDS->nBands = 1;
+        poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Int16 ) );
+    }
+    else if( EQUAL( pszDataType, rstREAL ) )
+    {
+        poDS->nBands = 1;
+        poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Float32 ) );
+    }
+    else if( EQUAL( pszDataType, rstRGB24 ) )
+    {
+        poDS->nBands = 3;
+        poDS->SetBand( 1, new IdrisiRasterBand( poDS, 1, GDT_Byte ) );
+        poDS->SetBand( 2, new IdrisiRasterBand( poDS, 2, GDT_Byte ) );
+        poDS->SetBand( 3, new IdrisiRasterBand( poDS, 3, GDT_Byte ) );
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown data type : %s", pszDataType);
+        delete poDS;
+        return NULL;
+    }
+
+    for(int i=0;i<poDS->nBands;i++)
+    {
+        IdrisiRasterBand* band = (IdrisiRasterBand*) poDS->GetRasterBand(i+1);
+        if (band->pabyScanLine == NULL)
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+
+    // --------------------------------------------------------------------
+    //      Load the transformation matrix
+    // --------------------------------------------------------------------
+
+    const char *pszMinX = CSLFetchNameValue( poDS->papszRDC, rdcMIN_X );
+    const char *pszMaxX = CSLFetchNameValue( poDS->papszRDC, rdcMAX_X );
+    const char *pszMinY = CSLFetchNameValue( poDS->papszRDC, rdcMIN_Y );
+    const char *pszMaxY = CSLFetchNameValue( poDS->papszRDC, rdcMAX_Y );
+    const char *pszUnit = CSLFetchNameValue( poDS->papszRDC, rdcUNIT_DIST );
+
+    if( pszMinX != NULL && strlen( pszMinX ) > 0 &&
+        pszMaxX != NULL && strlen( pszMaxX ) > 0 &&
+        pszMinY != NULL && strlen( pszMinY ) > 0 &&
+        pszMaxY != NULL && strlen( pszMaxY ) > 0 &&
+        pszUnit != NULL && strlen( pszUnit ) > 0 )
+    {
+        double dfMinX, dfMaxX, dfMinY, dfMaxY, dfUnit, dfXPixSz, dfYPixSz;
+
+        dfMinX = CPLAtof_nz( pszMinX );
+        dfMaxX = CPLAtof_nz( pszMaxX );
+        dfMinY = CPLAtof_nz( pszMinY );
+        dfMaxY = CPLAtof_nz( pszMaxY );
+        dfUnit = CPLAtof_nz( pszUnit );
+
+        dfMinX = dfMinX * dfUnit;
+        dfMaxX = dfMaxX * dfUnit;
+        dfMinY = dfMinY * dfUnit;
+        dfMaxY = dfMaxY * dfUnit;
+
+        dfYPixSz = ( dfMinY - dfMaxY ) / poDS->nRasterYSize;
+        dfXPixSz = ( dfMaxX - dfMinX ) / poDS->nRasterXSize;
+
+        poDS->adfGeoTransform[0] = dfMinX;
+        poDS->adfGeoTransform[1] = dfXPixSz;
+        poDS->adfGeoTransform[2] = 0.0;
+        poDS->adfGeoTransform[3] = dfMaxY;
+        poDS->adfGeoTransform[4] = 0.0;
+        poDS->adfGeoTransform[5] = dfYPixSz;
+    }
+
+    // --------------------------------------------------------------------
+    //      Set Color Table in the presence of a smp file
+    // --------------------------------------------------------------------
+
+    if( poDS->nBands != 3 )
+    {
+        const char *pszSMPFilename = CPLResetExtension( poDS->pszFilename, 
extSMP );
+        VSILFILE *fpSMP = VSIFOpenL( pszSMPFilename, "rb" );
+        if( fpSMP != NULL )
+        {
+            int dfMaxValue = atoi_nz( CSLFetchNameValue( poDS->papszRDC, 
rdcMAX_VALUE ) );
+            int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, 
rdcLEGEND_CATS ) );
+            if( nCatCount == 0 )
+                dfMaxValue = 255;
+            VSIFSeekL( fpSMP, smpHEADERSIZE, SEEK_SET );
+            GDALColorEntry oEntry;
+            unsigned char aucRGB[3];
+            int i = 0;
+            while( ( VSIFReadL( &aucRGB, sizeof( aucRGB ), 1, fpSMP ) ) &&( i 
<= dfMaxValue ) )
+            {
+                oEntry.c1 = (short) aucRGB[0];
+                oEntry.c2 = (short) aucRGB[1];
+                oEntry.c3 = (short) aucRGB[2];
+                oEntry.c4 = (short) 255;
+                poDS->poColorTable->SetColorEntry( i, &oEntry );
+                i++;
+            }
+            VSIFCloseL( fpSMP );
+        }
+    }
+
+    // --------------------------------------------------------------------
+    //      Check for Unit Type
+    // --------------------------------------------------------------------
+
+    const char *pszValueUnit = CSLFetchNameValue( poDS->papszRDC, 
rdcVALUE_UNITS );
+
+    if( pszValueUnit == NULL )
+        poDS->pszUnitType = CPLStrdup( "unspecified" );
+    else
+    {
+        if( STARTS_WITH_CI( pszValueUnit, "meter" ) )
+        {
+            poDS->pszUnitType = CPLStrdup( "m" );
+        }
+        else if( STARTS_WITH_CI(pszValueUnit, "feet") )
+        {
+            poDS->pszUnitType = CPLStrdup( "ft" );
+        }
+        else
+            poDS->pszUnitType = CPLStrdup( pszValueUnit );
+    }
+
+    // --------------------------------------------------------------------
+    //      Check for category names.
+    // --------------------------------------------------------------------
+
+    int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcLEGEND_CATS 
) );
+
+    if( nCatCount > 0 )
+    {
+        // ----------------------------------------------------------------
+        //      Sequentialize categories names, from 0 to the last "code n"
+        // ----------------------------------------------------------------
+
+        int nLine = -1;
+        for( int i = 0;( i < CSLCount( poDS->papszRDC ) ) &&( nLine == -1 ); 
i++ )
+            if( EQUALN( poDS->papszRDC[i], rdcLEGEND_CATS, 11 ) )
+                nLine = i;//get the line where legend cats is
+
+        if( nLine > 0 )
+        {
+            int nCode = 0;
+            int nCount = 0;

@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to