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

Generated by: LCOV version 1.14