LCOV - code coverage report
Current view: top level - frmts/gff - gff_dataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 23 120 19.2 %
Date: 2025-02-20 10:14:44 Functions: 3 9 33.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Ground-based SAR Applitcations Testbed File Format driver
       4             :  * Purpose:  Support in GDAL for Sandia National Laboratory's GFF format
       5             :  *           blame Tisham for putting me up to this
       6             :  * Author:   Philippe Vachon <philippe@cowpig.ca>
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2007, Philippe Vachon
      10             :  * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "cpl_conv.h"
      16             : #include "cpl_port.h"
      17             : #include "cpl_string.h"
      18             : #include "cpl_vsi.h"
      19             : #include "gdal_frmts.h"
      20             : #include "gdal_pam.h"
      21             : #include "gdal_priv.h"
      22             : 
      23             : /*******************************************************************
      24             :  * Declaration of the GFFDataset class                             *
      25             :  *******************************************************************/
      26             : 
      27             : class GFFRasterBand;
      28             : 
      29             : class GFFDataset final : public GDALPamDataset
      30             : {
      31             :     friend class GFFRasterBand;
      32             :     VSILFILE *fp;
      33             :     GDALDataType eDataType;
      34             :     unsigned int nEndianness;
      35             :     /* Some relevant headers */
      36             :     unsigned short nVersionMajor;
      37             :     unsigned short nVersionMinor;
      38             :     unsigned int nLength;
      39             :     // char *pszCreator;
      40             :     //  TODO: Needs a better explanation.
      41             :     /* I am taking this at face value (are they insane?) */
      42             :     // float fBPP;
      43             :     unsigned int nBPP;
      44             : 
      45             :     /* Good information to know */
      46             :     unsigned int nFrameCnt;
      47             :     unsigned int nImageType;
      48             :     unsigned int nRowMajor;
      49             :     unsigned int nRgCnt;
      50             :     unsigned int nAzCnt;
      51             :     // long nScaleExponent;
      52             :     // long nScaleMantissa;
      53             :     // long nOffsetExponent;
      54             :     // long nOffsetMantissa;
      55             :   public:
      56             :     GFFDataset();
      57             :     ~GFFDataset();
      58             : 
      59             :     static GDALDataset *Open(GDALOpenInfo *);
      60             :     static int Identify(GDALOpenInfo *poOpenInfo);
      61             : };
      62             : 
      63           0 : GFFDataset::GFFDataset()
      64             :     : fp(nullptr), eDataType(GDT_Unknown), nEndianness(0), nVersionMajor(0),
      65             :       nVersionMinor(0), nLength(0), nBPP(0), nFrameCnt(0), nImageType(0),
      66           0 :       nRowMajor(0), nRgCnt(0), nAzCnt(0)
      67             : {
      68           0 : }
      69             : 
      70           0 : GFFDataset::~GFFDataset()
      71             : {
      72           0 :     if (fp != nullptr)
      73           0 :         VSIFCloseL(fp);
      74           0 : }
      75             : 
      76             : /*********************************************************************
      77             :  * Declaration and implementation of the GFFRasterBand Class         *
      78             :  *********************************************************************/
      79             : 
      80             : class GFFRasterBand final : public GDALPamRasterBand
      81             : {
      82             :     long nRasterBandMemory;
      83             :     int nSampleSize;
      84             : 
      85             :   public:
      86             :     GFFRasterBand(GFFDataset *, int, GDALDataType);
      87             :     CPLErr IReadBlock(int, int, void *) override;
      88             : };
      89             : 
      90           0 : static unsigned long GFFSampleSize(GDALDataType eDataType)
      91             : {
      92             :     // Determine the number of bytes per sample.
      93           0 :     unsigned long nBytes = 1;
      94           0 :     switch (eDataType)
      95             :     {
      96           0 :         case GDT_CInt16:
      97           0 :             nBytes = 4;
      98           0 :             break;
      99           0 :         case GDT_CInt32:
     100             :         case GDT_CFloat32:
     101           0 :             nBytes = 8;
     102           0 :             break;
     103           0 :         default:
     104           0 :             nBytes = 1;
     105             :     }
     106             : 
     107           0 :     return nBytes;
     108             : }
     109             : 
     110             : /************************************************************************/
     111             : /*                           GFFRasterBand()                            */
     112             : /************************************************************************/
     113           0 : GFFRasterBand::GFFRasterBand(GFFDataset *poDSIn, int nBandIn,
     114           0 :                              GDALDataType eDataTypeIn)
     115           0 :     : nRasterBandMemory(GFFSampleSize(eDataTypeIn) * poDSIn->GetRasterXSize()),
     116           0 :       nSampleSize(static_cast<int>(GFFSampleSize(eDataTypeIn)))
     117             : {
     118           0 :     poDS = poDSIn;
     119           0 :     nBand = nBandIn;
     120             : 
     121           0 :     eDataType = eDataTypeIn;
     122             : 
     123           0 :     nBlockXSize = poDS->GetRasterXSize();
     124           0 :     nBlockYSize = 1;
     125           0 : }
     126             : 
     127             : /************************************************************************/
     128             : /*                             IReadBlock()                             */
     129             : /************************************************************************/
     130             : 
     131           0 : CPLErr GFFRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
     132             :                                  void *pImage)
     133             : {
     134           0 :     GFFDataset *poGDS = (GFFDataset *)poDS;
     135           0 :     long nOffset = poGDS->nLength;
     136             : 
     137           0 :     VSIFSeekL(poGDS->fp,
     138           0 :               nOffset + (poGDS->GetRasterXSize() * nBlockYOff * (nSampleSize)),
     139             :               SEEK_SET);
     140             : 
     141             :     /* Ingest entire range line */
     142           0 :     if (VSIFReadL(pImage, nRasterBandMemory, 1, poGDS->fp) != 1)
     143           0 :         return CE_Failure;
     144             : 
     145             : #if defined(CPL_MSB)
     146             :     if (GDALDataTypeIsComplex(eDataType))
     147             :     {
     148             :         int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
     149             :         GDALSwapWords(pImage, nWordSize, nBlockXSize, 2 * nWordSize);
     150             :         GDALSwapWords(((GByte *)pImage) + nWordSize, nWordSize, nBlockXSize,
     151             :                       2 * nWordSize);
     152             :     }
     153             : #endif
     154             : 
     155           0 :     return CE_None;
     156             : }
     157             : 
     158             : /********************************************************************
     159             :  * ================================================================ *
     160             :  * Implementation of the GFFDataset Class                           *
     161             :  * ================================================================ *
     162             :  ********************************************************************/
     163             : 
     164             : /************************************************************************/
     165             : /*                              Identify()                              */
     166             : /************************************************************************/
     167       36424 : int GFFDataset::Identify(GDALOpenInfo *poOpenInfo)
     168             : {
     169       36424 :     if (poOpenInfo->nHeaderBytes < 7)
     170       29124 :         return 0;
     171             : 
     172        7300 :     if (STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "GSATIMG"))
     173           0 :         return 1;
     174             : 
     175        7300 :     return 0;
     176             : }
     177             : 
     178             : /************************************************************************/
     179             : /*                                Open()                                */
     180             : /************************************************************************/
     181             : 
     182       36423 : GDALDataset *GFFDataset::Open(GDALOpenInfo *poOpenInfo)
     183             : {
     184             :     /* Check that the dataset is indeed a GSAT File Format (GFF) file */
     185       36423 :     if (!GFFDataset::Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
     186       36423 :         return nullptr;
     187             : 
     188             :     /* -------------------------------------------------------------------- */
     189             :     /*      Confirm the requested access is supported.                      */
     190             :     /* -------------------------------------------------------------------- */
     191           1 :     if (poOpenInfo->eAccess == GA_Update)
     192             :     {
     193           0 :         ReportUpdateNotSupportedByDriver("GFF");
     194           0 :         return nullptr;
     195             :     }
     196             : 
     197           1 :     GFFDataset *poDS = new GFFDataset();
     198             : 
     199           0 :     poDS->fp = poOpenInfo->fpL;
     200           0 :     poOpenInfo->fpL = nullptr;
     201             : 
     202             :     /* Check the endianness of the file */
     203           0 :     VSIFSeekL(poDS->fp, 54, SEEK_SET);
     204           0 :     VSIFReadL(&(poDS->nEndianness), 2, 1, poDS->fp);
     205             : 
     206           0 :     VSIFSeekL(poDS->fp, 8, SEEK_SET);
     207           0 :     VSIFReadL(&poDS->nVersionMinor, 2, 1, poDS->fp);
     208           0 :     CPL_LSBPTR16(&poDS->nVersionMinor);
     209           0 :     VSIFReadL(&poDS->nVersionMajor, 2, 1, poDS->fp);
     210           0 :     CPL_LSBPTR16(&poDS->nVersionMajor);
     211           0 :     VSIFReadL(&poDS->nLength, 4, 1, poDS->fp);
     212           0 :     CPL_LSBPTR32(&poDS->nLength);
     213             : 
     214           0 :     unsigned short nCreatorLength = 0;
     215           0 :     VSIFReadL(&nCreatorLength, 2, 1, poDS->fp);
     216           0 :     CPL_LSBPTR16(&nCreatorLength);
     217             :     /* Hack for now... I should properly load the date metadata, for
     218             :      * example
     219             :      */
     220           0 :     VSIFSeekL(poDS->fp, 56, SEEK_SET);
     221             : 
     222             :     /* By looking at the Matlab code, one should write something like the
     223             :      * following test */
     224             :     /* but the results don't seem to be the ones really expected */
     225             :     /*if ((poDS->nVersionMajor == 1 && poDS->nVersionMinor > 7) ||
     226             :     (poDS->nVersionMajor > 1))
     227             :     {
     228             :         float fBPP;
     229             :         VSIFRead(&fBPP,4,1,poDS->fp);
     230             :         poDS->nBPP = fBPP;
     231             :     }
     232             :     else*/
     233             :     {
     234           0 :         VSIFReadL(&poDS->nBPP, 4, 1, poDS->fp);
     235           0 :         CPL_LSBPTR32(&poDS->nBPP);
     236             :     }
     237           0 :     VSIFReadL(&poDS->nFrameCnt, 4, 1, poDS->fp);
     238           0 :     CPL_LSBPTR32(&poDS->nFrameCnt);
     239           0 :     VSIFReadL(&poDS->nImageType, 4, 1, poDS->fp);
     240           0 :     CPL_LSBPTR32(&poDS->nImageType);
     241           0 :     VSIFReadL(&poDS->nRowMajor, 4, 1, poDS->fp);
     242           0 :     CPL_LSBPTR32(&poDS->nRowMajor);
     243           0 :     VSIFReadL(&poDS->nRgCnt, 4, 1, poDS->fp);
     244           0 :     CPL_LSBPTR32(&poDS->nRgCnt);
     245           0 :     VSIFReadL(&poDS->nAzCnt, 4, 1, poDS->fp);
     246           0 :     CPL_LSBPTR32(&poDS->nAzCnt);
     247             : 
     248             :     /* We now have enough information to determine the number format */
     249           0 :     switch (poDS->nImageType)
     250             :     {
     251           0 :         case 0:
     252           0 :             poDS->eDataType = GDT_Byte;
     253           0 :             break;
     254             : 
     255           0 :         case 1:
     256           0 :             if (poDS->nBPP == 4)
     257           0 :                 poDS->eDataType = GDT_CInt16;
     258             :             else
     259           0 :                 poDS->eDataType = GDT_CInt32;
     260           0 :             break;
     261             : 
     262           0 :         case 2:
     263           0 :             poDS->eDataType = GDT_CFloat32;
     264           0 :             break;
     265             : 
     266           0 :         default:
     267           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unknown image type found!");
     268           0 :             delete poDS;
     269           0 :             return nullptr;
     270             :     }
     271             : 
     272             :     /* Set raster width/height
     273             :      * Note that the images that are complex are listed as having twice the
     274             :      * number of X-direction values than there are actual pixels. This is
     275             :      * because whoever came up with the format was crazy (actually, my
     276             :      * hunch is that they designed it very much for Matlab)
     277             :      * */
     278           0 :     if (poDS->nRowMajor)
     279             :     {
     280           0 :         poDS->nRasterXSize = poDS->nRgCnt / (poDS->nImageType == 0 ? 1 : 2);
     281           0 :         poDS->nRasterYSize = poDS->nAzCnt;
     282             :     }
     283             :     else
     284             :     {
     285           0 :         poDS->nRasterXSize = poDS->nAzCnt / (poDS->nImageType == 0 ? 1 : 2);
     286           0 :         poDS->nRasterYSize = poDS->nRgCnt;
     287             :     }
     288             : 
     289           0 :     if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     290             :     {
     291           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     292             :                  "Invalid raster dimensions : %d x %d", poDS->nRasterXSize,
     293             :                  poDS->nRasterYSize);
     294           0 :         delete poDS;
     295           0 :         return nullptr;
     296             :     }
     297             : 
     298           0 :     poDS->SetBand(1, new GFFRasterBand(poDS, 1, poDS->eDataType));
     299             : 
     300             :     /* -------------------------------------------------------------------- */
     301             :     /*      Initialize any PAM information.                                 */
     302             :     /* -------------------------------------------------------------------- */
     303           0 :     poDS->SetDescription(poOpenInfo->pszFilename);
     304           0 :     poDS->TryLoadXML();
     305             : 
     306             :     /* -------------------------------------------------------------------- */
     307             :     /*      Support overviews.                                              */
     308             :     /* -------------------------------------------------------------------- */
     309           0 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
     310             : 
     311           0 :     return poDS;
     312             : }
     313             : 
     314             : /************************************************************************/
     315             : /*                          GDALRegister_GFF()                          */
     316             : /************************************************************************/
     317             : 
     318        1686 : void GDALRegister_GFF()
     319             : {
     320        1686 :     if (GDALGetDriverByName("GFF") != nullptr)
     321         302 :         return;
     322             : 
     323        1384 :     GDALDriver *poDriver = new GDALDriver();
     324             : 
     325        1384 :     poDriver->SetDescription("GFF");
     326        1384 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     327        1384 :     poDriver->SetMetadataItem(
     328             :         GDAL_DMD_LONGNAME,
     329        1384 :         "Ground-based SAR Applications Testbed File Format (.gff)");
     330        1384 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gff.html");
     331        1384 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gff");
     332        1384 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     333        1384 :     poDriver->pfnOpen = GFFDataset::Open;
     334        1384 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     335             : }

Generated by: LCOV version 1.14