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

Generated by: LCOV version 1.14