LCOV - code coverage report
Current view: top level - frmts/raw - gscdataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 65 79 82.3 %
Date: 2025-10-17 19:28:35 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GSC Geogrid format driver.
       4             :  * Purpose:  Implements support for reading and writing GSC Geogrid format.
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2009-2011, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_string.h"
      15             : #include "gdal_frmts.h"
      16             : #include "gdal_priv.h"
      17             : #include "rawdataset.h"
      18             : 
      19             : #include <algorithm>
      20             : 
      21             : /************************************************************************/
      22             : /* ==================================================================== */
      23             : /*                              GSCDataset                              */
      24             : /* ==================================================================== */
      25             : /************************************************************************/
      26             : 
      27             : class GSCDataset final : public RawDataset
      28             : {
      29             :     VSILFILE *fpImage = nullptr;  // image data file.
      30             : 
      31             :     GDALGeoTransform m_gt{};
      32             : 
      33             :     CPL_DISALLOW_COPY_ASSIGN(GSCDataset)
      34             : 
      35             :     CPLErr Close() override;
      36             : 
      37             :   public:
      38           2 :     GSCDataset() = default;
      39             :     ~GSCDataset() override;
      40             : 
      41             :     CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
      42             : 
      43             :     static GDALDataset *Open(GDALOpenInfo *);
      44             : };
      45             : 
      46             : /************************************************************************/
      47             : /*                            ~GSCDataset()                             */
      48             : /************************************************************************/
      49             : 
      50           4 : GSCDataset::~GSCDataset()
      51             : 
      52             : {
      53           2 :     GSCDataset::Close();
      54           4 : }
      55             : 
      56             : /************************************************************************/
      57             : /*                              Close()                                 */
      58             : /************************************************************************/
      59             : 
      60           4 : CPLErr GSCDataset::Close()
      61             : {
      62           4 :     CPLErr eErr = CE_None;
      63           4 :     if (nOpenFlags != OPEN_FLAGS_CLOSED)
      64             :     {
      65           2 :         if (GSCDataset::FlushCache(true) != CE_None)
      66           0 :             eErr = CE_Failure;
      67             : 
      68           2 :         if (fpImage)
      69             :         {
      70           2 :             if (VSIFCloseL(fpImage) != 0)
      71             :             {
      72           0 :                 CPLError(CE_Failure, CPLE_FileIO, "I/O error");
      73           0 :                 eErr = CE_Failure;
      74             :             }
      75             :         }
      76             : 
      77           2 :         if (GDALPamDataset::Close() != CE_None)
      78           0 :             eErr = CE_Failure;
      79             :     }
      80           4 :     return eErr;
      81             : }
      82             : 
      83             : /************************************************************************/
      84             : /*                          GetGeoTransform()                           */
      85             : /************************************************************************/
      86             : 
      87           0 : CPLErr GSCDataset::GetGeoTransform(GDALGeoTransform &gt) const
      88             : 
      89             : {
      90           0 :     gt = m_gt;
      91             : 
      92           0 :     return CE_None;
      93             : }
      94             : 
      95             : /************************************************************************/
      96             : /*                                Open()                                */
      97             : /************************************************************************/
      98             : 
      99       34392 : GDALDataset *GSCDataset::Open(GDALOpenInfo *poOpenInfo)
     100             : 
     101             : {
     102             : 
     103             :     /* -------------------------------------------------------------------- */
     104             :     /*      Does this plausible look like a GSC Geogrid file?               */
     105             :     /* -------------------------------------------------------------------- */
     106       34392 :     if (poOpenInfo->nHeaderBytes < 20)
     107       30923 :         return nullptr;
     108             : 
     109        3469 :     if (poOpenInfo->pabyHeader[12] != 0x02 ||
     110          19 :         poOpenInfo->pabyHeader[13] != 0x00 ||
     111           2 :         poOpenInfo->pabyHeader[14] != 0x00 ||
     112           2 :         poOpenInfo->pabyHeader[15] != 0x00)
     113        3467 :         return nullptr;
     114             : 
     115           2 :     int nRecordLen =
     116           2 :         CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[0]);
     117           2 :     const int nPixels =
     118           2 :         CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[1]);
     119           2 :     const int nLines =
     120           2 :         CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[2]);
     121             : 
     122           2 :     if (nPixels < 1 || nLines < 1 || nPixels > 100000 || nLines > 100000)
     123           0 :         return nullptr;
     124             : 
     125           2 :     if (nRecordLen != nPixels * 4)
     126           0 :         return nullptr;
     127             : 
     128             :     /* -------------------------------------------------------------------- */
     129             :     /*      Confirm the requested access is supported.                      */
     130             :     /* -------------------------------------------------------------------- */
     131           2 :     if (poOpenInfo->eAccess == GA_Update)
     132             :     {
     133           0 :         ReportUpdateNotSupportedByDriver("GSC");
     134           0 :         return nullptr;
     135             :     }
     136             : 
     137           2 :     nRecordLen += 8;  // For record length markers.
     138             : 
     139             :     /* -------------------------------------------------------------------- */
     140             :     /*      Create a corresponding GDALDataset.                             */
     141             :     /* -------------------------------------------------------------------- */
     142           4 :     auto poDS = std::make_unique<GSCDataset>();
     143             : 
     144           2 :     poDS->nRasterXSize = nPixels;
     145           2 :     poDS->nRasterYSize = nLines;
     146           2 :     std::swap(poDS->fpImage, poOpenInfo->fpL);
     147             : 
     148             :     /* -------------------------------------------------------------------- */
     149             :     /*      Read the header information in the second record.               */
     150             :     /* -------------------------------------------------------------------- */
     151           2 :     float afHeaderInfo[8] = {0.0};
     152             : 
     153           4 :     if (VSIFSeekL(poDS->fpImage, nRecordLen + 12, SEEK_SET) != 0 ||
     154           2 :         VSIFReadL(afHeaderInfo, sizeof(float), 8, poDS->fpImage) != 8)
     155             :     {
     156           0 :         CPLError(
     157             :             CE_Failure, CPLE_FileIO,
     158             :             "Failure reading second record of GSC file with %d record length.",
     159             :             nRecordLen);
     160           0 :         return nullptr;
     161             :     }
     162             : 
     163          18 :     for (int i = 0; i < 8; i++)
     164             :     {
     165          16 :         CPL_LSBPTR32(afHeaderInfo + i);
     166             :     }
     167             : 
     168           2 :     poDS->m_gt[0] = afHeaderInfo[2];
     169           2 :     poDS->m_gt[1] = afHeaderInfo[0];
     170           2 :     poDS->m_gt[2] = 0.0;
     171           2 :     poDS->m_gt[3] = afHeaderInfo[5];
     172           2 :     poDS->m_gt[4] = 0.0;
     173           2 :     poDS->m_gt[5] = -afHeaderInfo[1];
     174             : 
     175             :     /* -------------------------------------------------------------------- */
     176             :     /*      Create band information objects.                                */
     177             :     /* -------------------------------------------------------------------- */
     178             :     auto poBand = RawRasterBand::Create(
     179           4 :         poDS.get(), 1, poDS->fpImage, nRecordLen * 2 + 4, sizeof(float),
     180             :         nRecordLen, GDT_Float32, RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN,
     181           4 :         RawRasterBand::OwnFP::NO);
     182           2 :     if (!poBand)
     183           0 :         return nullptr;
     184           2 :     poBand->SetNoDataValue(-1.0000000150474662199e+30);
     185           2 :     poDS->SetBand(1, std::move(poBand));
     186             : 
     187             :     /* -------------------------------------------------------------------- */
     188             :     /*      Initialize any PAM information.                                 */
     189             :     /* -------------------------------------------------------------------- */
     190           2 :     poDS->SetDescription(poOpenInfo->pszFilename);
     191           2 :     poDS->TryLoadXML();
     192             : 
     193             :     /* -------------------------------------------------------------------- */
     194             :     /*      Check for overviews.                                            */
     195             :     /* -------------------------------------------------------------------- */
     196           2 :     poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
     197             : 
     198           2 :     return poDS.release();
     199             : }
     200             : 
     201             : /************************************************************************/
     202             : /*                          GDALRegister_GSC()                          */
     203             : /************************************************************************/
     204             : 
     205        2033 : void GDALRegister_GSC()
     206             : 
     207             : {
     208        2033 :     if (GDALGetDriverByName("GSC") != nullptr)
     209         283 :         return;
     210             : 
     211        1750 :     GDALDriver *poDriver = new GDALDriver();
     212             : 
     213        1750 :     poDriver->SetDescription("GSC");
     214        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     215        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GSC Geogrid");
     216        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gsc.html");
     217        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     218             : 
     219        1750 :     poDriver->pfnOpen = GSCDataset::Open;
     220             : 
     221        1750 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     222             : }

Generated by: LCOV version 1.14