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-05-06 13:02:59 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      13             :  * copy of this software and associated documentation files (the "Software"),
      14             :  * to deal in the Software without restriction, including without limitation
      15             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16             :  * and/or sell copies of the Software, and to permit persons to whom the
      17             :  * Software is furnished to do so, subject to the following conditions:
      18             :  *
      19             :  * The above copyright notice and this permission notice shall be included
      20             :  * in all copies or substantial portions of the Software.
      21             :  *
      22             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28             :  * DEALINGS IN THE SOFTWARE.
      29             :  ****************************************************************************/
      30             : 
      31             : #include "cpl_conv.h"
      32             : #include "cpl_port.h"
      33             : #include "cpl_string.h"
      34             : #include "cpl_vsi.h"
      35             : #include "gdal_frmts.h"
      36             : #include "gdal_pam.h"
      37             : #include "gdal_priv.h"
      38             : 
      39             : /*******************************************************************
      40             :  * Declaration of the GFFDataset class                             *
      41             :  *******************************************************************/
      42             : 
      43             : class GFFRasterBand;
      44             : 
      45             : class GFFDataset final : public GDALPamDataset
      46             : {
      47             :     friend class GFFRasterBand;
      48             :     VSILFILE *fp;
      49             :     GDALDataType eDataType;
      50             :     unsigned int nEndianness;
      51             :     /* Some relevant headers */
      52             :     unsigned short nVersionMajor;
      53             :     unsigned short nVersionMinor;
      54             :     unsigned int nLength;
      55             :     // char *pszCreator;
      56             :     //  TODO: Needs a better explanation.
      57             :     /* I am taking this at face value (are they insane?) */
      58             :     // float fBPP;
      59             :     unsigned int nBPP;
      60             : 
      61             :     /* Good information to know */
      62             :     unsigned int nFrameCnt;
      63             :     unsigned int nImageType;
      64             :     unsigned int nRowMajor;
      65             :     unsigned int nRgCnt;
      66             :     unsigned int nAzCnt;
      67             :     // long nScaleExponent;
      68             :     // long nScaleMantissa;
      69             :     // long nOffsetExponent;
      70             :     // long nOffsetMantissa;
      71             :   public:
      72             :     GFFDataset();
      73             :     ~GFFDataset();
      74             : 
      75             :     static GDALDataset *Open(GDALOpenInfo *);
      76             :     static int Identify(GDALOpenInfo *poOpenInfo);
      77             : };
      78             : 
      79           0 : GFFDataset::GFFDataset()
      80             :     : fp(nullptr), eDataType(GDT_Unknown), nEndianness(0), nVersionMajor(0),
      81             :       nVersionMinor(0), nLength(0), nBPP(0), nFrameCnt(0), nImageType(0),
      82           0 :       nRowMajor(0), nRgCnt(0), nAzCnt(0)
      83             : {
      84           0 : }
      85             : 
      86           0 : GFFDataset::~GFFDataset()
      87             : {
      88           0 :     if (fp != nullptr)
      89           0 :         VSIFCloseL(fp);
      90           0 : }
      91             : 
      92             : /*********************************************************************
      93             :  * Declaration and implementation of the GFFRasterBand Class         *
      94             :  *********************************************************************/
      95             : 
      96             : class GFFRasterBand final : public GDALPamRasterBand
      97             : {
      98             :     long nRasterBandMemory;
      99             :     int nSampleSize;
     100             : 
     101             :   public:
     102             :     GFFRasterBand(GFFDataset *, int, GDALDataType);
     103             :     CPLErr IReadBlock(int, int, void *) override;
     104             : };
     105             : 
     106           0 : static unsigned long GFFSampleSize(GDALDataType eDataType)
     107             : {
     108             :     // Determine the number of bytes per sample.
     109           0 :     unsigned long nBytes = 1;
     110           0 :     switch (eDataType)
     111             :     {
     112           0 :         case GDT_CInt16:
     113           0 :             nBytes = 4;
     114           0 :             break;
     115           0 :         case GDT_CInt32:
     116             :         case GDT_CFloat32:
     117           0 :             nBytes = 8;
     118           0 :             break;
     119           0 :         default:
     120           0 :             nBytes = 1;
     121             :     }
     122             : 
     123           0 :     return nBytes;
     124             : }
     125             : 
     126             : /************************************************************************/
     127             : /*                           GFFRasterBand()                            */
     128             : /************************************************************************/
     129           0 : GFFRasterBand::GFFRasterBand(GFFDataset *poDSIn, int nBandIn,
     130           0 :                              GDALDataType eDataTypeIn)
     131           0 :     : nRasterBandMemory(GFFSampleSize(eDataTypeIn) * poDSIn->GetRasterXSize()),
     132           0 :       nSampleSize(static_cast<int>(GFFSampleSize(eDataTypeIn)))
     133             : {
     134           0 :     poDS = poDSIn;
     135           0 :     nBand = nBandIn;
     136             : 
     137           0 :     eDataType = eDataTypeIn;
     138             : 
     139           0 :     nBlockXSize = poDS->GetRasterXSize();
     140           0 :     nBlockYSize = 1;
     141           0 : }
     142             : 
     143             : /************************************************************************/
     144             : /*                             IReadBlock()                             */
     145             : /************************************************************************/
     146             : 
     147           0 : CPLErr GFFRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
     148             :                                  void *pImage)
     149             : {
     150           0 :     GFFDataset *poGDS = (GFFDataset *)poDS;
     151           0 :     long nOffset = poGDS->nLength;
     152             : 
     153           0 :     VSIFSeekL(poGDS->fp,
     154           0 :               nOffset + (poGDS->GetRasterXSize() * nBlockYOff * (nSampleSize)),
     155             :               SEEK_SET);
     156             : 
     157             :     /* Ingest entire range line */
     158           0 :     if (VSIFReadL(pImage, nRasterBandMemory, 1, poGDS->fp) != 1)
     159           0 :         return CE_Failure;
     160             : 
     161             : #if defined(CPL_MSB)
     162             :     if (GDALDataTypeIsComplex(eDataType))
     163             :     {
     164             :         int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
     165             :         GDALSwapWords(pImage, nWordSize, nBlockXSize, 2 * nWordSize);
     166             :         GDALSwapWords(((GByte *)pImage) + nWordSize, nWordSize, nBlockXSize,
     167             :                       2 * nWordSize);
     168             :     }
     169             : #endif
     170             : 
     171           0 :     return CE_None;
     172             : }
     173             : 
     174             : /********************************************************************
     175             :  * ================================================================ *
     176             :  * Implementation of the GFFDataset Class                           *
     177             :  * ================================================================ *
     178             :  ********************************************************************/
     179             : 
     180             : /************************************************************************/
     181             : /*                              Identify()                              */
     182             : /************************************************************************/
     183       34050 : int GFFDataset::Identify(GDALOpenInfo *poOpenInfo)
     184             : {
     185       34050 :     if (poOpenInfo->nHeaderBytes < 7)
     186       27218 :         return 0;
     187             : 
     188        6832 :     if (STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "GSATIMG"))
     189           0 :         return 1;
     190             : 
     191        6832 :     return 0;
     192             : }
     193             : 
     194             : /************************************************************************/
     195             : /*                                Open()                                */
     196             : /************************************************************************/
     197             : 
     198       34050 : GDALDataset *GFFDataset::Open(GDALOpenInfo *poOpenInfo)
     199             : {
     200             :     /* Check that the dataset is indeed a GSAT File Format (GFF) file */
     201       34050 :     if (!GFFDataset::Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
     202       34049 :         return nullptr;
     203             : 
     204             :     /* -------------------------------------------------------------------- */
     205             :     /*      Confirm the requested access is supported.                      */
     206             :     /* -------------------------------------------------------------------- */
     207           0 :     if (poOpenInfo->eAccess == GA_Update)
     208             :     {
     209           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     210             :                  "The GFF driver does not support update access to existing"
     211             :                  " datasets.\n");
     212           0 :         return nullptr;
     213             :     }
     214             : 
     215           0 :     GFFDataset *poDS = new GFFDataset();
     216             : 
     217           0 :     poDS->fp = poOpenInfo->fpL;
     218           0 :     poOpenInfo->fpL = nullptr;
     219             : 
     220             :     /* Check the endianness of the file */
     221           0 :     VSIFSeekL(poDS->fp, 54, SEEK_SET);
     222           0 :     VSIFReadL(&(poDS->nEndianness), 2, 1, poDS->fp);
     223             : 
     224           0 :     VSIFSeekL(poDS->fp, 8, SEEK_SET);
     225           0 :     VSIFReadL(&poDS->nVersionMinor, 2, 1, poDS->fp);
     226           0 :     CPL_LSBPTR16(&poDS->nVersionMinor);
     227           0 :     VSIFReadL(&poDS->nVersionMajor, 2, 1, poDS->fp);
     228           0 :     CPL_LSBPTR16(&poDS->nVersionMajor);
     229           0 :     VSIFReadL(&poDS->nLength, 4, 1, poDS->fp);
     230           0 :     CPL_LSBPTR32(&poDS->nLength);
     231             : 
     232           0 :     unsigned short nCreatorLength = 0;
     233           0 :     VSIFReadL(&nCreatorLength, 2, 1, poDS->fp);
     234           0 :     CPL_LSBPTR16(&nCreatorLength);
     235             :     /* Hack for now... I should properly load the date metadata, for
     236             :      * example
     237             :      */
     238           0 :     VSIFSeekL(poDS->fp, 56, SEEK_SET);
     239             : 
     240             :     /* By looking at the Matlab code, one should write something like the
     241             :      * following test */
     242             :     /* but the results don't seem to be the ones really expected */
     243             :     /*if ((poDS->nVersionMajor == 1 && poDS->nVersionMinor > 7) ||
     244             :     (poDS->nVersionMajor > 1))
     245             :     {
     246             :         float fBPP;
     247             :         VSIFRead(&fBPP,4,1,poDS->fp);
     248             :         poDS->nBPP = fBPP;
     249             :     }
     250             :     else*/
     251             :     {
     252           0 :         VSIFReadL(&poDS->nBPP, 4, 1, poDS->fp);
     253           0 :         CPL_LSBPTR32(&poDS->nBPP);
     254             :     }
     255           0 :     VSIFReadL(&poDS->nFrameCnt, 4, 1, poDS->fp);
     256           0 :     CPL_LSBPTR32(&poDS->nFrameCnt);
     257           0 :     VSIFReadL(&poDS->nImageType, 4, 1, poDS->fp);
     258           0 :     CPL_LSBPTR32(&poDS->nImageType);
     259           0 :     VSIFReadL(&poDS->nRowMajor, 4, 1, poDS->fp);
     260           0 :     CPL_LSBPTR32(&poDS->nRowMajor);
     261           0 :     VSIFReadL(&poDS->nRgCnt, 4, 1, poDS->fp);
     262           0 :     CPL_LSBPTR32(&poDS->nRgCnt);
     263           0 :     VSIFReadL(&poDS->nAzCnt, 4, 1, poDS->fp);
     264           0 :     CPL_LSBPTR32(&poDS->nAzCnt);
     265             : 
     266             :     /* We now have enough information to determine the number format */
     267           0 :     switch (poDS->nImageType)
     268             :     {
     269           0 :         case 0:
     270           0 :             poDS->eDataType = GDT_Byte;
     271           0 :             break;
     272             : 
     273           0 :         case 1:
     274           0 :             if (poDS->nBPP == 4)
     275           0 :                 poDS->eDataType = GDT_CInt16;
     276             :             else
     277           0 :                 poDS->eDataType = GDT_CInt32;
     278           0 :             break;
     279             : 
     280           0 :         case 2:
     281           0 :             poDS->eDataType = GDT_CFloat32;
     282           0 :             break;
     283             : 
     284           0 :         default:
     285           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unknown image type found!");
     286           0 :             delete poDS;
     287           0 :             return nullptr;
     288             :     }
     289             : 
     290             :     /* Set raster width/height
     291             :      * Note that the images that are complex are listed as having twice the
     292             :      * number of X-direction values than there are actual pixels. This is
     293             :      * because whoever came up with the format was crazy (actually, my
     294             :      * hunch is that they designed it very much for Matlab)
     295             :      * */
     296           0 :     if (poDS->nRowMajor)
     297             :     {
     298           0 :         poDS->nRasterXSize = poDS->nRgCnt / (poDS->nImageType == 0 ? 1 : 2);
     299           0 :         poDS->nRasterYSize = poDS->nAzCnt;
     300             :     }
     301             :     else
     302             :     {
     303           0 :         poDS->nRasterXSize = poDS->nAzCnt / (poDS->nImageType == 0 ? 1 : 2);
     304           0 :         poDS->nRasterYSize = poDS->nRgCnt;
     305             :     }
     306             : 
     307           0 :     if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     308             :     {
     309           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     310             :                  "Invalid raster dimensions : %d x %d", poDS->nRasterXSize,
     311             :                  poDS->nRasterYSize);
     312           0 :         delete poDS;
     313           0 :         return nullptr;
     314             :     }
     315             : 
     316           0 :     poDS->SetBand(1, new GFFRasterBand(poDS, 1, poDS->eDataType));
     317             : 
     318             :     /* -------------------------------------------------------------------- */
     319             :     /*      Initialize any PAM information.                                 */
     320             :     /* -------------------------------------------------------------------- */
     321           0 :     poDS->SetDescription(poOpenInfo->pszFilename);
     322           0 :     poDS->TryLoadXML();
     323             : 
     324             :     /* -------------------------------------------------------------------- */
     325             :     /*      Support overviews.                                              */
     326             :     /* -------------------------------------------------------------------- */
     327           0 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
     328             : 
     329           0 :     return poDS;
     330             : }
     331             : 
     332             : /************************************************************************/
     333             : /*                          GDALRegister_GFF()                          */
     334             : /************************************************************************/
     335             : 
     336        1520 : void GDALRegister_GFF()
     337             : {
     338        1520 :     if (GDALGetDriverByName("GFF") != nullptr)
     339         301 :         return;
     340             : 
     341        1219 :     GDALDriver *poDriver = new GDALDriver();
     342             : 
     343        1219 :     poDriver->SetDescription("GFF");
     344        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     345        1219 :     poDriver->SetMetadataItem(
     346             :         GDAL_DMD_LONGNAME,
     347        1219 :         "Ground-based SAR Applications Testbed File Format (.gff)");
     348        1219 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/gff.html");
     349        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gff");
     350        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     351        1219 :     poDriver->pfnOpen = GFFDataset::Open;
     352        1219 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     353             : }

Generated by: LCOV version 1.14