LCOV - code coverage report
Current view: top level - frmts/jaxapalsar - jaxapalsardataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 18 244 7.4 %
Date: 2024-11-21 22:18:42 Functions: 2 15 13.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PALSAR JAXA imagery reader
       4             :  * Purpose:  Support for PALSAR L1.1/1.5 imagery and appropriate metadata from
       5             :  *           JAXA and JAXA-supported ground stations (ASF, ESA, etc.). This
       6             :  *           driver does not support ERSDAC products.
       7             :  * Author:   Philippe Vachon <philippe@cowpig.ca>
       8             :  *
       9             :  ******************************************************************************
      10             :  * Copyright (c) 2007, Philippe P. Vachon <philippe@cowpig.ca>
      11             :  * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  ****************************************************************************/
      15             : 
      16             : #include "gdal_frmts.h"
      17             : #include "gdal_pam.h"
      18             : 
      19             : #if defined(_WIN32)
      20             : #define SEP_STRING "\\"
      21             : #else
      22             : #define SEP_STRING "/"
      23             : #endif
      24             : 
      25             : /* read binary fields */
      26             : #ifdef CPL_LSB
      27             : #define READ_WORD(f, x)                                                        \
      28             :     do                                                                         \
      29             :     {                                                                          \
      30             :         VSIFReadL(&(x), 4, 1, (f));                                            \
      31             :         (x) = CPL_SWAP32((x));                                                 \
      32             :     } while (false);
      33             : #define READ_SHORT(f, x)                                                       \
      34             :     do                                                                         \
      35             :     {                                                                          \
      36             :         VSIFReadL(&(x), 2, 1, (f));                                            \
      37             :         (x) = CPL_SWAP16((x));                                                 \
      38             :     } while (false);
      39             : #else
      40             : #define READ_WORD(f, x)                                                        \
      41             :     do                                                                         \
      42             :     {                                                                          \
      43             :         VSIFReadL(&(x), 4, 1, (f));                                            \
      44             :     } while (false);
      45             : #define READ_SHORT(f, x)                                                       \
      46             :     do                                                                         \
      47             :     {                                                                          \
      48             :         VSIFReadL(&(x), 2, 1, (f));                                            \
      49             :     } while (false);
      50             : #endif /* def CPL_LSB */
      51             : #define READ_BYTE(f, x)                                                        \
      52             :     do                                                                         \
      53             :     {                                                                          \
      54             :         VSIFReadL(&(x), 1, 1, (f));                                            \
      55             :     } while (false);
      56             : 
      57             : /* read floating point value stored as ASCII */
      58             : #define READ_CHAR_FLOAT(n, l, f)                                               \
      59             :     do                                                                         \
      60             :     {                                                                          \
      61             :         char psBuf[(l + 1)];                                                   \
      62             :         psBuf[(l)] = '\0';                                                     \
      63             :         VSIFReadL(&psBuf, (l), 1, (f));                                        \
      64             :         (n) = CPLAtof(psBuf);                                                  \
      65             :     } while (false);
      66             : 
      67             : /* read numbers stored as ASCII */
      68             : #define READ_CHAR_VAL(x, n, f)                                                 \
      69             :     do                                                                         \
      70             :     {                                                                          \
      71             :         char psBuf[(n + 1)];                                                   \
      72             :         psBuf[(n)] = '\0';                                                     \
      73             :         VSIFReadL(&psBuf, (n), 1, (f));                                        \
      74             :         (x) = atoi(psBuf);                                                     \
      75             :     } while (false);
      76             : 
      77             : /* read string fields
      78             :  * note: string must be size of field to be extracted + 1
      79             :  */
      80             : #define READ_STRING(s, n, f)                                                   \
      81             :     do                                                                         \
      82             :     {                                                                          \
      83             :         VSIFReadL(&(s), 1, (n), (f));                                          \
      84             :         (s)[(n)] = '\0';                                                       \
      85             :     } while (false);
      86             : 
      87             : /*************************************************************************/
      88             : /* a few key offsets in the volume directory file */
      89             : #define VOL_DESC_RECORD_LENGTH 360
      90             : #define FILE_PTR_RECORD_LENGTH 360
      91             : #define NUM_RECORDS_OFFSET 160
      92             : 
      93             : /* a few key offsets and values within the File Pointer record */
      94             : #define REF_FILE_CLASS_CODE_OFFSET 66
      95             : #define REF_FILE_CLASS_CODE_LENGTH 4
      96             : #define FILE_NAME_OFFSET 310
      97             : 
      98             : /* some image option descriptor records */
      99             : #define BITS_PER_SAMPLE_OFFSET 216
     100             : #define BITS_PER_SAMPLE_LENGTH 4
     101             : #define SAMPLES_PER_GROUP_OFFSET 220
     102             : #define SAMPLES_PER_GROUP_LENGTH 4
     103             : #define NUMBER_LINES_OFFSET 236
     104             : #define NUMBER_LINES_LENGTH 8
     105             : #define SAR_DATA_RECORD_LENGTH_OFFSET 186
     106             : #define SAR_DATA_RECORD_LENGTH_LENGTH 6
     107             : 
     108             : #define IMAGE_OPT_DESC_LENGTH 720
     109             : 
     110             : #define SIG_DAT_REC_OFFSET 412
     111             : #define PROC_DAT_REC_OFFSET 192
     112             : 
     113             : /* metadata to be extracted from the leader file */
     114             : #define LEADER_FILE_DESCRIPTOR_LENGTH 720
     115             : #define DATA_SET_SUMMARY_LENGTH 4096
     116             : 
     117             : /* relative to end of leader file descriptor */
     118             : #define EFFECTIVE_LOOKS_AZIMUTH_OFFSET 1174 /* floating point text */
     119             : #define EFFECTIVE_LOOKS_AZIMUTH_LENGTH 16
     120             : 
     121             : /* relative to leader file descriptor + dataset summary length */
     122             : #define PIXEL_SPACING_OFFSET 92
     123             : #define LINE_SPACING_OFFSET 108
     124             : #define ALPHANUMERIC_PROJECTION_NAME_OFFSET 412
     125             : #define TOP_LEFT_LAT_OFFSET 1072
     126             : #define TOP_LEFT_LON_OFFSET 1088
     127             : #define TOP_RIGHT_LAT_OFFSET 1104
     128             : #define TOP_RIGHT_LON_OFFSET 1120
     129             : #define BOTTOM_RIGHT_LAT_OFFSET 1136
     130             : #define BOTTOM_RIGHT_LON_OFFSET 1152
     131             : #define BOTTOM_LEFT_LAT_OFFSET 1168
     132             : #define BOTTOM_LEFT_LON_OFFSET 1184
     133             : 
     134             : namespace gdal::PSALSARJaxa
     135             : {
     136             : /* a few useful enums */
     137             : enum eFileType
     138             : {
     139             :     level_11 = 0,
     140             :     level_15,
     141             :     level_10,
     142             :     level_unknown = 999,
     143             : };
     144             : 
     145             : enum ePolarization
     146             : {
     147             :     hh = 0,
     148             :     hv,
     149             :     vh,
     150             :     vv
     151             : };
     152             : }  // namespace gdal::PSALSARJaxa
     153             : 
     154             : using namespace gdal::PSALSARJaxa;
     155             : 
     156             : /************************************************************************/
     157             : /* ==================================================================== */
     158             : /*                        PALSARJaxaDataset                             */
     159             : /* ==================================================================== */
     160             : /************************************************************************/
     161             : 
     162             : class PALSARJaxaRasterBand;
     163             : 
     164             : class PALSARJaxaDataset final : public GDALPamDataset
     165             : {
     166             :     friend class PALSARJaxaRasterBand;
     167             : 
     168             :   private:
     169             :     GDAL_GCP *pasGCPList;
     170             :     int nGCPCount;
     171             :     eFileType nFileType;
     172             : 
     173             :   public:
     174             :     PALSARJaxaDataset();
     175             :     ~PALSARJaxaDataset();
     176             : 
     177             :     int GetGCPCount() override;
     178             :     const GDAL_GCP *GetGCPs() override;
     179             : 
     180             :     static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
     181             :     static int Identify(GDALOpenInfo *poOpenInfo);
     182             :     static void ReadMetadata(PALSARJaxaDataset *poDS, VSILFILE *fp);
     183             : };
     184             : 
     185           0 : PALSARJaxaDataset::PALSARJaxaDataset()
     186           0 :     : pasGCPList(nullptr), nGCPCount(0), nFileType(level_unknown)
     187             : {
     188           0 : }
     189             : 
     190           0 : PALSARJaxaDataset::~PALSARJaxaDataset()
     191             : {
     192           0 :     if (nGCPCount > 0)
     193             :     {
     194           0 :         GDALDeinitGCPs(nGCPCount, pasGCPList);
     195           0 :         CPLFree(pasGCPList);
     196             :     }
     197           0 : }
     198             : 
     199             : /************************************************************************/
     200             : /* ==================================================================== */
     201             : /*                        PALSARJaxaRasterBand                          */
     202             : /* ==================================================================== */
     203             : /************************************************************************/
     204             : 
     205             : class PALSARJaxaRasterBand final : public GDALRasterBand
     206             : {
     207             :     VSILFILE *fp;
     208             :     ePolarization nPolarization;
     209             :     eFileType nFileType;
     210             :     int nBitsPerSample;
     211             :     int nSamplesPerGroup;
     212             :     int nRecordSize;
     213             : 
     214             :   public:
     215             :     PALSARJaxaRasterBand(PALSARJaxaDataset *poDS, int nBand, VSILFILE *fp);
     216             :     ~PALSARJaxaRasterBand();
     217             : 
     218             :     CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage) override;
     219             : };
     220             : 
     221             : /************************************************************************/
     222             : /*                         PALSARJaxaRasterBand()                       */
     223             : /************************************************************************/
     224             : 
     225           0 : PALSARJaxaRasterBand::PALSARJaxaRasterBand(PALSARJaxaDataset *poDSIn,
     226           0 :                                            int nBandIn, VSILFILE *fpIn)
     227             :     : fp(fpIn), nPolarization(hh), nBitsPerSample(0), nSamplesPerGroup(0),
     228           0 :       nRecordSize(0)
     229             : {
     230           0 :     poDS = poDSIn;
     231           0 :     nBand = nBandIn;
     232             : 
     233             :     /* Read image options record to determine the type of data */
     234           0 :     VSIFSeekL(fp, BITS_PER_SAMPLE_OFFSET, SEEK_SET);
     235           0 :     READ_CHAR_VAL(nBitsPerSample, BITS_PER_SAMPLE_LENGTH, fp);
     236           0 :     READ_CHAR_VAL(nSamplesPerGroup, SAMPLES_PER_GROUP_LENGTH, fp);
     237             : 
     238           0 :     if (nBitsPerSample == 32 && nSamplesPerGroup == 2)
     239             :     {
     240           0 :         eDataType = GDT_CFloat32;
     241           0 :         nFileType = level_11;
     242             :     }
     243           0 :     else if (nBitsPerSample == 8 && nSamplesPerGroup == 2)
     244             :     {
     245           0 :         eDataType = GDT_CInt16; /* shuold be 2 x signed byte */
     246           0 :         nFileType = level_10;
     247             :     }
     248             :     else
     249             :     {
     250           0 :         eDataType = GDT_UInt16;
     251           0 :         nFileType = level_15;
     252             :     }
     253             : 
     254           0 :     poDSIn->nFileType = nFileType;
     255             : 
     256             :     /* Read number of range/azimuth lines */
     257           0 :     VSIFSeekL(fp, NUMBER_LINES_OFFSET, SEEK_SET);
     258           0 :     READ_CHAR_VAL(nRasterYSize, NUMBER_LINES_LENGTH, fp);
     259           0 :     VSIFSeekL(fp, SAR_DATA_RECORD_LENGTH_OFFSET, SEEK_SET);
     260           0 :     READ_CHAR_VAL(nRecordSize, SAR_DATA_RECORD_LENGTH_LENGTH, fp);
     261           0 :     const int nDenom = ((nBitsPerSample / 8) * nSamplesPerGroup);
     262           0 :     if (nDenom != 0)
     263           0 :         nRasterXSize =
     264           0 :             (nRecordSize - (nFileType != level_15 ? SIG_DAT_REC_OFFSET
     265           0 :                                                   : PROC_DAT_REC_OFFSET)) /
     266             :             nDenom;
     267             : 
     268           0 :     poDSIn->nRasterXSize = nRasterXSize;
     269           0 :     poDSIn->nRasterYSize = nRasterYSize;
     270             : 
     271             :     /* Polarization */
     272           0 :     switch (nBand)
     273             :     {
     274           0 :         case 0:
     275           0 :             nPolarization = hh;
     276           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "HH");
     277           0 :             break;
     278           0 :         case 1:
     279           0 :             nPolarization = hv;
     280           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "HV");
     281           0 :             break;
     282           0 :         case 2:
     283           0 :             nPolarization = vh;
     284           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "VH");
     285           0 :             break;
     286           0 :         case 3:
     287           0 :             nPolarization = vv;
     288           0 :             SetMetadataItem("POLARIMETRIC_INTERP", "VV");
     289           0 :             break;
     290             :             // TODO: What about the default?
     291             :     }
     292             : 
     293             :     /* size of block we can read */
     294           0 :     nBlockXSize = nRasterXSize;
     295           0 :     nBlockYSize = 1;
     296             : 
     297             :     /* set the file pointer to the first SAR data record */
     298           0 :     VSIFSeekL(fp, IMAGE_OPT_DESC_LENGTH, SEEK_SET);
     299           0 : }
     300             : 
     301             : /************************************************************************/
     302             : /*                        ~PALSARJaxaRasterBand()                       */
     303             : /************************************************************************/
     304             : 
     305           0 : PALSARJaxaRasterBand::~PALSARJaxaRasterBand()
     306             : {
     307           0 :     if (fp)
     308           0 :         VSIFCloseL(fp);
     309           0 : }
     310             : 
     311             : /************************************************************************/
     312             : /*                             IReadBlock()                             */
     313             : /************************************************************************/
     314             : 
     315           0 : CPLErr PALSARJaxaRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     316             :                                         int nBlockYOff, void *pImage)
     317             : {
     318           0 :     int nNumBytes = 0;
     319           0 :     if (nFileType == level_11)
     320             :     {
     321           0 :         nNumBytes = 8;
     322             :     }
     323             :     else
     324             :     {
     325           0 :         nNumBytes = 2;
     326             :     }
     327             : 
     328           0 :     int nOffset =
     329           0 :         IMAGE_OPT_DESC_LENGTH + ((nBlockYOff - 1) * nRecordSize) +
     330           0 :         (nFileType == level_11 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET);
     331             : 
     332           0 :     VSIFSeekL(fp, nOffset, SEEK_SET);
     333           0 :     VSIFReadL(pImage, nNumBytes, nRasterXSize, fp);
     334             : 
     335             : #ifdef CPL_LSB
     336           0 :     if (nFileType == level_11)
     337           0 :         GDALSwapWords(pImage, 4, nBlockXSize * 2, 4);
     338             :     else
     339           0 :         GDALSwapWords(pImage, 2, nBlockXSize, 2);
     340             : #endif
     341             : 
     342           0 :     return CE_None;
     343             : }
     344             : 
     345             : /************************************************************************/
     346             : /* ==================================================================== */
     347             : /*                      PALSARJaxaDataset                               */
     348             : /* ==================================================================== */
     349             : /************************************************************************/
     350             : 
     351             : /************************************************************************/
     352             : /*                          ReadMetadata()                              */
     353             : /************************************************************************/
     354             : 
     355           0 : int PALSARJaxaDataset::GetGCPCount()
     356             : {
     357           0 :     return nGCPCount;
     358             : }
     359             : 
     360             : /************************************************************************/
     361             : /*                             GetGCPs()                                */
     362             : /************************************************************************/
     363             : 
     364           0 : const GDAL_GCP *PALSARJaxaDataset::GetGCPs()
     365             : {
     366           0 :     return pasGCPList;
     367             : }
     368             : 
     369             : /************************************************************************/
     370             : /*                            ReadMetadata()                            */
     371             : /************************************************************************/
     372             : 
     373           0 : void PALSARJaxaDataset::ReadMetadata(PALSARJaxaDataset *poDS, VSILFILE *fp)
     374             : {
     375             :     /* seek to the end of the leader file descriptor */
     376           0 :     VSIFSeekL(fp, LEADER_FILE_DESCRIPTOR_LENGTH, SEEK_SET);
     377           0 :     if (poDS->nFileType == level_10)
     378             :     {
     379           0 :         poDS->SetMetadataItem("PRODUCT_LEVEL", "1.0");
     380           0 :         poDS->SetMetadataItem("AZIMUTH_LOOKS", "1.0");
     381             :     }
     382           0 :     else if (poDS->nFileType == level_11)
     383             :     {
     384           0 :         poDS->SetMetadataItem("PRODUCT_LEVEL", "1.1");
     385           0 :         poDS->SetMetadataItem("AZIMUTH_LOOKS", "1.0");
     386             :     }
     387             :     else
     388             :     {
     389           0 :         poDS->SetMetadataItem("PRODUCT_LEVEL", "1.5");
     390             :         /* extract equivalent number of looks */
     391           0 :         VSIFSeekL(
     392             :             fp, LEADER_FILE_DESCRIPTOR_LENGTH + EFFECTIVE_LOOKS_AZIMUTH_OFFSET,
     393             :             SEEK_SET);
     394             :         char szENL[17];
     395             :         double dfENL;
     396           0 :         READ_CHAR_FLOAT(dfENL, 16, fp);
     397           0 :         snprintf(szENL, sizeof(szENL), "%-16.1f", dfENL);
     398           0 :         poDS->SetMetadataItem("AZIMUTH_LOOKS", szENL);
     399             : 
     400             :         /* extract pixel spacings */
     401           0 :         VSIFSeekL(fp,
     402             :                   LEADER_FILE_DESCRIPTOR_LENGTH + DATA_SET_SUMMARY_LENGTH +
     403             :                       PIXEL_SPACING_OFFSET,
     404             :                   SEEK_SET);
     405             :         double dfPixelSpacing;
     406             :         double dfLineSpacing;
     407             :         char szPixelSpacing[33];
     408             :         char szLineSpacing[33];
     409           0 :         READ_CHAR_FLOAT(dfPixelSpacing, 16, fp);
     410           0 :         READ_CHAR_FLOAT(dfLineSpacing, 16, fp);
     411           0 :         snprintf(szPixelSpacing, sizeof(szPixelSpacing), "%-32.1f",
     412             :                  dfPixelSpacing);
     413           0 :         snprintf(szLineSpacing, sizeof(szLineSpacing), "%-32.1f",
     414             :                  dfLineSpacing);
     415           0 :         poDS->SetMetadataItem("PIXEL_SPACING", szPixelSpacing);
     416           0 :         poDS->SetMetadataItem("LINE_SPACING", szPixelSpacing);
     417             : 
     418             :         /* Alphanumeric projection name */
     419           0 :         VSIFSeekL(fp,
     420             :                   LEADER_FILE_DESCRIPTOR_LENGTH + DATA_SET_SUMMARY_LENGTH +
     421             :                       ALPHANUMERIC_PROJECTION_NAME_OFFSET,
     422             :                   SEEK_SET);
     423             :         char szProjName[33];
     424           0 :         READ_STRING(szProjName, 32, fp);
     425           0 :         poDS->SetMetadataItem("PROJECTION_NAME", szProjName);
     426             : 
     427             :         /* Extract corner GCPs */
     428           0 :         poDS->nGCPCount = 4;
     429           0 :         poDS->pasGCPList =
     430           0 :             (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP), poDS->nGCPCount);
     431           0 :         GDALInitGCPs(poDS->nGCPCount, poDS->pasGCPList);
     432             : 
     433             :         /* setup the GCPs */
     434             :         int i;
     435           0 :         for (i = 0; i < poDS->nGCPCount; i++)
     436             :         {
     437             :             char szID[30];
     438           0 :             snprintf(szID, sizeof(szID), "%d", i + 1);
     439           0 :             CPLFree(poDS->pasGCPList[i].pszId);
     440           0 :             poDS->pasGCPList[i].pszId = CPLStrdup(szID);
     441           0 :             poDS->pasGCPList[i].dfGCPZ = 0.0;
     442             :         }
     443             : 
     444           0 :         double dfTemp = 0.0;
     445             :         /* seek to start of GCPs */
     446           0 :         VSIFSeekL(fp,
     447             :                   LEADER_FILE_DESCRIPTOR_LENGTH + DATA_SET_SUMMARY_LENGTH +
     448             :                       TOP_LEFT_LAT_OFFSET,
     449             :                   SEEK_SET);
     450             : 
     451             :         /* top-left GCP */
     452           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     453           0 :         poDS->pasGCPList[0].dfGCPY = dfTemp;
     454           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     455           0 :         poDS->pasGCPList[0].dfGCPX = dfTemp;
     456           0 :         poDS->pasGCPList[0].dfGCPLine = 0.5;
     457           0 :         poDS->pasGCPList[0].dfGCPPixel = 0.5;
     458             : 
     459             :         /* top right GCP */
     460           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     461           0 :         poDS->pasGCPList[1].dfGCPY = dfTemp;
     462           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     463           0 :         poDS->pasGCPList[1].dfGCPX = dfTemp;
     464           0 :         poDS->pasGCPList[1].dfGCPLine = 0.5;
     465           0 :         poDS->pasGCPList[1].dfGCPPixel = poDS->nRasterYSize - 0.5;
     466             : 
     467             :         /* bottom right GCP */
     468           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     469           0 :         poDS->pasGCPList[2].dfGCPY = dfTemp;
     470           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     471           0 :         poDS->pasGCPList[2].dfGCPX = dfTemp;
     472           0 :         poDS->pasGCPList[2].dfGCPLine = poDS->nRasterYSize - 0.5;
     473           0 :         poDS->pasGCPList[2].dfGCPPixel = poDS->nRasterYSize - 0.5;
     474             : 
     475             :         /* bottom left GCP */
     476           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     477           0 :         poDS->pasGCPList[3].dfGCPY = dfTemp;
     478           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     479           0 :         poDS->pasGCPList[3].dfGCPX = dfTemp;
     480           0 :         poDS->pasGCPList[3].dfGCPLine = poDS->nRasterYSize - 0.5;
     481           0 :         poDS->pasGCPList[3].dfGCPPixel = 0.5;
     482             :     }
     483             : 
     484             :     /* some generic metadata items */
     485           0 :     poDS->SetMetadataItem("SENSOR_BAND", "L"); /* PALSAR is L-band */
     486           0 :     poDS->SetMetadataItem("RANGE_LOOKS", "1.0");
     487             : 
     488             :     /* Check if this is a PolSAR dataset */
     489           0 :     if (poDS->GetRasterCount() == 4)
     490             :     {
     491             :         /* PALSAR data is only available from JAXA in Scattering Matrix form */
     492           0 :         poDS->SetMetadataItem("MATRIX_REPRESENTATION", "SCATTERING");
     493             :     }
     494           0 : }
     495             : 
     496             : /************************************************************************/
     497             : /*                              Identify()                              */
     498             : /************************************************************************/
     499             : 
     500           0 : static void ReadWord(VSILFILE *fp, int *pVal)
     501             : {
     502           0 :     READ_WORD(fp, *pVal);
     503           0 : }
     504             : 
     505           0 : static void ReadByte(VSILFILE *fp, int *pVal)
     506             : {
     507           0 :     READ_BYTE(fp, *pVal);
     508           0 : }
     509             : 
     510       57030 : int PALSARJaxaDataset::Identify(GDALOpenInfo *poOpenInfo)
     511             : {
     512       57030 :     if (poOpenInfo->nHeaderBytes < 360 || poOpenInfo->fpL == nullptr)
     513       50848 :         return 0;
     514             : 
     515             :     /* First, check that this is a PALSAR image indeed */
     516        6182 :     if (!STARTS_WITH_CI((char *)(poOpenInfo->pabyHeader + 60), "AL") ||
     517           0 :         !STARTS_WITH_CI(CPLGetBasename((char *)(poOpenInfo->pszFilename)) + 4,
     518             :                         "ALPSR"))
     519             :     {
     520        6182 :         return 0;
     521             :     }
     522             : 
     523             :     /* Check that this is a volume directory file */
     524           0 :     int nRecordSeq = 0;
     525           0 :     int nRecordSubtype = 0;
     526           0 :     int nRecordType = 0;
     527           0 :     int nSecondSubtype = 0;
     528           0 :     int nThirdSubtype = 0;
     529           0 :     int nLengthRecord = 0;
     530             : 
     531           0 :     VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
     532             : 
     533           0 :     ReadWord(poOpenInfo->fpL, &nRecordSeq);
     534           0 :     ReadByte(poOpenInfo->fpL, &nRecordSubtype);
     535           0 :     ReadByte(poOpenInfo->fpL, &nRecordType);
     536           0 :     ReadByte(poOpenInfo->fpL, &nSecondSubtype);
     537           0 :     ReadByte(poOpenInfo->fpL, &nThirdSubtype);
     538           0 :     ReadWord(poOpenInfo->fpL, &nLengthRecord);
     539             : 
     540           0 :     VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
     541             : 
     542             :     /* Check that we have the right record */
     543           0 :     if (nRecordSeq == 1 && nRecordSubtype == 192 && nRecordType == 192 &&
     544           0 :         nSecondSubtype == 18 && nThirdSubtype == 18 && nLengthRecord == 360)
     545             :     {
     546           0 :         return 1;
     547             :     }
     548             : 
     549           0 :     return 0;
     550             : }
     551             : 
     552             : /************************************************************************/
     553             : /*                                Open()                                */
     554             : /************************************************************************/
     555           0 : GDALDataset *PALSARJaxaDataset::Open(GDALOpenInfo *poOpenInfo)
     556             : {
     557             :     /* Check that this actually is a JAXA PALSAR product */
     558           0 :     if (!PALSARJaxaDataset::Identify(poOpenInfo))
     559           0 :         return nullptr;
     560             : 
     561             :     /* -------------------------------------------------------------------- */
     562             :     /*      Confirm the requested access is supported.                      */
     563             :     /* -------------------------------------------------------------------- */
     564           0 :     if (poOpenInfo->eAccess == GA_Update)
     565             :     {
     566           0 :         CPLError(
     567             :             CE_Failure, CPLE_NotSupported,
     568             :             "The JAXAPALSAR driver does not support update access to existing"
     569             :             " datasets.\n");
     570           0 :         return nullptr;
     571             :     }
     572             : 
     573           0 :     PALSARJaxaDataset *poDS = new PALSARJaxaDataset();
     574             : 
     575             :     /* Get the suffix of the filename, we'll need this */
     576             :     char *pszSuffix =
     577           0 :         VSIStrdup((char *)(CPLGetFilename(poOpenInfo->pszFilename) + 3));
     578             : 
     579             :     /* Try to read each of the polarizations */
     580             :     const size_t nImgFileLen =
     581           0 :         strlen(CPLGetDirname(poOpenInfo->pszFilename)) + strlen(pszSuffix) + 8;
     582           0 :     char *pszImgFile = (char *)CPLMalloc(nImgFileLen);
     583             : 
     584           0 :     int nBandNum = 1;
     585             : 
     586             :     /* HH */
     587           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-HH%s",
     588           0 :              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix);
     589           0 :     VSILFILE *fpHH = VSIFOpenL(pszImgFile, "rb");
     590           0 :     if (fpHH != nullptr)
     591             :     {
     592           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 0, fpHH));
     593           0 :         nBandNum++;
     594             :     }
     595             : 
     596             :     /* HV */
     597           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-HV%s",
     598           0 :              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix);
     599           0 :     VSILFILE *fpHV = VSIFOpenL(pszImgFile, "rb");
     600           0 :     if (fpHV != nullptr)
     601             :     {
     602           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 1, fpHV));
     603           0 :         nBandNum++;
     604             :     }
     605             : 
     606             :     /* VH */
     607           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-VH%s",
     608           0 :              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix);
     609           0 :     VSILFILE *fpVH = VSIFOpenL(pszImgFile, "rb");
     610           0 :     if (fpVH != nullptr)
     611             :     {
     612           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 2, fpVH));
     613           0 :         nBandNum++;
     614             :     }
     615             : 
     616             :     /* VV */
     617           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-VV%s",
     618           0 :              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix);
     619           0 :     VSILFILE *fpVV = VSIFOpenL(pszImgFile, "rb");
     620           0 :     if (fpVV != nullptr)
     621             :     {
     622           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 3, fpVV));
     623             :         /* nBandNum++; */
     624             :     }
     625             : 
     626           0 :     VSIFree(pszImgFile);
     627             : 
     628             :     /* did we get at least one band? */
     629           0 :     if (fpVV == nullptr && fpVH == nullptr && fpHV == nullptr &&
     630             :         fpHH == nullptr)
     631             :     {
     632           0 :         CPLError(
     633             :             CE_Failure, CPLE_AppDefined,
     634             :             "Unable to find any image data. Aborting opening as PALSAR image.");
     635           0 :         delete poDS;
     636           0 :         VSIFree(pszSuffix);
     637           0 :         return nullptr;
     638             :     }
     639             : 
     640             :     /* Level 1.0 products are not supported */
     641           0 :     if (poDS->nFileType == level_10)
     642             :     {
     643           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     644             :                  "ALOS PALSAR Level 1.0 products are not supported. Aborting "
     645             :                  "opening as PALSAR image.");
     646           0 :         delete poDS;
     647           0 :         VSIFree(pszSuffix);
     648           0 :         return nullptr;
     649             :     }
     650             : 
     651             :     /* read metadata from Leader file. */
     652             :     const size_t nLeaderFilenameLen =
     653           0 :         strlen(CPLGetDirname(poOpenInfo->pszFilename)) + strlen(pszSuffix) + 5;
     654           0 :     char *pszLeaderFilename = (char *)CPLMalloc(nLeaderFilenameLen);
     655           0 :     snprintf(pszLeaderFilename, nLeaderFilenameLen, "%s%sLED%s",
     656           0 :              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix);
     657             : 
     658           0 :     VSILFILE *fpLeader = VSIFOpenL(pszLeaderFilename, "rb");
     659             :     /* check if the leader is actually present */
     660           0 :     if (fpLeader != nullptr)
     661             :     {
     662           0 :         ReadMetadata(poDS, fpLeader);
     663           0 :         VSIFCloseL(fpLeader);
     664             :     }
     665             : 
     666           0 :     VSIFree(pszLeaderFilename);
     667             : 
     668           0 :     VSIFree(pszSuffix);
     669             : 
     670             :     /* -------------------------------------------------------------------- */
     671             :     /*      Initialize any PAM information.                                 */
     672             :     /* -------------------------------------------------------------------- */
     673           0 :     poDS->SetDescription(poOpenInfo->pszFilename);
     674           0 :     poDS->TryLoadXML();
     675             : 
     676             :     /* -------------------------------------------------------------------- */
     677             :     /*      Check for overviews.                                            */
     678             :     /* -------------------------------------------------------------------- */
     679           0 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
     680             : 
     681           0 :     return poDS;
     682             : }
     683             : 
     684             : /************************************************************************/
     685             : /*                      GDALRegister_PALSARJaxa()                       */
     686             : /************************************************************************/
     687             : 
     688        1595 : void GDALRegister_PALSARJaxa()
     689             : 
     690             : {
     691        1595 :     if (GDALGetDriverByName("JAXAPALSAR") != nullptr)
     692         302 :         return;
     693             : 
     694        1293 :     GDALDriver *poDriver = new GDALDriver();
     695             : 
     696        1293 :     poDriver->SetDescription("JAXAPALSAR");
     697        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     698        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     699        1293 :                               "JAXA PALSAR Product Reader (Level 1.1/1.5)");
     700        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/palsar.html");
     701             : 
     702        1293 :     poDriver->pfnOpen = PALSARJaxaDataset::Open;
     703        1293 :     poDriver->pfnIdentify = PALSARJaxaDataset::Identify;
     704        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     705             : 
     706        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     707             : }

Generated by: LCOV version 1.14