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-05-02 00:41:30 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included
      12             :  * in all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      15             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      17             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      19             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      20             :  * DEALINGS IN THE SOFTWARE.
      21             :  */
      22             : 
      23             : #include "cpl_conv.h"
      24             : #include "cpl_port.h"
      25             : #include "cpl_float.h"
      26             : #include "cpl_string.h"
      27             : #include "cpl_vsi.h"
      28             : #include "gdal_frmts.h"
      29             : #include "gdal_priv.h"
      30             : 
      31             : #include <algorithm>
      32             : #include <string.h>
      33             : 
      34             : /* Various offsets, in bytes */
      35             : // Commented out the unused defines.
      36             : // #define BIB_OFFSET   0  /* Bytes in burst, valid only for ScanSAR */
      37             : // #define RSRI_OFFSET  4  /* Range Sample Relative Index */
      38             : constexpr int RS_OFFSET = 8; /* Range Samples, the length of a range line */
      39             : // #define AS_OFFSET    12 /* Azimuth Samples, the length of an azimuth column
      40             : // */ #define BI_OFFSET    16 /* Burst Index, the index number of the burst */
      41             : constexpr int RTNB_OFFSET =
      42             :     20; /* Rangeline total number of bytes, incl. annot. */
      43             : // #define TNL_OFFSET   24 /* Total Number of Lines */
      44             : constexpr int MAGIC1_OFFSET = 28;         /* Magic number 1: 0x43534152 */
      45             : constexpr int VERSION_NUMBER_OFFSET = 32; /* 1 for COSAR, 2 for COSSC */
      46             : 
      47             : // #define FILLER_MAGIC 0x7F7F7F7F  /* Filler value, we'll use this for a test
      48             : // */
      49             : 
      50             : class COSARDataset final : public GDALDataset
      51             : {
      52             :     friend class COSARRasterBand;
      53             :     VSILFILE *m_fp = nullptr;
      54             :     uint32_t m_nVersion = 0;
      55             : 
      56             :   public:
      57           0 :     COSARDataset() = default;
      58             :     ~COSARDataset();
      59             : 
      60             :     static GDALDataset *Open(GDALOpenInfo *);
      61             : };
      62             : 
      63             : class COSARRasterBand final : public GDALRasterBand
      64             : {
      65             :     uint32_t nRTNB;
      66             : 
      67             :   public:
      68             :     COSARRasterBand(COSARDataset *, uint32_t nRTNB);
      69             :     CPLErr IReadBlock(int, int, void *) override;
      70             : };
      71             : 
      72             : /*****************************************************************************
      73             :  * COSARRasterBand Implementation
      74             :  *****************************************************************************/
      75             : 
      76           0 : COSARRasterBand::COSARRasterBand(COSARDataset *pDS, uint32_t nRTNBIn)
      77           0 :     : nRTNB(nRTNBIn)
      78             : {
      79           0 :     COSARDataset *pCDS = cpl::down_cast<COSARDataset *>(pDS);
      80           0 :     nBlockXSize = pDS->GetRasterXSize();
      81           0 :     nBlockYSize = 1;
      82           0 :     eDataType = pCDS->m_nVersion == 1 ? GDT_CInt16 : GDT_CFloat32;
      83           0 : }
      84             : 
      85           0 : CPLErr COSARRasterBand::IReadBlock(int /*nBlockXOff*/, int nBlockYOff,
      86             :                                    void *pImage)
      87             : {
      88             : 
      89           0 :     COSARDataset *pCDS = cpl::down_cast<COSARDataset *>(poDS);
      90           0 :     constexpr uint32_t ITEM_SIZE = 2 * sizeof(int16_t);
      91             : 
      92             :     /* Find the line we want to be at */
      93             :     /* To explain some magic numbers:
      94             :      *   4 bytes for an entire sample (2 I, 2 Q)
      95             :      *   nBlockYOff + 4 = Y offset + 4 annotation lines at beginning
      96             :      *    of file
      97             :      */
      98             : 
      99           0 :     VSIFSeekL(pCDS->m_fp,
     100           0 :               static_cast<vsi_l_offset>(nRTNB) * (nBlockYOff + ITEM_SIZE),
     101             :               SEEK_SET);
     102             : 
     103             :     /* Read RSFV and RSLV (TX-GS-DD-3307) */
     104           0 :     uint32_t nRSFV = 0;  // Range Sample First Valid (starting at 1)
     105           0 :     uint32_t nRSLV = 0;  // Range Sample Last Valid (starting at 1)
     106           0 :     VSIFReadL(&nRSFV, 1, sizeof(nRSFV), pCDS->m_fp);
     107           0 :     VSIFReadL(&nRSLV, 1, sizeof(nRSLV), pCDS->m_fp);
     108             : 
     109           0 :     nRSFV = CPL_MSBWORD32(nRSFV);
     110           0 :     nRSLV = CPL_MSBWORD32(nRSLV);
     111             : 
     112           0 :     if (nRSLV < nRSFV || nRSFV == 0 || nRSLV == 0 ||
     113           0 :         nRSFV - 1 >= static_cast<uint32_t>(nBlockXSize) ||
     114           0 :         nRSLV - 1 >= static_cast<uint32_t>(nBlockXSize) ||
     115           0 :         nRSFV >= this->nRTNB || nRSLV > this->nRTNB)
     116             :     {
     117             :         /* throw an error */
     118           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     119             :                  "RSLV/RSFV values are not sane... oh dear.\n");
     120           0 :         return CE_Failure;
     121             :     }
     122             : 
     123             :     /* zero out the range line */
     124           0 :     memset(pImage, 0,
     125           0 :            static_cast<size_t>(nBlockXSize) *
     126           0 :                GDALGetDataTypeSizeBytes(eDataType));
     127             : 
     128             :     /* properly account for validity mask */
     129           0 :     if (nRSFV > 1)
     130             :     {
     131           0 :         VSIFSeekL(pCDS->m_fp,
     132           0 :                   static_cast<vsi_l_offset>(nRTNB) * (nBlockYOff + ITEM_SIZE) +
     133           0 :                       (nRSFV + 1) * ITEM_SIZE,
     134             :                   SEEK_SET);
     135             :     }
     136             : 
     137             :     /* Read the valid samples: */
     138           0 :     VSIFReadL(((char *)pImage) + (static_cast<size_t>(nRSFV - 1) * ITEM_SIZE),
     139           0 :               1, static_cast<size_t>(nRSLV - nRSFV + 1) * ITEM_SIZE,
     140             :               pCDS->m_fp);
     141             : 
     142             : #ifdef CPL_LSB
     143           0 :     GDALSwapWords(pImage, sizeof(int16_t), nBlockXSize * 2, sizeof(int16_t));
     144             : #endif
     145             : 
     146           0 :     if (pCDS->m_nVersion == 2)
     147             :     {
     148             :         // Convert from half-float to float32
     149             :         // Iterate starting the end to avoid overwriting first values
     150           0 :         for (int i = nBlockXSize * 2 - 1; i >= 0; --i)
     151             :         {
     152           0 :             static_cast<GUInt32 *>(pImage)[i] =
     153           0 :                 CPLHalfToFloat(static_cast<GUInt16 *>(pImage)[i]);
     154             :         }
     155             :     }
     156             : 
     157           0 :     return CE_None;
     158             : }
     159             : 
     160             : /*****************************************************************************
     161             :  * COSARDataset Implementation
     162             :  *****************************************************************************/
     163             : 
     164           0 : COSARDataset::~COSARDataset()
     165             : {
     166           0 :     if (m_fp != nullptr)
     167             :     {
     168           0 :         VSIFCloseL(m_fp);
     169             :     }
     170           0 : }
     171             : 
     172       30252 : GDALDataset *COSARDataset::Open(GDALOpenInfo *pOpenInfo)
     173             : {
     174             : 
     175             :     /* Check if we're actually a COSAR data set. */
     176       30252 :     if (pOpenInfo->nHeaderBytes < VERSION_NUMBER_OFFSET + 4 ||
     177        3804 :         pOpenInfo->fpL == nullptr)
     178       26488 :         return nullptr;
     179             : 
     180        3764 :     if (!STARTS_WITH_CI((char *)pOpenInfo->pabyHeader + MAGIC1_OFFSET, "CSAR"))
     181        3764 :         return nullptr;
     182             : 
     183             :     uint32_t nVersionMSB;
     184           0 :     memcpy(&nVersionMSB, pOpenInfo->pabyHeader + VERSION_NUMBER_OFFSET,
     185             :            sizeof(uint32_t));
     186           0 :     const uint32_t nVersion = CPL_MSBWORD32(nVersionMSB);
     187           0 :     if (nVersion != 1 && nVersion != 2)
     188           0 :         return nullptr;
     189             : 
     190             :     /* -------------------------------------------------------------------- */
     191             :     /*      Confirm the requested access is supported.                      */
     192             :     /* -------------------------------------------------------------------- */
     193           0 :     if (pOpenInfo->eAccess == GA_Update)
     194             :     {
     195           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     196             :                  "The COSAR driver does not support update access to existing"
     197             :                  " datasets.\n");
     198           0 :         return nullptr;
     199             :     }
     200             : 
     201             :     /* this is a cosar dataset */
     202           0 :     COSARDataset *pDS = new COSARDataset();
     203           0 :     pDS->m_nVersion = nVersion;
     204             : 
     205             :     /* steal fp */
     206           0 :     std::swap(pDS->m_fp, pOpenInfo->fpL);
     207             : 
     208           0 :     VSIFSeekL(pDS->m_fp, RS_OFFSET, SEEK_SET);
     209             :     int32_t nXSize;
     210           0 :     VSIFReadL(&nXSize, 1, sizeof(nXSize), pDS->m_fp);
     211           0 :     pDS->nRasterXSize = CPL_MSBWORD32(nXSize);
     212             : 
     213             :     int32_t nYSize;
     214           0 :     VSIFReadL(&nYSize, 1, sizeof(nYSize), pDS->m_fp);
     215           0 :     pDS->nRasterYSize = CPL_MSBWORD32(nYSize);
     216             : 
     217           0 :     if (!GDALCheckDatasetDimensions(pDS->nRasterXSize, pDS->nRasterYSize))
     218             :     {
     219           0 :         delete pDS;
     220           0 :         return nullptr;
     221             :     }
     222             : 
     223           0 :     VSIFSeekL(pDS->m_fp, RTNB_OFFSET, SEEK_SET);
     224             :     uint32_t nRTNB;
     225           0 :     VSIFReadL(&nRTNB, 1, sizeof(nRTNB), pDS->m_fp);
     226           0 :     nRTNB = CPL_MSBWORD32(nRTNB);
     227             : 
     228             :     /* Add raster band */
     229           0 :     pDS->SetBand(1, new COSARRasterBand(pDS, nRTNB));
     230           0 :     return pDS;
     231             : }
     232             : 
     233             : /* register the driver with GDAL */
     234        1512 : void GDALRegister_COSAR()
     235             : 
     236             : {
     237        1512 :     if (GDALGetDriverByName("cosar") != nullptr)
     238         295 :         return;
     239             : 
     240        1217 :     GDALDriver *poDriver = new GDALDriver();
     241        1217 :     poDriver->SetDescription("COSAR");
     242        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     243        1217 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     244        1217 :                               "COSAR Annotated Binary Matrix (TerraSAR-X)");
     245        1217 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/cosar.html");
     246        1217 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     247        1217 :     poDriver->pfnOpen = COSARDataset::Open;
     248        1217 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     249             : }

Generated by: LCOV version 1.14