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

Generated by: LCOV version 1.14