LCOV - code coverage report
Current view: top level - frmts/airsar - airsardataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 16 232 6.9 %
Date: 2025-10-17 19:28:35 Functions: 2 11 18.2 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  AirSAR Reader
       4             :  * Purpose:  Implements read support for AirSAR Polarimetric data.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2007-2009, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : #include "cpl_vsi.h"
      17             : #include "gdal_frmts.h"
      18             : #include "gdal_pam.h"
      19             : #include "gdal_driver.h"
      20             : #include "gdal_drivermanager.h"
      21             : #include "gdal_openinfo.h"
      22             : #include "gdal_cpp_functions.h"
      23             : 
      24             : /************************************************************************/
      25             : /* ==================================================================== */
      26             : /*                              AirSARDataset                           */
      27             : /* ==================================================================== */
      28             : /************************************************************************/
      29             : 
      30             : class AirSARRasterBand;
      31             : 
      32             : class AirSARDataset final : public GDALPamDataset
      33             : {
      34             :     friend class AirSARRasterBand;
      35             : 
      36             :     VSILFILE *fp;
      37             : 
      38             :     int nLoadedLine;
      39             :     GByte *pabyCompressedLine;
      40             :     double *padfMatrix;
      41             : 
      42             :     int nDataStart;
      43             :     int nRecordLength;
      44             : 
      45             :     CPLErr LoadLine(int iLine);
      46             : 
      47             :     static char **ReadHeader(VSILFILE *fp, int nFileOffset,
      48             :                              const char *pszPrefix, int nMaxLines);
      49             : 
      50             :   public:
      51             :     AirSARDataset();
      52             :     ~AirSARDataset() override;
      53             : 
      54             :     static GDALDataset *Open(GDALOpenInfo *);
      55             : };
      56             : 
      57             : /************************************************************************/
      58             : /* ==================================================================== */
      59             : /*                            AirSARRasterBand                          */
      60             : /* ==================================================================== */
      61             : /************************************************************************/
      62             : 
      63             : class AirSARRasterBand final : public GDALPamRasterBand
      64             : {
      65             :   public:
      66             :     AirSARRasterBand(AirSARDataset *, int);
      67             :     ~AirSARRasterBand() override;
      68             : 
      69             :     CPLErr IReadBlock(int, int, void *) override;
      70             : };
      71             : 
      72             : /* locations of stokes matrix values within padfMatrix ... same order as they
      73             :    are computed in the document. */
      74             : 
      75             : constexpr int M11 = 0;
      76             : constexpr int M12 = 1;
      77             : constexpr int M13 = 2;
      78             : constexpr int M14 = 3;
      79             : constexpr int M23 = 4;
      80             : constexpr int M24 = 5;
      81             : constexpr int M33 = 6;
      82             : constexpr int M34 = 7;
      83             : constexpr int M44 = 8;
      84             : constexpr int M22 = 9;
      85             : 
      86             : /************************************************************************/
      87             : /*                          AirSARRasterBand()                          */
      88             : /************************************************************************/
      89             : 
      90           0 : AirSARRasterBand::AirSARRasterBand(AirSARDataset *poDSIn, int nBandIn)
      91             : 
      92             : {
      93           0 :     poDS = poDSIn;
      94           0 :     nBand = nBandIn;
      95             : 
      96           0 :     nBlockXSize = poDS->GetRasterXSize();
      97           0 :     nBlockYSize = 1;
      98             : 
      99           0 :     if (this->nBand == 2 || this->nBand == 3 || this->nBand == 5)
     100           0 :         eDataType = GDT_CFloat32;
     101             :     else
     102           0 :         eDataType = GDT_Float32;
     103             : 
     104           0 :     switch (nBand)
     105             :     {
     106           0 :         case 1:
     107           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_11");
     108           0 :             SetDescription("Covariance_11");
     109           0 :             eDataType = GDT_CFloat32;
     110           0 :             break;
     111             : 
     112           0 :         case 2:
     113           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_12");
     114           0 :             SetDescription("Covariance_12");
     115           0 :             eDataType = GDT_CFloat32;
     116           0 :             break;
     117             : 
     118           0 :         case 3:
     119           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_13");
     120           0 :             SetDescription("Covariance_13");
     121           0 :             eDataType = GDT_CFloat32;
     122           0 :             break;
     123             : 
     124           0 :         case 4:
     125           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_22");
     126           0 :             SetDescription("Covariance_22");
     127           0 :             eDataType = GDT_CFloat32;
     128           0 :             break;
     129             : 
     130           0 :         case 5:
     131           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_23");
     132           0 :             SetDescription("Covariance_23");
     133           0 :             eDataType = GDT_CFloat32;
     134           0 :             break;
     135             : 
     136           0 :         case 6:
     137           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_33");
     138           0 :             SetDescription("Covariance_33");
     139           0 :             eDataType = GDT_CFloat32;
     140           0 :             break;
     141             :     }
     142           0 : }
     143             : 
     144             : /************************************************************************/
     145             : /*                         ~AirSARRasterBand()                          */
     146             : /************************************************************************/
     147             : 
     148           0 : AirSARRasterBand::~AirSARRasterBand()
     149             : 
     150             : {
     151           0 : }
     152             : 
     153             : /************************************************************************/
     154             : /*                             IReadBlock()                             */
     155             : /************************************************************************/
     156             : 
     157           0 : CPLErr AirSARRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
     158             :                                     void *pImage)
     159             : {
     160           0 :     float *pafLine = (float *)pImage;
     161           0 :     const double SQRT_2 = 1.4142135623730951;
     162             : 
     163           0 :     CPLErr eErr = cpl::down_cast<AirSARDataset *>(poDS)->LoadLine(nBlockYOff);
     164           0 :     if (eErr != CE_None)
     165           0 :         return eErr;
     166             : 
     167           0 :     double *padfMatrix = cpl::down_cast<AirSARDataset *>(poDS)->padfMatrix;
     168             : 
     169           0 :     if (nBand == 1) /* C11 */
     170             :     {
     171           0 :         for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     172             :         {
     173           0 :             double *m = padfMatrix + 10 * iPixel;
     174             : 
     175           0 :             pafLine[iPixel * 2 + 0] = (float)(m[M11] + m[M22] + 2 * m[M12]);
     176           0 :             pafLine[iPixel * 2 + 1] = 0.0;
     177             :         }
     178             :     }
     179           0 :     else if (nBand == 2) /* C12 */
     180             :     {
     181           0 :         for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     182             :         {
     183           0 :             double *m = padfMatrix + 10 * iPixel;
     184             : 
     185             :             // real
     186           0 :             pafLine[iPixel * 2 + 0] = (float)(SQRT_2 * (m[M13] + m[M23]));
     187             : 
     188             :             // imaginary
     189           0 :             pafLine[iPixel * 2 + 1] = (float)(-SQRT_2 * (m[M24] + m[M14]));
     190             :         }
     191             :     }
     192           0 :     else if (nBand == 3) /* C13 */
     193             :     {
     194           0 :         for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     195             :         {
     196           0 :             double *m = padfMatrix + 10 * iPixel;
     197             : 
     198             :             // real
     199           0 :             pafLine[iPixel * 2 + 0] = (float)(2 * m[M33] + m[M22] - m[M11]);
     200             : 
     201             :             // imaginary
     202           0 :             pafLine[iPixel * 2 + 1] = (float)(-2 * m[M34]);
     203             :         }
     204             :     }
     205           0 :     else if (nBand == 4) /* C22 */
     206             :     {
     207           0 :         for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     208             :         {
     209           0 :             double *m = padfMatrix + 10 * iPixel;
     210             : 
     211           0 :             pafLine[iPixel * 2 + 0] = (float)(2 * (m[M11] - m[M22]));
     212           0 :             pafLine[iPixel * 2 + 1] = 0.0;
     213             :         }
     214             :     }
     215           0 :     else if (nBand == 5) /* C23 */
     216             :     {
     217           0 :         for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     218             :         {
     219           0 :             double *m = padfMatrix + 10 * iPixel;
     220             : 
     221             :             // real
     222           0 :             pafLine[iPixel * 2 + 0] = (float)(SQRT_2 * (m[M13] - m[M23]));
     223             : 
     224             :             // imaginary
     225           0 :             pafLine[iPixel * 2 + 1] = (float)(SQRT_2 * (m[M24] - m[M14]));
     226             :         }
     227             :     }
     228           0 :     else if (nBand == 6) /* C33 */
     229             :     {
     230           0 :         for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     231             :         {
     232           0 :             double *m = padfMatrix + 10 * iPixel;
     233             : 
     234           0 :             pafLine[iPixel * 2 + 0] = (float)(m[M11] + m[M22] - 2 * m[M12]);
     235           0 :             pafLine[iPixel * 2 + 1] = 0.0;
     236             :         }
     237             :     }
     238             : 
     239           0 :     return CE_None;
     240             : }
     241             : 
     242             : /************************************************************************/
     243             : /* ==================================================================== */
     244             : /*                              AirSARDataset                           */
     245             : /* ==================================================================== */
     246             : /************************************************************************/
     247             : 
     248             : /************************************************************************/
     249             : /*                           AirSARDataset()                            */
     250             : /************************************************************************/
     251             : 
     252           0 : AirSARDataset::AirSARDataset()
     253             :     : fp(nullptr), nLoadedLine(-1), pabyCompressedLine(nullptr),
     254           0 :       padfMatrix(nullptr), nDataStart(0), nRecordLength(0)
     255             : {
     256           0 : }
     257             : 
     258             : /************************************************************************/
     259             : /*                           ~AirSARDataset()                           */
     260             : /************************************************************************/
     261             : 
     262           0 : AirSARDataset::~AirSARDataset()
     263             : 
     264             : {
     265           0 :     FlushCache(true);
     266           0 :     CPLFree(pabyCompressedLine);
     267           0 :     CPLFree(padfMatrix);
     268             : 
     269           0 :     if (fp != nullptr)
     270             :     {
     271           0 :         VSIFCloseL(fp);
     272           0 :         fp = nullptr;
     273             :     }
     274           0 : }
     275             : 
     276             : /************************************************************************/
     277             : /*                              LoadLine()                              */
     278             : /************************************************************************/
     279             : 
     280           0 : CPLErr AirSARDataset::LoadLine(int iLine)
     281             : 
     282             : {
     283           0 :     if (iLine == nLoadedLine)
     284           0 :         return CE_None;
     285             : 
     286             :     /* -------------------------------------------------------------------- */
     287             :     /*      allocate working buffers if we don't have them already.         */
     288             :     /* -------------------------------------------------------------------- */
     289           0 :     if (pabyCompressedLine == nullptr)
     290             :     {
     291           0 :         pabyCompressedLine = (GByte *)VSI_MALLOC2_VERBOSE(nRasterXSize, 10);
     292             : 
     293           0 :         padfMatrix =
     294           0 :             (double *)VSI_MALLOC2_VERBOSE(10 * sizeof(double), nRasterXSize);
     295           0 :         if (pabyCompressedLine == nullptr || padfMatrix == nullptr)
     296             :         {
     297           0 :             CPLFree(pabyCompressedLine);
     298           0 :             CPLFree(padfMatrix);
     299           0 :             return CE_Failure;
     300             :         }
     301             :     }
     302             : 
     303           0 :     CPLAssert(nRecordLength == nRasterXSize * 10);
     304             : 
     305             :     /* -------------------------------------------------------------------- */
     306             :     /*      Load raw compressed data.                                       */
     307             :     /* -------------------------------------------------------------------- */
     308           0 :     if (VSIFSeekL(fp, nDataStart + iLine * nRecordLength, SEEK_SET) != 0 ||
     309           0 :         ((int)VSIFReadL(pabyCompressedLine, 10, nRasterXSize, fp)) !=
     310           0 :             nRasterXSize)
     311             :     {
     312           0 :         CPLError(CE_Failure, CPLE_FileIO,
     313             :                  "Error reading %d bytes for line %d at offset %d.\n%s",
     314           0 :                  nRasterXSize * 10, iLine, nDataStart + iLine * nRecordLength,
     315           0 :                  VSIStrerror(errno));
     316           0 :         return CE_Failure;
     317             :     }
     318             : 
     319             :     /* -------------------------------------------------------------------- */
     320             :     /*      Build stokes matrix                                             */
     321             :     /* -------------------------------------------------------------------- */
     322           0 :     for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
     323             :     {
     324           0 :         double *M = padfMatrix + 10 * iPixel;
     325           0 :         signed char *byte = (signed char *)pabyCompressedLine + 10 * iPixel - 1;
     326           0 :         const double gen_fac = 1.0;  // should we have a general scale factor?
     327             : 
     328           0 :         M[M11] = (byte[2] / 254.0 + 1.5) * pow(2.0, byte[1]) * gen_fac;
     329           0 :         M[M12] = byte[3] * M[M11] / 127.0;
     330           0 :         M[M13] = byte[4] * fabs((double)byte[4]) * M[M11] / (127 * 127);
     331           0 :         M[M14] = byte[5] * fabs((double)byte[5]) * M[M11] / (127 * 127);
     332           0 :         M[M23] = byte[6] * fabs((double)byte[6]) * M[M11] / (127 * 127);
     333           0 :         M[M24] = byte[7] * fabs((double)byte[7]) * M[M11] / (127 * 127);
     334           0 :         M[M33] = byte[8] * M[M11] / 127;
     335           0 :         M[M34] = byte[9] * M[M11] / 127;
     336           0 :         M[M44] = byte[10] * M[M11] / 127;
     337           0 :         M[M22] = M[M11] - M[M33] - M[M44];
     338             :     }
     339             : 
     340           0 :     return CE_None;
     341             : }
     342             : 
     343             : /************************************************************************/
     344             : /*                             ReadHeader()                             */
     345             : /*                                                                      */
     346             : /*      Read the AirSAR header.  We assume an equal sign separates      */
     347             : /*      the keyword name from the value.  If not, assume the last       */
     348             : /*      "blank delimited" word is the value and everything else is a    */
     349             : /*      keyword.                                                        */
     350             : /*                                                                      */
     351             : /*      The records are 50 characters each.  Read till we get an all    */
     352             : /*      blank record or some zero bytes.                                */
     353             : /************************************************************************/
     354             : 
     355           0 : char **AirSARDataset::ReadHeader(VSILFILE *fp, int nFileOffset,
     356             :                                  const char *pszPrefix, int nMaxLines)
     357             : 
     358             : {
     359           0 :     char **papszHeadInfo = nullptr;
     360             :     char szLine[51];
     361             : 
     362           0 :     VSIFSeekL(fp, nFileOffset, SEEK_SET);
     363             : 
     364             :     /* ==================================================================== */
     365             :     /*      Loop collecting one line at a time.                             */
     366             :     /* ==================================================================== */
     367           0 :     for (int iLine = 0; iLine < nMaxLines; iLine++)
     368             :     {
     369             :         /* --------------------------------------------------------------------
     370             :          */
     371             :         /*      Read a 50 byte header record. */
     372             :         /* --------------------------------------------------------------------
     373             :          */
     374           0 :         if (VSIFReadL(szLine, 1, 50, fp) != 50)
     375             :         {
     376           0 :             CPLError(CE_Failure, CPLE_FileIO,
     377             :                      "Read error collecting AirSAR header.");
     378           0 :             CSLDestroy(papszHeadInfo);
     379           0 :             return nullptr;
     380             :         }
     381             : 
     382           0 :         szLine[50] = '\0';
     383             : 
     384             :         /* --------------------------------------------------------------------
     385             :          */
     386             :         /*      Is it all spaces, or does it have a zero byte? */
     387             :         /* --------------------------------------------------------------------
     388             :          */
     389           0 :         bool bAllSpaces = true;
     390           0 :         bool bHasIllegalChars = false;
     391             : 
     392           0 :         for (int i = 0; i < 50; i++)
     393             :         {
     394           0 :             if (szLine[i] == '\0')
     395           0 :                 break;
     396             : 
     397           0 :             if (szLine[i] != ' ')
     398           0 :                 bAllSpaces = false;
     399             : 
     400           0 :             if (((unsigned char *)szLine)[i] > 127 ||
     401           0 :                 ((unsigned char *)szLine)[i] < 10)
     402           0 :                 bHasIllegalChars = true;
     403             :         }
     404             : 
     405           0 :         if (bAllSpaces || bHasIllegalChars)
     406             :             break;
     407             : 
     408             :         /* --------------------------------------------------------------------
     409             :          */
     410             :         /*      Find the pivot between the keyword name and value. */
     411             :         /* --------------------------------------------------------------------
     412             :          */
     413           0 :         int iPivot = -1;
     414             : 
     415           0 :         for (int i = 0; i < 50; i++)
     416             :         {
     417           0 :             if (szLine[i] == '=')
     418             :             {
     419           0 :                 iPivot = i;
     420           0 :                 break;
     421             :             }
     422             :         }
     423             : 
     424             :         // If no "=" found, split on first double white space
     425           0 :         if (iPivot == -1)
     426             :         {
     427           0 :             for (int i = 48; i >= 0; i--)
     428             :             {
     429           0 :                 if (szLine[i] == ' ' && szLine[i + 1] == ' ')
     430             :                 {
     431           0 :                     iPivot = i;
     432           0 :                     break;
     433             :                 }
     434             :             }
     435             :         }
     436             : 
     437           0 :         if (iPivot == -1)  // Yikes!
     438             :         {
     439           0 :             CPLDebug("AIRSAR", "No pivot in line `%s'.", szLine);
     440           0 :             CPLAssert(iPivot != -1);
     441           0 :             break;
     442             :         }
     443             : 
     444             :         /* --------------------------------------------------------------------
     445             :          */
     446             :         /*      Trace ahead to the first non-white space value character. */
     447             :         /* --------------------------------------------------------------------
     448             :          */
     449           0 :         int iValue = iPivot + 1;
     450             : 
     451           0 :         while (iValue < 50 && szLine[iValue] == ' ')
     452           0 :             iValue++;
     453             : 
     454             :         /* --------------------------------------------------------------------
     455             :          */
     456             :         /*      Strip any white space off the keyword. */
     457             :         /* --------------------------------------------------------------------
     458             :          */
     459           0 :         int iKeyEnd = iPivot - 1;
     460             : 
     461           0 :         while (iKeyEnd > 0 && szLine[iKeyEnd] == ' ')
     462           0 :             iKeyEnd--;
     463             : 
     464           0 :         szLine[iKeyEnd + 1] = '\0';
     465             : 
     466             :         /* --------------------------------------------------------------------
     467             :          */
     468             :         /*      Convert spaces or colons into underscores in the key name. */
     469             :         /* --------------------------------------------------------------------
     470             :          */
     471           0 :         for (int i = 0; szLine[i] != '\0'; i++)
     472             :         {
     473           0 :             if (szLine[i] == ' ' || szLine[i] == ':' || szLine[i] == ',')
     474           0 :                 szLine[i] = '_';
     475             :         }
     476             : 
     477             :         /* --------------------------------------------------------------------
     478             :          */
     479             :         /*      Prefix key name with provided prefix string. */
     480             :         /* --------------------------------------------------------------------
     481             :          */
     482             :         char szPrefixedKeyName[55];
     483             : 
     484           0 :         snprintf(szPrefixedKeyName, sizeof(szPrefixedKeyName), "%s_%s",
     485             :                  pszPrefix, szLine);
     486             : 
     487             :         papszHeadInfo =
     488           0 :             CSLSetNameValue(papszHeadInfo, szPrefixedKeyName, szLine + iValue);
     489             :     }
     490             : 
     491           0 :     return papszHeadInfo;
     492             : }
     493             : 
     494             : /************************************************************************/
     495             : /*                                Open()                                */
     496             : /************************************************************************/
     497             : 
     498       37909 : GDALDataset *AirSARDataset::Open(GDALOpenInfo *poOpenInfo)
     499             : 
     500             : {
     501       37909 :     if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 800)
     502       33758 :         return nullptr;
     503             : 
     504             :     /* -------------------------------------------------------------------- */
     505             :     /*      Check for AirSAR/ keyword.                                      */
     506             :     /* -------------------------------------------------------------------- */
     507        4151 :     if (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader,
     508             :                         "RECORD LENGTH IN BYTES"))
     509        4151 :         return nullptr;
     510             : 
     511           0 :     if (strstr((char *)poOpenInfo->pabyHeader, "COMPRESSED") == nullptr ||
     512           0 :         strstr((char *)poOpenInfo->pabyHeader, "JPL AIRCRAFT") == nullptr)
     513           0 :         return nullptr;
     514             : 
     515             :     /* -------------------------------------------------------------------- */
     516             :     /*      Parse the header fields.  We turn all the transform the         */
     517             :     /*      keywords by converting spaces to underscores so they will be    */
     518             :     /*      "well behaved" as metadata keywords.                            */
     519             :     /* -------------------------------------------------------------------- */
     520           0 :     char **papszMD = ReadHeader(poOpenInfo->fpL, 0, "MH", 20);
     521             : 
     522           0 :     if (papszMD == nullptr)
     523           0 :         return nullptr;
     524             : 
     525             :     /* -------------------------------------------------------------------- */
     526             :     /*      Confirm the requested access is supported.                      */
     527             :     /* -------------------------------------------------------------------- */
     528           0 :     if (poOpenInfo->eAccess == GA_Update)
     529             :     {
     530           0 :         ReportUpdateNotSupportedByDriver("AIRSAR");
     531           0 :         CSLDestroy(papszMD);
     532           0 :         return nullptr;
     533             :     }
     534             :     /* -------------------------------------------------------------------- */
     535             :     /*      Create a corresponding GDALDataset.                             */
     536             :     /* -------------------------------------------------------------------- */
     537           0 :     AirSARDataset *poDS = new AirSARDataset();
     538             : 
     539             :     /* -------------------------------------------------------------------- */
     540             :     /*      Extract some key information.                                   */
     541             :     /* -------------------------------------------------------------------- */
     542             : 
     543           0 :     poDS->nRasterXSize =
     544           0 :         atoi(CSLFetchNameValue(papszMD, "MH_NUMBER_OF_SAMPLES_PER_RECORD"));
     545           0 :     poDS->nRasterYSize =
     546           0 :         atoi(CSLFetchNameValue(papszMD, "MH_NUMBER_OF_LINES_IN_IMAGE"));
     547             : 
     548           0 :     poDS->nRecordLength =
     549           0 :         atoi(CSLFetchNameValue(papszMD, "MH_RECORD_LENGTH_IN_BYTES"));
     550             : 
     551           0 :     poDS->nDataStart =
     552           0 :         atoi(CSLFetchNameValue(papszMD, "MH_BYTE_OFFSET_OF_FIRST_DATA_RECORD"));
     553             : 
     554             :     /* -------------------------------------------------------------------- */
     555             :     /*      Adopt the openinfo file pointer.                                */
     556             :     /* -------------------------------------------------------------------- */
     557           0 :     poDS->fp = poOpenInfo->fpL;
     558           0 :     poOpenInfo->fpL = nullptr;
     559             : 
     560             :     /* -------------------------------------------------------------------- */
     561             :     /*      Read and merge parameter header into metadata.  Prefix          */
     562             :     /*      parameter header values with PH_.                               */
     563             :     /* -------------------------------------------------------------------- */
     564           0 :     int nPHOffset = 0;
     565             : 
     566           0 :     if (CSLFetchNameValue(papszMD, "MH_BYTE_OFFSET_OF_PARAMETER_HEADER") !=
     567             :         nullptr)
     568             :     {
     569           0 :         nPHOffset = atoi(
     570             :             CSLFetchNameValue(papszMD, "MH_BYTE_OFFSET_OF_PARAMETER_HEADER"));
     571           0 :         char **papszPHInfo = ReadHeader(poDS->fp, nPHOffset, "PH", 100);
     572             : 
     573           0 :         papszMD = CSLInsertStrings(papszMD, CSLCount(papszMD), papszPHInfo);
     574             : 
     575           0 :         CSLDestroy(papszPHInfo);
     576             :     }
     577             : 
     578             :     /* -------------------------------------------------------------------- */
     579             :     /*      Read and merge calibration header into metadata.  Prefix        */
     580             :     /*      parameter header values with CH_.                               */
     581             :     /* -------------------------------------------------------------------- */
     582           0 :     if (nPHOffset != 0)
     583             :     {
     584             :         char **papszCHInfo =
     585           0 :             ReadHeader(poDS->fp, nPHOffset + poDS->nRecordLength, "CH", 18);
     586             : 
     587           0 :         papszMD = CSLInsertStrings(papszMD, CSLCount(papszMD), papszCHInfo);
     588             : 
     589           0 :         CSLDestroy(papszCHInfo);
     590             :     }
     591             : 
     592             :     /* -------------------------------------------------------------------- */
     593             :     /*      Assign metadata to dataset.                                     */
     594             :     /* -------------------------------------------------------------------- */
     595           0 :     poDS->SetMetadata(papszMD);
     596           0 :     CSLDestroy(papszMD);
     597             : 
     598             :     /* -------------------------------------------------------------------- */
     599             :     /*      Create band information objects.                                */
     600             :     /* -------------------------------------------------------------------- */
     601           0 :     poDS->SetBand(1, new AirSARRasterBand(poDS, 1));
     602           0 :     poDS->SetBand(2, new AirSARRasterBand(poDS, 2));
     603           0 :     poDS->SetBand(3, new AirSARRasterBand(poDS, 3));
     604           0 :     poDS->SetBand(4, new AirSARRasterBand(poDS, 4));
     605           0 :     poDS->SetBand(5, new AirSARRasterBand(poDS, 5));
     606           0 :     poDS->SetBand(6, new AirSARRasterBand(poDS, 6));
     607             : 
     608           0 :     poDS->SetMetadataItem("MATRIX_REPRESENTATION", "SYMMETRIZED_COVARIANCE");
     609             : 
     610             :     /* -------------------------------------------------------------------- */
     611             :     /*      Initialize any PAM information.                                 */
     612             :     /* -------------------------------------------------------------------- */
     613           0 :     poDS->SetDescription(poOpenInfo->pszFilename);
     614           0 :     poDS->TryLoadXML();
     615             : 
     616           0 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
     617             : 
     618           0 :     return poDS;
     619             : }
     620             : 
     621             : /************************************************************************/
     622             : /*                        GDALRegister_AirSAR()                         */
     623             : /************************************************************************/
     624             : 
     625        2033 : void GDALRegister_AirSAR()
     626             : 
     627             : {
     628        2033 :     if (GDALGetDriverByName("AirSAR") != nullptr)
     629         283 :         return;
     630             : 
     631        1750 :     GDALDriver *poDriver = new GDALDriver();
     632             : 
     633        1750 :     poDriver->SetDescription("AirSAR");
     634        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     635        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "AirSAR Polarimetric Image");
     636        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/airsar.html");
     637             : 
     638        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     639             : 
     640        1750 :     poDriver->pfnOpen = AirSARDataset::Open;
     641             : 
     642        1750 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     643             : }

Generated by: LCOV version 1.14