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: 2024-11-21 22:18:42 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       30632 : GDALDataset *GSCDataset::Open(GDALOpenInfo *poOpenInfo)
     113             : 
     114             : {
     115             : 
     116             :     /* -------------------------------------------------------------------- */
     117             :     /*      Does this plausible look like a GSC Geogrid file?               */
     118             :     /* -------------------------------------------------------------------- */
     119       30632 :     if (poOpenInfo->nHeaderBytes < 20)
     120       27319 :         return nullptr;
     121             : 
     122        3313 :     if (poOpenInfo->pabyHeader[12] != 0x02 ||
     123          21 :         poOpenInfo->pabyHeader[13] != 0x00 ||
     124           3 :         poOpenInfo->pabyHeader[14] != 0x00 ||
     125           3 :         poOpenInfo->pabyHeader[15] != 0x00)
     126        3311 :         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 :         CPLError(CE_Failure, CPLE_NotSupported,
     147             :                  "The GSC driver does not support update access to existing "
     148             :                  "datasets.");
     149           0 :         return nullptr;
     150             :     }
     151             : 
     152           2 :     nRecordLen += 8;  // For record length markers.
     153             : 
     154             :     /* -------------------------------------------------------------------- */
     155             :     /*      Create a corresponding GDALDataset.                             */
     156             :     /* -------------------------------------------------------------------- */
     157           4 :     auto poDS = std::make_unique<GSCDataset>();
     158             : 
     159           2 :     poDS->nRasterXSize = nPixels;
     160           2 :     poDS->nRasterYSize = nLines;
     161           2 :     std::swap(poDS->fpImage, poOpenInfo->fpL);
     162             : 
     163             :     /* -------------------------------------------------------------------- */
     164             :     /*      Read the header information in the second record.               */
     165             :     /* -------------------------------------------------------------------- */
     166           2 :     float afHeaderInfo[8] = {0.0};
     167             : 
     168           4 :     if (VSIFSeekL(poDS->fpImage, nRecordLen + 12, SEEK_SET) != 0 ||
     169           2 :         VSIFReadL(afHeaderInfo, sizeof(float), 8, poDS->fpImage) != 8)
     170             :     {
     171           0 :         CPLError(
     172             :             CE_Failure, CPLE_FileIO,
     173             :             "Failure reading second record of GSC file with %d record length.",
     174             :             nRecordLen);
     175           0 :         return nullptr;
     176             :     }
     177             : 
     178          18 :     for (int i = 0; i < 8; i++)
     179             :     {
     180          16 :         CPL_LSBPTR32(afHeaderInfo + i);
     181             :     }
     182             : 
     183           2 :     poDS->adfGeoTransform[0] = afHeaderInfo[2];
     184           2 :     poDS->adfGeoTransform[1] = afHeaderInfo[0];
     185           2 :     poDS->adfGeoTransform[2] = 0.0;
     186           2 :     poDS->adfGeoTransform[3] = afHeaderInfo[5];
     187           2 :     poDS->adfGeoTransform[4] = 0.0;
     188           2 :     poDS->adfGeoTransform[5] = -afHeaderInfo[1];
     189             : 
     190             :     /* -------------------------------------------------------------------- */
     191             :     /*      Create band information objects.                                */
     192             :     /* -------------------------------------------------------------------- */
     193             :     auto poBand = RawRasterBand::Create(
     194           4 :         poDS.get(), 1, poDS->fpImage, nRecordLen * 2 + 4, sizeof(float),
     195             :         nRecordLen, GDT_Float32, RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN,
     196           4 :         RawRasterBand::OwnFP::NO);
     197           2 :     if (!poBand)
     198           0 :         return nullptr;
     199           2 :     poBand->SetNoDataValue(-1.0000000150474662199e+30);
     200           2 :     poDS->SetBand(1, std::move(poBand));
     201             : 
     202             :     /* -------------------------------------------------------------------- */
     203             :     /*      Initialize any PAM information.                                 */
     204             :     /* -------------------------------------------------------------------- */
     205           2 :     poDS->SetDescription(poOpenInfo->pszFilename);
     206           2 :     poDS->TryLoadXML();
     207             : 
     208             :     /* -------------------------------------------------------------------- */
     209             :     /*      Check for overviews.                                            */
     210             :     /* -------------------------------------------------------------------- */
     211           2 :     poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
     212             : 
     213           2 :     return poDS.release();
     214             : }
     215             : 
     216             : /************************************************************************/
     217             : /*                          GDALRegister_GSC()                          */
     218             : /************************************************************************/
     219             : 
     220        1595 : void GDALRegister_GSC()
     221             : 
     222             : {
     223        1595 :     if (GDALGetDriverByName("GSC") != nullptr)
     224         302 :         return;
     225             : 
     226        1293 :     GDALDriver *poDriver = new GDALDriver();
     227             : 
     228        1293 :     poDriver->SetDescription("GSC");
     229        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     230        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GSC Geogrid");
     231        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gsc.html");
     232        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     233             : 
     234        1293 :     poDriver->pfnOpen = GSCDataset::Open;
     235             : 
     236        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     237             : }

Generated by: LCOV version 1.14