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

Generated by: LCOV version 1.14