LCOV - code coverage report
Current view: top level - frmts/raw - byndataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 154 236 65.3 %
Date: 2025-08-01 10:10:57 Functions: 11 15 73.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Natural Resources Canada's Geoid BYN file format
       4             :  * Purpose:  Implementation of BYN format
       5             :  * Author:   Ivan Lucena, ivan.lucena@outlook.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2018, Ivan Lucena
       9             :  * Copyright (c) 2018, Even Rouault
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "byndataset.h"
      16             : #include "rawdataset.h"
      17             : 
      18             : #include "cpl_string.h"
      19             : #include "gdal_frmts.h"
      20             : #include "ogr_spatialref.h"
      21             : #include "ogr_srs_api.h"
      22             : 
      23             : #include <algorithm>
      24             : #include <cstdlib>
      25             : #include <limits>
      26             : 
      27             : // Specification at
      28             : // https://www.nrcan.gc.ca/sites/www.nrcan.gc.ca/files/earthsciences/pdf/gpshgrid_e.pdf
      29             : 
      30             : const static BYNEllipsoids EllipsoidTable[] = {
      31             :     {"GRS80", 6378137.0, 298.257222101},
      32             :     {"WGS84", 6378137.0, 298.257223564},
      33             :     {"ALT1", 6378136.3, 298.256415099},
      34             :     {"GRS67", 6378160.0, 298.247167427},
      35             :     {"ELLIP1", 6378136.46, 298.256415099},
      36             :     {"ALT2", 6378136.3, 298.257},
      37             :     {"ELLIP2", 6378136.0, 298.257},
      38             :     {"CLARKE 1866", 6378206.4, 294.9786982}};
      39             : 
      40             : /************************************************************************/
      41             : /*                            BYNRasterBand()                           */
      42             : /************************************************************************/
      43             : 
      44           4 : BYNRasterBand::BYNRasterBand(GDALDataset *poDSIn, int nBandIn,
      45             :                              VSILFILE *fpRawIn, vsi_l_offset nImgOffsetIn,
      46             :                              int nPixelOffsetIn, int nLineOffsetIn,
      47           4 :                              GDALDataType eDataTypeIn, int bNativeOrderIn)
      48             :     : RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
      49             :                     nLineOffsetIn, eDataTypeIn, bNativeOrderIn,
      50           4 :                     RawRasterBand::OwnFP::NO)
      51             : {
      52           4 : }
      53             : 
      54             : /************************************************************************/
      55             : /*                           ~BYNRasterBand()                           */
      56             : /************************************************************************/
      57             : 
      58           8 : BYNRasterBand::~BYNRasterBand()
      59             : {
      60           8 : }
      61             : 
      62             : /************************************************************************/
      63             : /*                           GetNoDataValue()                           */
      64             : /************************************************************************/
      65             : 
      66           0 : double BYNRasterBand::GetNoDataValue(int *pbSuccess)
      67             : {
      68           0 :     if (pbSuccess)
      69           0 :         *pbSuccess = TRUE;
      70           0 :     int bSuccess = FALSE;
      71           0 :     double dfNoData = GDALPamRasterBand::GetNoDataValue(&bSuccess);
      72           0 :     if (bSuccess)
      73             :     {
      74           0 :         return dfNoData;
      75             :     }
      76             :     const double dfFactor =
      77           0 :         cpl::down_cast<BYNDataset *>(poDS)->hHeader.dfFactor;
      78           0 :     return eDataType == GDT_Int16 ? 32767.0 : 9999.0 * dfFactor;
      79             : }
      80             : 
      81             : /************************************************************************/
      82             : /*                              GetScale()                              */
      83             : /************************************************************************/
      84             : 
      85           0 : double BYNRasterBand::GetScale(int *pbSuccess)
      86             : {
      87           0 :     if (pbSuccess != nullptr)
      88           0 :         *pbSuccess = TRUE;
      89             :     const double dfFactor =
      90           0 :         cpl::down_cast<BYNDataset *>(poDS)->hHeader.dfFactor;
      91           0 :     return (dfFactor != 0.0) ? 1.0 / dfFactor : 0.0;
      92             : }
      93             : 
      94             : /************************************************************************/
      95             : /* ==================================================================== */
      96             : /*                              BYNDataset                              */
      97             : /* ==================================================================== */
      98             : /************************************************************************/
      99             : 
     100           4 : BYNDataset::BYNDataset()
     101             :     : fpImage(nullptr), hHeader{0, 0, 0, 0, 0, 0,   0,   0, 0.0, 0,   0, 0,
     102           4 :                                 0, 0, 0, 0, 0, 0.0, 0.0, 0, 0,   0.0, 0}
     103             : {
     104           4 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     105           4 : }
     106             : 
     107             : /************************************************************************/
     108             : /*                            ~BYNDataset()                             */
     109             : /************************************************************************/
     110             : 
     111           8 : BYNDataset::~BYNDataset()
     112             : 
     113             : {
     114           4 :     BYNDataset::Close();
     115           8 : }
     116             : 
     117             : /************************************************************************/
     118             : /*                              Close()                                 */
     119             : /************************************************************************/
     120             : 
     121           8 : CPLErr BYNDataset::Close()
     122             : {
     123           8 :     CPLErr eErr = CE_None;
     124           8 :     if (nOpenFlags != OPEN_FLAGS_CLOSED)
     125             :     {
     126           4 :         if (BYNDataset::FlushCache(true) != CE_None)
     127           0 :             eErr = CE_Failure;
     128             : 
     129           4 :         if (fpImage != nullptr)
     130             :         {
     131           4 :             if (VSIFCloseL(fpImage) != 0)
     132             :             {
     133           0 :                 eErr = CE_Failure;
     134           0 :                 CPLError(CE_Failure, CPLE_FileIO, "I/O error");
     135             :             }
     136             :         }
     137             : 
     138           4 :         if (GDALPamDataset::Close() != CE_None)
     139           0 :             eErr = CE_Failure;
     140             :     }
     141           8 :     return eErr;
     142             : }
     143             : 
     144             : /************************************************************************/
     145             : /*                              Identify()                              */
     146             : /************************************************************************/
     147             : 
     148       57994 : int BYNDataset::Identify(GDALOpenInfo *poOpenInfo)
     149             : 
     150             : {
     151       57994 :     if (poOpenInfo->nHeaderBytes < BYN_HDR_SZ)
     152       54588 :         return FALSE;
     153             : 
     154             : /* -------------------------------------------------------------------- */
     155             : /*      Check file extension (.byn/.err)                                */
     156             : /* -------------------------------------------------------------------- */
     157             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     158        3406 :     const char *pszFileExtension = poOpenInfo->osExtension.c_str();
     159             : 
     160        3406 :     if (!EQUAL(pszFileExtension, "byn") && !EQUAL(pszFileExtension, "err"))
     161             :     {
     162        3398 :         return FALSE;
     163             :     }
     164             : #endif
     165             : 
     166             :     /* -------------------------------------------------------------------- */
     167             :     /*      Check some value's ranges on header                             */
     168             :     /* -------------------------------------------------------------------- */
     169             : 
     170           8 :     BYNHeader hHeader = {0, 0, 0, 0, 0, 0,   0,   0, 0.0, 0,   0, 0,
     171             :                          0, 0, 0, 0, 0, 0.0, 0.0, 0, 0,   0.0, 0};
     172             : 
     173           8 :     buffer2header(poOpenInfo->pabyHeader, &hHeader);
     174             : 
     175           8 :     if (hHeader.nGlobal < 0 || hHeader.nGlobal > 1 || hHeader.nType < 0 ||
     176           8 :         hHeader.nType > 9 || (hHeader.nSizeOf != 2 && hHeader.nSizeOf != 4) ||
     177           8 :         hHeader.nVDatum < 0 || hHeader.nVDatum > 3 || hHeader.nDescrip < 0 ||
     178           8 :         hHeader.nDescrip > 3 || hHeader.nSubType < 0 || hHeader.nSubType > 9 ||
     179           8 :         hHeader.nDatum < 0 || hHeader.nDatum > 1 || hHeader.nEllipsoid < 0 ||
     180           8 :         hHeader.nEllipsoid > 7 || hHeader.nByteOrder < 0 ||
     181           8 :         hHeader.nByteOrder > 1 || hHeader.nScale < 0 || hHeader.nScale > 1)
     182           0 :         return FALSE;
     183             : 
     184             : #if 0
     185             :     // We have disabled those checks as invalid values are often found in some
     186             :     // datasets, such as http://s3.microsurvey.com/os/fieldgenius/geoids/Lithuania.zip
     187             :     // We don't use those fields, so we may just ignore them.
     188             :     if((hHeader.nTideSys   < 0 || hHeader.nTideSys   > 2 ||
     189             :         hHeader.nPtType    < 0 || hHeader.nPtType    > 1 ))
     190             :     {
     191             :         // Some datasets use 0xCC as a marker for invalidity for
     192             :         // records starting from Geopotential Wo
     193             :         for( int i = 52; i < 78; i++ )
     194             :         {
     195             :             if( poOpenInfo->pabyHeader[i] != 0xCC )
     196             :                 return FALSE;
     197             :         }
     198             :     }
     199             : #endif
     200             : 
     201           8 :     if (hHeader.nScale == 0)
     202             :     {
     203          16 :         if ((std::abs(static_cast<GIntBig>(hHeader.nSouth) -
     204          16 :                       (hHeader.nDLat / 2)) > BYN_MAX_LAT) ||
     205           8 :             (std::abs(static_cast<GIntBig>(hHeader.nNorth) +
     206          16 :                       (hHeader.nDLat / 2)) > BYN_MAX_LAT) ||
     207           8 :             (std::abs(static_cast<GIntBig>(hHeader.nWest) -
     208          24 :                       (hHeader.nDLon / 2)) > BYN_MAX_LON) ||
     209           8 :             (std::abs(static_cast<GIntBig>(hHeader.nEast) +
     210           8 :                       (hHeader.nDLon / 2)) > BYN_MAX_LON))
     211           0 :             return FALSE;
     212             :     }
     213             :     else
     214             :     {
     215           0 :         if ((std::abs(static_cast<GIntBig>(hHeader.nSouth) -
     216           0 :                       (hHeader.nDLat / 2)) > BYN_MAX_LAT_SCL) ||
     217           0 :             (std::abs(static_cast<GIntBig>(hHeader.nNorth) +
     218           0 :                       (hHeader.nDLat / 2)) > BYN_MAX_LAT_SCL) ||
     219           0 :             (std::abs(static_cast<GIntBig>(hHeader.nWest) -
     220           0 :                       (hHeader.nDLon / 2)) > BYN_MAX_LON_SCL) ||
     221           0 :             (std::abs(static_cast<GIntBig>(hHeader.nEast) +
     222           0 :                       (hHeader.nDLon / 2)) > BYN_MAX_LON_SCL))
     223           0 :             return FALSE;
     224             :     }
     225             : 
     226           8 :     return TRUE;
     227             : }
     228             : 
     229             : /************************************************************************/
     230             : /*                                Open()                                */
     231             : /************************************************************************/
     232             : 
     233           4 : GDALDataset *BYNDataset::Open(GDALOpenInfo *poOpenInfo)
     234             : 
     235             : {
     236           8 :     if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr ||
     237           4 :         poOpenInfo->eAccess == GA_Update)
     238           0 :         return nullptr;
     239             : 
     240             :     /* -------------------------------------------------------------------- */
     241             :     /*      Create a corresponding GDALDataset.                             */
     242             :     /* -------------------------------------------------------------------- */
     243             : 
     244           8 :     auto poDS = std::make_unique<BYNDataset>();
     245             : 
     246           4 :     poDS->eAccess = poOpenInfo->eAccess;
     247           4 :     std::swap(poDS->fpImage, poOpenInfo->fpL);
     248             : 
     249             :     /* -------------------------------------------------------------------- */
     250             :     /*      Read the header.                                                */
     251             :     /* -------------------------------------------------------------------- */
     252             : 
     253           4 :     buffer2header(poOpenInfo->pabyHeader, &poDS->hHeader);
     254             : 
     255             :     /********************************/
     256             :     /* Scale boundaries and spacing */
     257             :     /********************************/
     258             : 
     259           4 :     double dfSouth = poDS->hHeader.nSouth;
     260           4 :     double dfNorth = poDS->hHeader.nNorth;
     261           4 :     double dfWest = poDS->hHeader.nWest;
     262           4 :     double dfEast = poDS->hHeader.nEast;
     263           4 :     double dfDLat = poDS->hHeader.nDLat;
     264           4 :     double dfDLon = poDS->hHeader.nDLon;
     265             : 
     266           4 :     if (poDS->hHeader.nScale == 1)
     267             :     {
     268           0 :         dfSouth *= BYN_SCALE;
     269           0 :         dfNorth *= BYN_SCALE;
     270           0 :         dfWest *= BYN_SCALE;
     271           0 :         dfEast *= BYN_SCALE;
     272           0 :         dfDLat *= BYN_SCALE;
     273           0 :         dfDLon *= BYN_SCALE;
     274             :     }
     275             : 
     276             :     /******************************/
     277             :     /* Calculate rows and columns */
     278             :     /******************************/
     279             : 
     280           4 :     double dfXSize = -1;
     281           4 :     double dfYSize = -1;
     282             : 
     283           4 :     poDS->nRasterXSize = -1;
     284           4 :     poDS->nRasterYSize = -1;
     285             : 
     286           4 :     if (dfDLat != 0.0 && dfDLon != 0.0)
     287             :     {
     288           4 :         dfXSize = ((dfEast - dfWest + 1.0) / dfDLon) + 1.0;
     289           4 :         dfYSize = ((dfNorth - dfSouth + 1.0) / dfDLat) + 1.0;
     290             :     }
     291             : 
     292           4 :     if (dfXSize > 0.0 && dfXSize < std::numeric_limits<double>::max() &&
     293           8 :         dfYSize > 0.0 && dfYSize < std::numeric_limits<double>::max())
     294             :     {
     295           4 :         poDS->nRasterXSize = static_cast<GInt32>(dfXSize);
     296           4 :         poDS->nRasterYSize = static_cast<GInt32>(dfYSize);
     297             :     }
     298             : 
     299           4 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     300             :     {
     301           0 :         return nullptr;
     302             :     }
     303             : 
     304             :     /*****************************/
     305             :     /* Build GeoTransform matrix */
     306             :     /*****************************/
     307             : 
     308           4 :     poDS->m_gt[0] = (dfWest - (dfDLon / 2.0)) / 3600.0;
     309           4 :     poDS->m_gt[1] = dfDLon / 3600.0;
     310           4 :     poDS->m_gt[2] = 0.0;
     311           4 :     poDS->m_gt[3] = (dfNorth + (dfDLat / 2.0)) / 3600.0;
     312           4 :     poDS->m_gt[4] = 0.0;
     313           4 :     poDS->m_gt[5] = -1 * dfDLat / 3600.0;
     314             : 
     315             :     /*********************/
     316             :     /* Set data type     */
     317             :     /*********************/
     318             : 
     319           4 :     GDALDataType eDT = GDT_Unknown;
     320             : 
     321           4 :     if (poDS->hHeader.nSizeOf == 2)
     322           0 :         eDT = GDT_Int16;
     323           4 :     else if (poDS->hHeader.nSizeOf == 4)
     324           4 :         eDT = GDT_Int32;
     325             :     else
     326             :     {
     327           0 :         return nullptr;
     328             :     }
     329             : 
     330             :     /* -------------------------------------------------------------------- */
     331             :     /*      Create band information object.                                 */
     332             :     /* -------------------------------------------------------------------- */
     333             : 
     334           4 :     const int nDTSize = GDALGetDataTypeSizeBytes(eDT);
     335             : 
     336           4 :     int bIsLSB = poDS->hHeader.nByteOrder == 1 ? 1 : 0;
     337             : 
     338             :     auto poBand = std::make_unique<BYNRasterBand>(
     339           4 :         poDS.get(), 1, poDS->fpImage, BYN_HDR_SZ, nDTSize,
     340          12 :         poDS->nRasterXSize * nDTSize, eDT, CPL_IS_LSB == bIsLSB);
     341           4 :     if (!poBand->IsValid())
     342           0 :         return nullptr;
     343           4 :     poDS->SetBand(1, std::move(poBand));
     344             : 
     345             :     /* -------------------------------------------------------------------- */
     346             :     /*      Initialize any PAM information.                                 */
     347             :     /* -------------------------------------------------------------------- */
     348             : 
     349           4 :     poDS->SetDescription(poOpenInfo->pszFilename);
     350           4 :     poDS->TryLoadXML();
     351             : 
     352             :     /* -------------------------------------------------------------------- */
     353             :     /*      Check for overviews.                                            */
     354             :     /* -------------------------------------------------------------------- */
     355             : 
     356           4 :     poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
     357             : 
     358           4 :     return poDS.release();
     359             : }
     360             : 
     361             : /************************************************************************/
     362             : /*                          GetGeoTransform()                           */
     363             : /************************************************************************/
     364             : 
     365           0 : CPLErr BYNDataset::GetGeoTransform(GDALGeoTransform &gt) const
     366             : {
     367           0 :     gt = m_gt;
     368           0 :     return CE_None;
     369             : }
     370             : 
     371             : /************************************************************************/
     372             : /*                          GetSpatialRef()                             */
     373             : /************************************************************************/
     374             : 
     375           0 : const OGRSpatialReference *BYNDataset::GetSpatialRef() const
     376             : 
     377             : {
     378           0 :     if (!m_oSRS.IsEmpty())
     379           0 :         return &m_oSRS;
     380             : 
     381             :     /* Try to use a prefefined EPSG compound CS */
     382             : 
     383           0 :     if (hHeader.nDatum == 1 && hHeader.nVDatum == 2)
     384             :     {
     385           0 :         m_oSRS.importFromEPSG(BYN_DATUM_1_VDATUM_2);
     386           0 :         return &m_oSRS;
     387             :     }
     388             : 
     389             :     /* Build the GEOGCS based on Datum ( or Ellipsoid )*/
     390             : 
     391           0 :     bool bNoGeogCS = false;
     392             : 
     393           0 :     if (hHeader.nDatum == 0)
     394           0 :         m_oSRS.importFromEPSG(BYN_DATUM_0);
     395           0 :     else if (hHeader.nDatum == 1)
     396           0 :         m_oSRS.importFromEPSG(BYN_DATUM_1);
     397             :     else
     398             :     {
     399             :         /* Build GEOGCS based on Ellipsoid (Table 3) */
     400             : 
     401           0 :         if (hHeader.nEllipsoid > -1 &&
     402           0 :             hHeader.nEllipsoid <
     403             :                 static_cast<GInt16>(CPL_ARRAYSIZE(EllipsoidTable)))
     404           0 :             m_oSRS.SetGeogCS(
     405           0 :                 CPLSPrintf("BYN Ellipsoid(%d)", hHeader.nEllipsoid),
     406           0 :                 "Unspecified", EllipsoidTable[hHeader.nEllipsoid].pszName,
     407           0 :                 EllipsoidTable[hHeader.nEllipsoid].dfSemiMajor,
     408           0 :                 EllipsoidTable[hHeader.nEllipsoid].dfInvFlattening);
     409             :         else
     410           0 :             bNoGeogCS = true;
     411             :     }
     412             : 
     413             :     /* Build the VERT_CS based on VDatum */
     414             : 
     415           0 :     OGRSpatialReference oSRSComp;
     416           0 :     OGRSpatialReference oSRSVert;
     417             : 
     418           0 :     int nVertCS = 0;
     419             : 
     420           0 :     if (hHeader.nVDatum == 1)
     421           0 :         nVertCS = BYN_VDATUM_1;
     422           0 :     else if (hHeader.nVDatum == 2)
     423           0 :         nVertCS = BYN_VDATUM_2;
     424           0 :     else if (hHeader.nVDatum == 3)
     425           0 :         nVertCS = BYN_VDATUM_3;
     426             :     else
     427             :     {
     428             :         /* Return GEOGCS ( .err files ) */
     429             : 
     430           0 :         if (bNoGeogCS)
     431           0 :             return nullptr;
     432             : 
     433           0 :         return &m_oSRS;
     434             :     }
     435             : 
     436           0 :     oSRSVert.importFromEPSG(nVertCS);
     437             : 
     438             :     /* Create CPMPD_CS with GEOGCS and VERT_CS */
     439             : 
     440           0 :     if (oSRSComp.SetCompoundCS(CPLSPrintf("BYN Datum(%d) & VDatum(%d)",
     441           0 :                                           hHeader.nDatum, hHeader.nDatum),
     442           0 :                                &m_oSRS, &oSRSVert) == CE_None)
     443             :     {
     444             :         /* Return COMPD_CS with GEOGCS and VERT_CS */
     445             : 
     446           0 :         m_oSRS = std::move(oSRSComp);
     447           0 :         m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     448           0 :         return &m_oSRS;
     449             :     }
     450             : 
     451           0 :     return nullptr;
     452             : }
     453             : 
     454             : /*----------------------------------------------------------------------*/
     455             : /*                           buffer2header()                            */
     456             : /*----------------------------------------------------------------------*/
     457             : 
     458          12 : void BYNDataset::buffer2header(const GByte *pabyBuf, BYNHeader *pohHeader)
     459             : 
     460             : {
     461          12 :     memcpy(&pohHeader->nSouth, pabyBuf, 4);
     462          12 :     memcpy(&pohHeader->nNorth, pabyBuf + 4, 4);
     463          12 :     memcpy(&pohHeader->nWest, pabyBuf + 8, 4);
     464          12 :     memcpy(&pohHeader->nEast, pabyBuf + 12, 4);
     465          12 :     memcpy(&pohHeader->nDLat, pabyBuf + 16, 2);
     466          12 :     memcpy(&pohHeader->nDLon, pabyBuf + 18, 2);
     467          12 :     memcpy(&pohHeader->nGlobal, pabyBuf + 20, 2);
     468          12 :     memcpy(&pohHeader->nType, pabyBuf + 22, 2);
     469          12 :     memcpy(&pohHeader->dfFactor, pabyBuf + 24, 8);
     470          12 :     memcpy(&pohHeader->nSizeOf, pabyBuf + 32, 2);
     471          12 :     memcpy(&pohHeader->nVDatum, pabyBuf + 34, 2);
     472          12 :     memcpy(&pohHeader->nDescrip, pabyBuf + 40, 2);
     473          12 :     memcpy(&pohHeader->nSubType, pabyBuf + 42, 2);
     474          12 :     memcpy(&pohHeader->nDatum, pabyBuf + 44, 2);
     475          12 :     memcpy(&pohHeader->nEllipsoid, pabyBuf + 46, 2);
     476          12 :     memcpy(&pohHeader->nByteOrder, pabyBuf + 48, 2);
     477          12 :     memcpy(&pohHeader->nScale, pabyBuf + 50, 2);
     478          12 :     memcpy(&pohHeader->dfWo, pabyBuf + 52, 8);
     479          12 :     memcpy(&pohHeader->dfGM, pabyBuf + 60, 8);
     480          12 :     memcpy(&pohHeader->nTideSys, pabyBuf + 68, 2);
     481          12 :     memcpy(&pohHeader->nRealiz, pabyBuf + 70, 2);
     482          12 :     memcpy(&pohHeader->dEpoch, pabyBuf + 72, 4);
     483          12 :     memcpy(&pohHeader->nPtType, pabyBuf + 76, 2);
     484             : 
     485             : #if defined(CPL_MSB)
     486             :     CPL_LSBPTR32(&pohHeader->nSouth);
     487             :     CPL_LSBPTR32(&pohHeader->nNorth);
     488             :     CPL_LSBPTR32(&pohHeader->nWest);
     489             :     CPL_LSBPTR32(&pohHeader->nEast);
     490             :     CPL_LSBPTR16(&pohHeader->nDLat);
     491             :     CPL_LSBPTR16(&pohHeader->nDLon);
     492             :     CPL_LSBPTR16(&pohHeader->nGlobal);
     493             :     CPL_LSBPTR16(&pohHeader->nType);
     494             :     CPL_LSBPTR64(&pohHeader->dfFactor);
     495             :     CPL_LSBPTR16(&pohHeader->nSizeOf);
     496             :     CPL_LSBPTR16(&pohHeader->nVDatum);
     497             :     CPL_LSBPTR16(&pohHeader->nDescrip);
     498             :     CPL_LSBPTR16(&pohHeader->nSubType);
     499             :     CPL_LSBPTR16(&pohHeader->nDatum);
     500             :     CPL_LSBPTR16(&pohHeader->nEllipsoid);
     501             :     CPL_LSBPTR16(&pohHeader->nByteOrder);
     502             :     CPL_LSBPTR16(&pohHeader->nScale);
     503             :     CPL_LSBPTR64(&pohHeader->dfWo);
     504             :     CPL_LSBPTR64(&pohHeader->dfGM);
     505             :     CPL_LSBPTR16(&pohHeader->nTideSys);
     506             :     CPL_LSBPTR16(&pohHeader->nRealiz);
     507             :     CPL_LSBPTR32(&pohHeader->dEpoch);
     508             :     CPL_LSBPTR16(&pohHeader->nPtType);
     509             : #endif
     510             : 
     511             : #if DEBUG
     512          12 :     CPLDebug("BYN", "South         = %d", pohHeader->nSouth);
     513          12 :     CPLDebug("BYN", "North         = %d", pohHeader->nNorth);
     514          12 :     CPLDebug("BYN", "West          = %d", pohHeader->nWest);
     515          12 :     CPLDebug("BYN", "East          = %d", pohHeader->nEast);
     516          12 :     CPLDebug("BYN", "DLat          = %d", pohHeader->nDLat);
     517          12 :     CPLDebug("BYN", "DLon          = %d", pohHeader->nDLon);
     518          12 :     CPLDebug("BYN", "DGlobal       = %d", pohHeader->nGlobal);
     519          12 :     CPLDebug("BYN", "DType         = %d", pohHeader->nType);
     520          12 :     CPLDebug("BYN", "Factor        = %f", pohHeader->dfFactor);
     521          12 :     CPLDebug("BYN", "SizeOf        = %d", pohHeader->nSizeOf);
     522          12 :     CPLDebug("BYN", "VDatum        = %d", pohHeader->nVDatum);
     523          12 :     CPLDebug("BYN", "Data          = %d", pohHeader->nDescrip);
     524          12 :     CPLDebug("BYN", "SubType       = %d", pohHeader->nSubType);
     525          12 :     CPLDebug("BYN", "Datum         = %d", pohHeader->nDatum);
     526          12 :     CPLDebug("BYN", "Ellipsoid     = %d", pohHeader->nEllipsoid);
     527          12 :     CPLDebug("BYN", "ByteOrder     = %d", pohHeader->nByteOrder);
     528          12 :     CPLDebug("BYN", "Scale         = %d", pohHeader->nScale);
     529          12 :     CPLDebug("BYN", "Wo            = %f", pohHeader->dfWo);
     530          12 :     CPLDebug("BYN", "GM            = %f", pohHeader->dfGM);
     531          12 :     CPLDebug("BYN", "TideSystem    = %d", pohHeader->nTideSys);
     532          12 :     CPLDebug("BYN", "RefRealzation = %d", pohHeader->nRealiz);
     533          12 :     CPLDebug("BYN", "Epoch         = %f", pohHeader->dEpoch);
     534          12 :     CPLDebug("BYN", "PtType        = %d", pohHeader->nPtType);
     535             : #endif
     536          12 : }
     537             : 
     538             : /************************************************************************/
     539             : /*                          GDALRegister_BYN()                          */
     540             : /************************************************************************/
     541             : 
     542        1961 : void GDALRegister_BYN()
     543             : 
     544             : {
     545        1961 :     if (GDALGetDriverByName("BYN") != nullptr)
     546         283 :         return;
     547             : 
     548        1678 :     GDALDriver *poDriver = new GDALDriver();
     549             : 
     550        1678 :     poDriver->SetDescription("BYN");
     551        1678 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     552        1678 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     553        1678 :                               "Natural Resources Canada's Geoid");
     554        1678 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "byn err");
     555        1678 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     556        1678 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/byn.html");
     557             : 
     558        1678 :     poDriver->pfnOpen = BYNDataset::Open;
     559        1678 :     poDriver->pfnIdentify = BYNDataset::Identify;
     560             : 
     561        1678 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     562             : }

Generated by: LCOV version 1.14