LCOV - code coverage report
Current view: top level - frmts/gff - gff_dataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 21 120 17.5 %
Date: 2024-11-21 22:18:42 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       35861 : int GFFDataset::Identify(GDALOpenInfo *poOpenInfo)
     168             : {
     169       35861 :     if (poOpenInfo->nHeaderBytes < 7)
     170       28596 :         return 0;
     171             : 
     172        7265 :     if (STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "GSATIMG"))
     173           0 :         return 1;
     174             : 
     175        7265 :     return 0;
     176             : }
     177             : 
     178             : /************************************************************************/
     179             : /*                                Open()                                */
     180             : /************************************************************************/
     181             : 
     182       35861 : GDALDataset *GFFDataset::Open(GDALOpenInfo *poOpenInfo)
     183             : {
     184             :     /* Check that the dataset is indeed a GSAT File Format (GFF) file */
     185       35861 :     if (!GFFDataset::Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
     186       35859 :         return nullptr;
     187             : 
     188             :     /* -------------------------------------------------------------------- */
     189             :     /*      Confirm the requested access is supported.                      */
     190             :     /* -------------------------------------------------------------------- */
     191           0 :     if (poOpenInfo->eAccess == GA_Update)
     192             :     {
     193           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     194             :                  "The GFF driver does not support update access to existing"
     195             :                  " datasets.\n");
     196           0 :         return nullptr;
     197             :     }
     198             : 
     199           0 :     GFFDataset *poDS = new GFFDataset();
     200             : 
     201           0 :     poDS->fp = poOpenInfo->fpL;
     202           0 :     poOpenInfo->fpL = nullptr;
     203             : 
     204             :     /* Check the endianness of the file */
     205           0 :     VSIFSeekL(poDS->fp, 54, SEEK_SET);
     206           0 :     VSIFReadL(&(poDS->nEndianness), 2, 1, poDS->fp);
     207             : 
     208           0 :     VSIFSeekL(poDS->fp, 8, SEEK_SET);
     209           0 :     VSIFReadL(&poDS->nVersionMinor, 2, 1, poDS->fp);
     210           0 :     CPL_LSBPTR16(&poDS->nVersionMinor);
     211           0 :     VSIFReadL(&poDS->nVersionMajor, 2, 1, poDS->fp);
     212           0 :     CPL_LSBPTR16(&poDS->nVersionMajor);
     213           0 :     VSIFReadL(&poDS->nLength, 4, 1, poDS->fp);
     214           0 :     CPL_LSBPTR32(&poDS->nLength);
     215             : 
     216           0 :     unsigned short nCreatorLength = 0;
     217           0 :     VSIFReadL(&nCreatorLength, 2, 1, poDS->fp);
     218           0 :     CPL_LSBPTR16(&nCreatorLength);
     219             :     /* Hack for now... I should properly load the date metadata, for
     220             :      * example
     221             :      */
     222           0 :     VSIFSeekL(poDS->fp, 56, SEEK_SET);
     223             : 
     224             :     /* By looking at the Matlab code, one should write something like the
     225             :      * following test */
     226             :     /* but the results don't seem to be the ones really expected */
     227             :     /*if ((poDS->nVersionMajor == 1 && poDS->nVersionMinor > 7) ||
     228             :     (poDS->nVersionMajor > 1))
     229             :     {
     230             :         float fBPP;
     231             :         VSIFRead(&fBPP,4,1,poDS->fp);
     232             :         poDS->nBPP = fBPP;
     233             :     }
     234             :     else*/
     235             :     {
     236           0 :         VSIFReadL(&poDS->nBPP, 4, 1, poDS->fp);
     237           0 :         CPL_LSBPTR32(&poDS->nBPP);
     238             :     }
     239           0 :     VSIFReadL(&poDS->nFrameCnt, 4, 1, poDS->fp);
     240           0 :     CPL_LSBPTR32(&poDS->nFrameCnt);
     241           0 :     VSIFReadL(&poDS->nImageType, 4, 1, poDS->fp);
     242           0 :     CPL_LSBPTR32(&poDS->nImageType);
     243           0 :     VSIFReadL(&poDS->nRowMajor, 4, 1, poDS->fp);
     244           0 :     CPL_LSBPTR32(&poDS->nRowMajor);
     245           0 :     VSIFReadL(&poDS->nRgCnt, 4, 1, poDS->fp);
     246           0 :     CPL_LSBPTR32(&poDS->nRgCnt);
     247           0 :     VSIFReadL(&poDS->nAzCnt, 4, 1, poDS->fp);
     248           0 :     CPL_LSBPTR32(&poDS->nAzCnt);
     249             : 
     250             :     /* We now have enough information to determine the number format */
     251           0 :     switch (poDS->nImageType)
     252             :     {
     253           0 :         case 0:
     254           0 :             poDS->eDataType = GDT_Byte;
     255           0 :             break;
     256             : 
     257           0 :         case 1:
     258           0 :             if (poDS->nBPP == 4)
     259           0 :                 poDS->eDataType = GDT_CInt16;
     260             :             else
     261           0 :                 poDS->eDataType = GDT_CInt32;
     262           0 :             break;
     263             : 
     264           0 :         case 2:
     265           0 :             poDS->eDataType = GDT_CFloat32;
     266           0 :             break;
     267             : 
     268           0 :         default:
     269           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unknown image type found!");
     270           0 :             delete poDS;
     271           0 :             return nullptr;
     272             :     }
     273             : 
     274             :     /* Set raster width/height
     275             :      * Note that the images that are complex are listed as having twice the
     276             :      * number of X-direction values than there are actual pixels. This is
     277             :      * because whoever came up with the format was crazy (actually, my
     278             :      * hunch is that they designed it very much for Matlab)
     279             :      * */
     280           0 :     if (poDS->nRowMajor)
     281             :     {
     282           0 :         poDS->nRasterXSize = poDS->nRgCnt / (poDS->nImageType == 0 ? 1 : 2);
     283           0 :         poDS->nRasterYSize = poDS->nAzCnt;
     284             :     }
     285             :     else
     286             :     {
     287           0 :         poDS->nRasterXSize = poDS->nAzCnt / (poDS->nImageType == 0 ? 1 : 2);
     288           0 :         poDS->nRasterYSize = poDS->nRgCnt;
     289             :     }
     290             : 
     291           0 :     if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     292             :     {
     293           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     294             :                  "Invalid raster dimensions : %d x %d", poDS->nRasterXSize,
     295             :                  poDS->nRasterYSize);
     296           0 :         delete poDS;
     297           0 :         return nullptr;
     298             :     }
     299             : 
     300           0 :     poDS->SetBand(1, new GFFRasterBand(poDS, 1, poDS->eDataType));
     301             : 
     302             :     /* -------------------------------------------------------------------- */
     303             :     /*      Initialize any PAM information.                                 */
     304             :     /* -------------------------------------------------------------------- */
     305           0 :     poDS->SetDescription(poOpenInfo->pszFilename);
     306           0 :     poDS->TryLoadXML();
     307             : 
     308             :     /* -------------------------------------------------------------------- */
     309             :     /*      Support overviews.                                              */
     310             :     /* -------------------------------------------------------------------- */
     311           0 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
     312             : 
     313           0 :     return poDS;
     314             : }
     315             : 
     316             : /************************************************************************/
     317             : /*                          GDALRegister_GFF()                          */
     318             : /************************************************************************/
     319             : 
     320        1595 : void GDALRegister_GFF()
     321             : {
     322        1595 :     if (GDALGetDriverByName("GFF") != nullptr)
     323         302 :         return;
     324             : 
     325        1293 :     GDALDriver *poDriver = new GDALDriver();
     326             : 
     327        1293 :     poDriver->SetDescription("GFF");
     328        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     329        1293 :     poDriver->SetMetadataItem(
     330             :         GDAL_DMD_LONGNAME,
     331        1293 :         "Ground-based SAR Applications Testbed File Format (.gff)");
     332        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gff.html");
     333        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gff");
     334        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     335        1293 :     poDriver->pfnOpen = GFFDataset::Open;
     336        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     337             : }

Generated by: LCOV version 1.14