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-05-03 15:49: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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_string.h"
      31             : #include "gdal_frmts.h"
      32             : #include "rawdataset.h"
      33             : 
      34             : #include <algorithm>
      35             : 
      36             : /************************************************************************/
      37             : /* ==================================================================== */
      38             : /*                              GSCDataset                              */
      39             : /* ==================================================================== */
      40             : /************************************************************************/
      41             : 
      42             : class GSCDataset final : public RawDataset
      43             : {
      44             :     VSILFILE *fpImage;  // image data file.
      45             : 
      46             :     double adfGeoTransform[6];
      47             : 
      48             :     CPL_DISALLOW_COPY_ASSIGN(GSCDataset)
      49             : 
      50             :     CPLErr Close() override;
      51             : 
      52             :   public:
      53             :     GSCDataset();
      54             :     ~GSCDataset();
      55             : 
      56             :     CPLErr GetGeoTransform(double *padfTransform) override;
      57             : 
      58             :     static GDALDataset *Open(GDALOpenInfo *);
      59             : };
      60             : 
      61             : /************************************************************************/
      62             : /*                            GSCDataset()                             */
      63             : /************************************************************************/
      64             : 
      65           2 : GSCDataset::GSCDataset() : fpImage(nullptr)
      66             : {
      67           2 :     adfGeoTransform[0] = 0.0;
      68           2 :     adfGeoTransform[1] = 1.0;
      69           2 :     adfGeoTransform[2] = 0.0;
      70           2 :     adfGeoTransform[3] = 0.0;
      71           2 :     adfGeoTransform[4] = 0.0;
      72           2 :     adfGeoTransform[5] = 1.0;
      73           2 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                            ~GSCDataset()                             */
      77             : /************************************************************************/
      78             : 
      79           4 : GSCDataset::~GSCDataset()
      80             : 
      81             : {
      82           2 :     GSCDataset::Close();
      83           4 : }
      84             : 
      85             : /************************************************************************/
      86             : /*                              Close()                                 */
      87             : /************************************************************************/
      88             : 
      89           4 : CPLErr GSCDataset::Close()
      90             : {
      91           4 :     CPLErr eErr = CE_None;
      92           4 :     if (nOpenFlags != OPEN_FLAGS_CLOSED)
      93             :     {
      94           2 :         if (GSCDataset::FlushCache(true) != CE_None)
      95           0 :             eErr = CE_Failure;
      96             : 
      97           2 :         if (fpImage)
      98             :         {
      99           2 :             if (VSIFCloseL(fpImage) != 0)
     100             :             {
     101           0 :                 CPLError(CE_Failure, CPLE_FileIO, "I/O error");
     102           0 :                 eErr = CE_Failure;
     103             :             }
     104             :         }
     105             : 
     106           2 :         if (GDALPamDataset::Close() != CE_None)
     107           0 :             eErr = CE_Failure;
     108             :     }
     109           4 :     return eErr;
     110             : }
     111             : 
     112             : /************************************************************************/
     113             : /*                          GetGeoTransform()                           */
     114             : /************************************************************************/
     115             : 
     116           0 : CPLErr GSCDataset::GetGeoTransform(double *padfTransform)
     117             : 
     118             : {
     119           0 :     memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     120             : 
     121           0 :     return CE_None;
     122             : }
     123             : 
     124             : /************************************************************************/
     125             : /*                                Open()                                */
     126             : /************************************************************************/
     127             : 
     128       29191 : GDALDataset *GSCDataset::Open(GDALOpenInfo *poOpenInfo)
     129             : 
     130             : {
     131             : 
     132             :     /* -------------------------------------------------------------------- */
     133             :     /*      Does this plausible look like a GSC Geogrid file?               */
     134             :     /* -------------------------------------------------------------------- */
     135       29191 :     if (poOpenInfo->nHeaderBytes < 20)
     136       25994 :         return nullptr;
     137             : 
     138        3197 :     if (poOpenInfo->pabyHeader[12] != 0x02 ||
     139          21 :         poOpenInfo->pabyHeader[13] != 0x00 ||
     140           3 :         poOpenInfo->pabyHeader[14] != 0x00 ||
     141           3 :         poOpenInfo->pabyHeader[15] != 0x00)
     142        3195 :         return nullptr;
     143             : 
     144           2 :     int nRecordLen =
     145           2 :         CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[0]);
     146           2 :     const int nPixels =
     147           2 :         CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[1]);
     148           2 :     const int nLines =
     149           2 :         CPL_LSBWORD32(reinterpret_cast<GInt32 *>(poOpenInfo->pabyHeader)[2]);
     150             : 
     151           2 :     if (nPixels < 1 || nLines < 1 || nPixels > 100000 || nLines > 100000)
     152           0 :         return nullptr;
     153             : 
     154           2 :     if (nRecordLen != nPixels * 4)
     155           0 :         return nullptr;
     156             : 
     157             :     /* -------------------------------------------------------------------- */
     158             :     /*      Confirm the requested access is supported.                      */
     159             :     /* -------------------------------------------------------------------- */
     160           2 :     if (poOpenInfo->eAccess == GA_Update)
     161             :     {
     162           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     163             :                  "The GSC driver does not support update access to existing "
     164             :                  "datasets.");
     165           0 :         return nullptr;
     166             :     }
     167             : 
     168           2 :     nRecordLen += 8;  // For record length markers.
     169             : 
     170             :     /* -------------------------------------------------------------------- */
     171             :     /*      Create a corresponding GDALDataset.                             */
     172             :     /* -------------------------------------------------------------------- */
     173           4 :     auto poDS = std::make_unique<GSCDataset>();
     174             : 
     175           2 :     poDS->nRasterXSize = nPixels;
     176           2 :     poDS->nRasterYSize = nLines;
     177           2 :     std::swap(poDS->fpImage, poOpenInfo->fpL);
     178             : 
     179             :     /* -------------------------------------------------------------------- */
     180             :     /*      Read the header information in the second record.               */
     181             :     /* -------------------------------------------------------------------- */
     182           2 :     float afHeaderInfo[8] = {0.0};
     183             : 
     184           4 :     if (VSIFSeekL(poDS->fpImage, nRecordLen + 12, SEEK_SET) != 0 ||
     185           2 :         VSIFReadL(afHeaderInfo, sizeof(float), 8, poDS->fpImage) != 8)
     186             :     {
     187           0 :         CPLError(
     188             :             CE_Failure, CPLE_FileIO,
     189             :             "Failure reading second record of GSC file with %d record length.",
     190             :             nRecordLen);
     191           0 :         return nullptr;
     192             :     }
     193             : 
     194          18 :     for (int i = 0; i < 8; i++)
     195             :     {
     196          16 :         CPL_LSBPTR32(afHeaderInfo + i);
     197             :     }
     198             : 
     199           2 :     poDS->adfGeoTransform[0] = afHeaderInfo[2];
     200           2 :     poDS->adfGeoTransform[1] = afHeaderInfo[0];
     201           2 :     poDS->adfGeoTransform[2] = 0.0;
     202           2 :     poDS->adfGeoTransform[3] = afHeaderInfo[5];
     203           2 :     poDS->adfGeoTransform[4] = 0.0;
     204           2 :     poDS->adfGeoTransform[5] = -afHeaderInfo[1];
     205             : 
     206             :     /* -------------------------------------------------------------------- */
     207             :     /*      Create band information objects.                                */
     208             :     /* -------------------------------------------------------------------- */
     209             :     auto poBand = RawRasterBand::Create(
     210           4 :         poDS.get(), 1, poDS->fpImage, nRecordLen * 2 + 4, sizeof(float),
     211             :         nRecordLen, GDT_Float32, RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN,
     212           4 :         RawRasterBand::OwnFP::NO);
     213           2 :     if (!poBand)
     214           0 :         return nullptr;
     215           2 :     poBand->SetNoDataValue(-1.0000000150474662199e+30);
     216           2 :     poDS->SetBand(1, std::move(poBand));
     217             : 
     218             :     /* -------------------------------------------------------------------- */
     219             :     /*      Initialize any PAM information.                                 */
     220             :     /* -------------------------------------------------------------------- */
     221           2 :     poDS->SetDescription(poOpenInfo->pszFilename);
     222           2 :     poDS->TryLoadXML();
     223             : 
     224             :     /* -------------------------------------------------------------------- */
     225             :     /*      Check for overviews.                                            */
     226             :     /* -------------------------------------------------------------------- */
     227           2 :     poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
     228             : 
     229           2 :     return poDS.release();
     230             : }
     231             : 
     232             : /************************************************************************/
     233             : /*                          GDALRegister_GSC()                          */
     234             : /************************************************************************/
     235             : 
     236        1511 : void GDALRegister_GSC()
     237             : 
     238             : {
     239        1511 :     if (GDALGetDriverByName("GSC") != nullptr)
     240         295 :         return;
     241             : 
     242        1216 :     GDALDriver *poDriver = new GDALDriver();
     243             : 
     244        1216 :     poDriver->SetDescription("GSC");
     245        1216 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     246        1216 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GSC Geogrid");
     247        1216 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gsc.html");
     248        1216 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     249             : 
     250        1216 :     poDriver->pfnOpen = GSCDataset::Open;
     251             : 
     252        1216 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     253             : }

Generated by: LCOV version 1.14