LCOV - code coverage report
Current view: top level - frmts/cosar - cosar_dataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 18 85 21.2 %
Date: 2024-11-21 22:18:42 Functions: 2 7 28.6 %

          Line data    Source code
       1             : /* TerraSAR-X COSAR Format Driver
       2             :  * (C)2007 Philippe P. Vachon <philippe@cowpig.ca>
       3             :  * ---------------------------------------------------------------------------
       4             :  * SPDX-License-Identifier: MIT
       5             :  */
       6             : 
       7             : #include "cpl_conv.h"
       8             : #include "cpl_port.h"
       9             : #include "cpl_float.h"
      10             : #include "cpl_string.h"
      11             : #include "cpl_vsi.h"
      12             : #include "gdal_frmts.h"
      13             : #include "gdal_priv.h"
      14             : 
      15             : #include <algorithm>
      16             : #include <string.h>
      17             : 
      18             : /* Various offsets, in bytes */
      19             : // Commented out the unused defines.
      20             : // #define BIB_OFFSET   0  /* Bytes in burst, valid only for ScanSAR */
      21             : // #define RSRI_OFFSET  4  /* Range Sample Relative Index */
      22             : constexpr int RS_OFFSET = 8; /* Range Samples, the length of a range line */
      23             : // #define AS_OFFSET    12 /* Azimuth Samples, the length of an azimuth column
      24             : // */ #define BI_OFFSET    16 /* Burst Index, the index number of the burst */
      25             : constexpr int RTNB_OFFSET =
      26             :     20; /* Rangeline total number of bytes, incl. annot. */
      27             : // #define TNL_OFFSET   24 /* Total Number of Lines */
      28             : constexpr int MAGIC1_OFFSET = 28;         /* Magic number 1: 0x43534152 */
      29             : constexpr int VERSION_NUMBER_OFFSET = 32; /* 1 for COSAR, 2 for COSSC */
      30             : 
      31             : // #define FILLER_MAGIC 0x7F7F7F7F  /* Filler value, we'll use this for a test
      32             : // */
      33             : 
      34             : class COSARDataset final : public GDALDataset
      35             : {
      36             :     friend class COSARRasterBand;
      37             :     VSILFILE *m_fp = nullptr;
      38             :     uint32_t m_nVersion = 0;
      39             : 
      40             :   public:
      41           0 :     COSARDataset() = default;
      42             :     ~COSARDataset();
      43             : 
      44             :     static GDALDataset *Open(GDALOpenInfo *);
      45             : };
      46             : 
      47             : class COSARRasterBand final : public GDALRasterBand
      48             : {
      49             :     uint32_t nRTNB;
      50             : 
      51             :   public:
      52             :     COSARRasterBand(COSARDataset *, uint32_t nRTNB);
      53             :     CPLErr IReadBlock(int, int, void *) override;
      54             : };
      55             : 
      56             : /*****************************************************************************
      57             :  * COSARRasterBand Implementation
      58             :  *****************************************************************************/
      59             : 
      60           0 : COSARRasterBand::COSARRasterBand(COSARDataset *pDS, uint32_t nRTNBIn)
      61           0 :     : nRTNB(nRTNBIn)
      62             : {
      63           0 :     COSARDataset *pCDS = cpl::down_cast<COSARDataset *>(pDS);
      64           0 :     nBlockXSize = pDS->GetRasterXSize();
      65           0 :     nBlockYSize = 1;
      66           0 :     eDataType = pCDS->m_nVersion == 1 ? GDT_CInt16 : GDT_CFloat32;
      67           0 : }
      68             : 
      69           0 : CPLErr COSARRasterBand::IReadBlock(int /*nBlockXOff*/, int nBlockYOff,
      70             :                                    void *pImage)
      71             : {
      72             : 
      73           0 :     COSARDataset *pCDS = cpl::down_cast<COSARDataset *>(poDS);
      74           0 :     constexpr uint32_t ITEM_SIZE = 2 * sizeof(int16_t);
      75             : 
      76             :     /* Find the line we want to be at */
      77             :     /* To explain some magic numbers:
      78             :      *   4 bytes for an entire sample (2 I, 2 Q)
      79             :      *   nBlockYOff + 4 = Y offset + 4 annotation lines at beginning
      80             :      *    of file
      81             :      */
      82             : 
      83           0 :     VSIFSeekL(pCDS->m_fp,
      84           0 :               static_cast<vsi_l_offset>(nRTNB) * (nBlockYOff + ITEM_SIZE),
      85             :               SEEK_SET);
      86             : 
      87             :     /* Read RSFV and RSLV (TX-GS-DD-3307) */
      88           0 :     uint32_t nRSFV = 0;  // Range Sample First Valid (starting at 1)
      89           0 :     uint32_t nRSLV = 0;  // Range Sample Last Valid (starting at 1)
      90           0 :     VSIFReadL(&nRSFV, 1, sizeof(nRSFV), pCDS->m_fp);
      91           0 :     VSIFReadL(&nRSLV, 1, sizeof(nRSLV), pCDS->m_fp);
      92             : 
      93           0 :     nRSFV = CPL_MSBWORD32(nRSFV);
      94           0 :     nRSLV = CPL_MSBWORD32(nRSLV);
      95             : 
      96           0 :     if (nRSLV < nRSFV || nRSFV == 0 || nRSLV == 0 ||
      97           0 :         nRSFV - 1 >= static_cast<uint32_t>(nBlockXSize) ||
      98           0 :         nRSLV - 1 >= static_cast<uint32_t>(nBlockXSize) ||
      99           0 :         nRSFV >= this->nRTNB || nRSLV > this->nRTNB)
     100             :     {
     101             :         /* throw an error */
     102           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     103             :                  "RSLV/RSFV values are not sane... oh dear.\n");
     104           0 :         return CE_Failure;
     105             :     }
     106             : 
     107             :     /* zero out the range line */
     108           0 :     memset(pImage, 0,
     109           0 :            static_cast<size_t>(nBlockXSize) *
     110           0 :                GDALGetDataTypeSizeBytes(eDataType));
     111             : 
     112             :     /* properly account for validity mask */
     113           0 :     if (nRSFV > 1)
     114             :     {
     115           0 :         VSIFSeekL(pCDS->m_fp,
     116           0 :                   static_cast<vsi_l_offset>(nRTNB) * (nBlockYOff + ITEM_SIZE) +
     117           0 :                       (nRSFV + 1) * ITEM_SIZE,
     118             :                   SEEK_SET);
     119             :     }
     120             : 
     121             :     /* Read the valid samples: */
     122           0 :     VSIFReadL(((char *)pImage) + (static_cast<size_t>(nRSFV - 1) * ITEM_SIZE),
     123           0 :               1, static_cast<size_t>(nRSLV - nRSFV + 1) * ITEM_SIZE,
     124             :               pCDS->m_fp);
     125             : 
     126             : #ifdef CPL_LSB
     127           0 :     GDALSwapWords(pImage, sizeof(int16_t), nBlockXSize * 2, sizeof(int16_t));
     128             : #endif
     129             : 
     130           0 :     if (pCDS->m_nVersion == 2)
     131             :     {
     132             :         // Convert from half-float to float32
     133             :         // Iterate starting the end to avoid overwriting first values
     134           0 :         for (int i = nBlockXSize * 2 - 1; i >= 0; --i)
     135             :         {
     136           0 :             static_cast<GUInt32 *>(pImage)[i] =
     137           0 :                 CPLHalfToFloat(static_cast<GUInt16 *>(pImage)[i]);
     138             :         }
     139             :     }
     140             : 
     141           0 :     return CE_None;
     142             : }
     143             : 
     144             : /*****************************************************************************
     145             :  * COSARDataset Implementation
     146             :  *****************************************************************************/
     147             : 
     148           0 : COSARDataset::~COSARDataset()
     149             : {
     150           0 :     if (m_fp != nullptr)
     151             :     {
     152           0 :         VSIFCloseL(m_fp);
     153             :     }
     154           0 : }
     155             : 
     156       31745 : GDALDataset *COSARDataset::Open(GDALOpenInfo *pOpenInfo)
     157             : {
     158             : 
     159             :     /* Check if we're actually a COSAR data set. */
     160       31745 :     if (pOpenInfo->nHeaderBytes < VERSION_NUMBER_OFFSET + 4 ||
     161        3908 :         pOpenInfo->fpL == nullptr)
     162       27877 :         return nullptr;
     163             : 
     164        3868 :     if (!STARTS_WITH_CI((char *)pOpenInfo->pabyHeader + MAGIC1_OFFSET, "CSAR"))
     165        3868 :         return nullptr;
     166             : 
     167             :     uint32_t nVersionMSB;
     168           0 :     memcpy(&nVersionMSB, pOpenInfo->pabyHeader + VERSION_NUMBER_OFFSET,
     169             :            sizeof(uint32_t));
     170           0 :     const uint32_t nVersion = CPL_MSBWORD32(nVersionMSB);
     171           0 :     if (nVersion != 1 && nVersion != 2)
     172           0 :         return nullptr;
     173             : 
     174             :     /* -------------------------------------------------------------------- */
     175             :     /*      Confirm the requested access is supported.                      */
     176             :     /* -------------------------------------------------------------------- */
     177           0 :     if (pOpenInfo->eAccess == GA_Update)
     178             :     {
     179           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     180             :                  "The COSAR driver does not support update access to existing"
     181             :                  " datasets.\n");
     182           0 :         return nullptr;
     183             :     }
     184             : 
     185             :     /* this is a cosar dataset */
     186           0 :     COSARDataset *pDS = new COSARDataset();
     187           0 :     pDS->m_nVersion = nVersion;
     188             : 
     189             :     /* steal fp */
     190           0 :     std::swap(pDS->m_fp, pOpenInfo->fpL);
     191             : 
     192           0 :     VSIFSeekL(pDS->m_fp, RS_OFFSET, SEEK_SET);
     193             :     int32_t nXSize;
     194           0 :     VSIFReadL(&nXSize, 1, sizeof(nXSize), pDS->m_fp);
     195           0 :     pDS->nRasterXSize = CPL_MSBWORD32(nXSize);
     196             : 
     197             :     int32_t nYSize;
     198           0 :     VSIFReadL(&nYSize, 1, sizeof(nYSize), pDS->m_fp);
     199           0 :     pDS->nRasterYSize = CPL_MSBWORD32(nYSize);
     200             : 
     201           0 :     if (!GDALCheckDatasetDimensions(pDS->nRasterXSize, pDS->nRasterYSize))
     202             :     {
     203           0 :         delete pDS;
     204           0 :         return nullptr;
     205             :     }
     206             : 
     207           0 :     VSIFSeekL(pDS->m_fp, RTNB_OFFSET, SEEK_SET);
     208             :     uint32_t nRTNB;
     209           0 :     VSIFReadL(&nRTNB, 1, sizeof(nRTNB), pDS->m_fp);
     210           0 :     nRTNB = CPL_MSBWORD32(nRTNB);
     211             : 
     212             :     /* Add raster band */
     213           0 :     pDS->SetBand(1, new COSARRasterBand(pDS, nRTNB));
     214           0 :     return pDS;
     215             : }
     216             : 
     217             : /* register the driver with GDAL */
     218        1595 : void GDALRegister_COSAR()
     219             : 
     220             : {
     221        1595 :     if (GDALGetDriverByName("cosar") != nullptr)
     222         302 :         return;
     223             : 
     224        1293 :     GDALDriver *poDriver = new GDALDriver();
     225        1293 :     poDriver->SetDescription("COSAR");
     226        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     227        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     228        1293 :                               "COSAR Annotated Binary Matrix (TerraSAR-X)");
     229        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/cosar.html");
     230        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     231        1293 :     poDriver->pfnOpen = COSARDataset::Open;
     232        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     233             : }

Generated by: LCOV version 1.14