LCOV - code coverage report
Current view: top level - frmts/jaxapalsar - jaxapalsardataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 18 253 7.1 %
Date: 2026-01-15 17:31:20 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 :     const vsi_l_offset nOffset =
     333             :         IMAGE_OPT_DESC_LENGTH +
     334           0 :         (static_cast<vsi_l_offset>(nBlockYOff - 1) * nRecordSize) +
     335           0 :         (nFileType == level_11 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET);
     336             : 
     337           0 :     VSIFSeekL(fp, nOffset, SEEK_SET);
     338           0 :     VSIFReadL(pImage, nNumBytes, nRasterXSize, fp);
     339             : 
     340             : #ifdef CPL_LSB
     341           0 :     if (nFileType == level_11)
     342           0 :         GDALSwapWords(pImage, 4, nBlockXSize * 2, 4);
     343             :     else
     344           0 :         GDALSwapWords(pImage, 2, nBlockXSize, 2);
     345             : #endif
     346             : 
     347           0 :     return CE_None;
     348             : }
     349             : 
     350             : /************************************************************************/
     351             : /* ==================================================================== */
     352             : /*                      PALSARJaxaDataset                               */
     353             : /* ==================================================================== */
     354             : /************************************************************************/
     355             : 
     356             : /************************************************************************/
     357             : /*                          ReadMetadata()                              */
     358             : /************************************************************************/
     359             : 
     360           0 : int PALSARJaxaDataset::GetGCPCount()
     361             : {
     362           0 :     return nGCPCount;
     363             : }
     364             : 
     365             : /************************************************************************/
     366             : /*                             GetGCPs()                                */
     367             : /************************************************************************/
     368             : 
     369           0 : const GDAL_GCP *PALSARJaxaDataset::GetGCPs()
     370             : {
     371           0 :     return pasGCPList;
     372             : }
     373             : 
     374             : /************************************************************************/
     375             : /*                            ReadMetadata()                            */
     376             : /************************************************************************/
     377             : 
     378           0 : void PALSARJaxaDataset::ReadMetadata(PALSARJaxaDataset *poDS, VSILFILE *fp)
     379             : {
     380             :     /* seek to the end of the leader file descriptor */
     381           0 :     VSIFSeekL(fp, LEADER_FILE_DESCRIPTOR_LENGTH, SEEK_SET);
     382           0 :     if (poDS->nFileType == level_10)
     383             :     {
     384           0 :         poDS->SetMetadataItem("PRODUCT_LEVEL", "1.0");
     385           0 :         poDS->SetMetadataItem("AZIMUTH_LOOKS", "1.0");
     386             :     }
     387           0 :     else if (poDS->nFileType == level_11)
     388             :     {
     389           0 :         poDS->SetMetadataItem("PRODUCT_LEVEL", "1.1");
     390           0 :         poDS->SetMetadataItem("AZIMUTH_LOOKS", "1.0");
     391             :     }
     392             :     else
     393             :     {
     394           0 :         poDS->SetMetadataItem("PRODUCT_LEVEL", "1.5");
     395             :         /* extract equivalent number of looks */
     396           0 :         VSIFSeekL(
     397           0 :             fp, LEADER_FILE_DESCRIPTOR_LENGTH + EFFECTIVE_LOOKS_AZIMUTH_OFFSET,
     398             :             SEEK_SET);
     399             :         char szENL[17];
     400             :         double dfENL;
     401           0 :         READ_CHAR_FLOAT(dfENL, 16, fp);
     402           0 :         snprintf(szENL, sizeof(szENL), "%-16.1f", dfENL);
     403           0 :         poDS->SetMetadataItem("AZIMUTH_LOOKS", szENL);
     404             : 
     405             :         /* extract pixel spacings */
     406           0 :         VSIFSeekL(fp,
     407           0 :                   LEADER_FILE_DESCRIPTOR_LENGTH + DATA_SET_SUMMARY_LENGTH +
     408             :                       PIXEL_SPACING_OFFSET,
     409             :                   SEEK_SET);
     410             :         double dfPixelSpacing;
     411             :         double dfLineSpacing;
     412             :         char szPixelSpacing[33];
     413             :         char szLineSpacing[33];
     414           0 :         READ_CHAR_FLOAT(dfPixelSpacing, 16, fp);
     415           0 :         READ_CHAR_FLOAT(dfLineSpacing, 16, fp);
     416           0 :         snprintf(szPixelSpacing, sizeof(szPixelSpacing), "%-32.1f",
     417             :                  dfPixelSpacing);
     418           0 :         snprintf(szLineSpacing, sizeof(szLineSpacing), "%-32.1f",
     419             :                  dfLineSpacing);
     420           0 :         poDS->SetMetadataItem("PIXEL_SPACING", szPixelSpacing);
     421           0 :         poDS->SetMetadataItem("LINE_SPACING", szPixelSpacing);
     422             : 
     423             :         /* Alphanumeric projection name */
     424           0 :         VSIFSeekL(fp,
     425           0 :                   LEADER_FILE_DESCRIPTOR_LENGTH + DATA_SET_SUMMARY_LENGTH +
     426             :                       ALPHANUMERIC_PROJECTION_NAME_OFFSET,
     427             :                   SEEK_SET);
     428             :         char szProjName[33];
     429           0 :         READ_STRING(szProjName, 32, fp);
     430           0 :         poDS->SetMetadataItem("PROJECTION_NAME", szProjName);
     431             : 
     432             :         /* Extract corner GCPs */
     433           0 :         poDS->nGCPCount = 4;
     434           0 :         poDS->pasGCPList =
     435           0 :             (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP), poDS->nGCPCount);
     436           0 :         GDALInitGCPs(poDS->nGCPCount, poDS->pasGCPList);
     437             : 
     438             :         /* setup the GCPs */
     439             :         int i;
     440           0 :         for (i = 0; i < poDS->nGCPCount; i++)
     441             :         {
     442             :             char szID[30];
     443           0 :             snprintf(szID, sizeof(szID), "%d", i + 1);
     444           0 :             CPLFree(poDS->pasGCPList[i].pszId);
     445           0 :             poDS->pasGCPList[i].pszId = CPLStrdup(szID);
     446           0 :             poDS->pasGCPList[i].dfGCPZ = 0.0;
     447             :         }
     448             : 
     449           0 :         double dfTemp = 0.0;
     450             :         /* seek to start of GCPs */
     451           0 :         VSIFSeekL(fp,
     452           0 :                   LEADER_FILE_DESCRIPTOR_LENGTH + DATA_SET_SUMMARY_LENGTH +
     453             :                       TOP_LEFT_LAT_OFFSET,
     454             :                   SEEK_SET);
     455             : 
     456             :         /* top-left GCP */
     457           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     458           0 :         poDS->pasGCPList[0].dfGCPY = dfTemp;
     459           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     460           0 :         poDS->pasGCPList[0].dfGCPX = dfTemp;
     461           0 :         poDS->pasGCPList[0].dfGCPLine = 0.5;
     462           0 :         poDS->pasGCPList[0].dfGCPPixel = 0.5;
     463             : 
     464             :         /* top right GCP */
     465           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     466           0 :         poDS->pasGCPList[1].dfGCPY = dfTemp;
     467           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     468           0 :         poDS->pasGCPList[1].dfGCPX = dfTemp;
     469           0 :         poDS->pasGCPList[1].dfGCPLine = 0.5;
     470           0 :         poDS->pasGCPList[1].dfGCPPixel = poDS->nRasterYSize - 0.5;
     471             : 
     472             :         /* bottom right GCP */
     473           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     474           0 :         poDS->pasGCPList[2].dfGCPY = dfTemp;
     475           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     476           0 :         poDS->pasGCPList[2].dfGCPX = dfTemp;
     477           0 :         poDS->pasGCPList[2].dfGCPLine = poDS->nRasterYSize - 0.5;
     478           0 :         poDS->pasGCPList[2].dfGCPPixel = poDS->nRasterYSize - 0.5;
     479             : 
     480             :         /* bottom left GCP */
     481           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     482           0 :         poDS->pasGCPList[3].dfGCPY = dfTemp;
     483           0 :         READ_CHAR_FLOAT(dfTemp, 16, fp);
     484           0 :         poDS->pasGCPList[3].dfGCPX = dfTemp;
     485           0 :         poDS->pasGCPList[3].dfGCPLine = poDS->nRasterYSize - 0.5;
     486           0 :         poDS->pasGCPList[3].dfGCPPixel = 0.5;
     487             :     }
     488             : 
     489             :     /* some generic metadata items */
     490           0 :     poDS->SetMetadataItem("SENSOR_BAND", "L"); /* PALSAR is L-band */
     491           0 :     poDS->SetMetadataItem("RANGE_LOOKS", "1.0");
     492             : 
     493             :     /* Check if this is a PolSAR dataset */
     494           0 :     if (poDS->GetRasterCount() == 4)
     495             :     {
     496             :         /* PALSAR data is only available from JAXA in Scattering Matrix form */
     497           0 :         poDS->SetMetadataItem("MATRIX_REPRESENTATION", "SCATTERING");
     498             :     }
     499           0 : }
     500             : 
     501             : /************************************************************************/
     502             : /*                              Identify()                              */
     503             : /************************************************************************/
     504             : 
     505           0 : static void ReadWord(VSILFILE *fp, int *pVal)
     506             : {
     507           0 :     READ_WORD(fp, *pVal);
     508           0 : }
     509             : 
     510           0 : static void ReadByte(VSILFILE *fp, int *pVal)
     511             : {
     512           0 :     READ_BYTE(fp, *pVal);
     513           0 : }
     514             : 
     515       66699 : int PALSARJaxaDataset::Identify(GDALOpenInfo *poOpenInfo)
     516             : {
     517       66699 :     if (poOpenInfo->nHeaderBytes < 360 || poOpenInfo->fpL == nullptr)
     518       59372 :         return 0;
     519             : 
     520             :     /* First, check that this is a PALSAR image indeed */
     521        7327 :     if (!STARTS_WITH_CI((char *)(poOpenInfo->pabyHeader + 60), "AL"))
     522             :     {
     523        7327 :         return 0;
     524             :     }
     525           0 :     const std::string osBasename = CPLGetBasenameSafe(poOpenInfo->pszFilename);
     526           0 :     if (osBasename.size() < 9 ||
     527           0 :         !STARTS_WITH_CI(osBasename.c_str() + 4, "ALPSR"))
     528             :     {
     529           0 :         return 0;
     530             :     }
     531             : 
     532             :     /* Check that this is a volume directory file */
     533           0 :     int nRecordSeq = 0;
     534           0 :     int nRecordSubtype = 0;
     535           0 :     int nRecordType = 0;
     536           0 :     int nSecondSubtype = 0;
     537           0 :     int nThirdSubtype = 0;
     538           0 :     int nLengthRecord = 0;
     539             : 
     540           0 :     VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
     541             : 
     542           0 :     ReadWord(poOpenInfo->fpL, &nRecordSeq);
     543           0 :     ReadByte(poOpenInfo->fpL, &nRecordSubtype);
     544           0 :     ReadByte(poOpenInfo->fpL, &nRecordType);
     545           0 :     ReadByte(poOpenInfo->fpL, &nSecondSubtype);
     546           0 :     ReadByte(poOpenInfo->fpL, &nThirdSubtype);
     547           0 :     ReadWord(poOpenInfo->fpL, &nLengthRecord);
     548             : 
     549           0 :     VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
     550             : 
     551             :     /* Check that we have the right record */
     552           0 :     if (nRecordSeq == 1 && nRecordSubtype == 192 && nRecordType == 192 &&
     553           0 :         nSecondSubtype == 18 && nThirdSubtype == 18 && nLengthRecord == 360)
     554             :     {
     555           0 :         return 1;
     556             :     }
     557             : 
     558           0 :     return 0;
     559             : }
     560             : 
     561             : /************************************************************************/
     562             : /*                                Open()                                */
     563             : /************************************************************************/
     564           0 : GDALDataset *PALSARJaxaDataset::Open(GDALOpenInfo *poOpenInfo)
     565             : {
     566             :     /* Check that this actually is a JAXA PALSAR product */
     567           0 :     if (!PALSARJaxaDataset::Identify(poOpenInfo))
     568           0 :         return nullptr;
     569             : 
     570             :     /* -------------------------------------------------------------------- */
     571             :     /*      Confirm the requested access is supported.                      */
     572             :     /* -------------------------------------------------------------------- */
     573           0 :     if (poOpenInfo->eAccess == GA_Update)
     574             :     {
     575           0 :         ReportUpdateNotSupportedByDriver("JAXAPALSAR");
     576           0 :         return nullptr;
     577             :     }
     578             : 
     579           0 :     PALSARJaxaDataset *poDS = new PALSARJaxaDataset();
     580             : 
     581             :     /* Get the suffix of the filename, we'll need this */
     582             :     char *pszSuffix =
     583           0 :         VSIStrdup((char *)(CPLGetFilename(poOpenInfo->pszFilename) + 3));
     584             : 
     585             :     /* Try to read each of the polarizations */
     586             :     const size_t nImgFileLen =
     587           0 :         CPLGetDirnameSafe(poOpenInfo->pszFilename).size() + strlen(pszSuffix) +
     588           0 :         8;
     589           0 :     char *pszImgFile = (char *)CPLMalloc(nImgFileLen);
     590             : 
     591           0 :     int nBandNum = 1;
     592             : 
     593             :     /* HH */
     594           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-HH%s",
     595           0 :              CPLGetDirnameSafe(poOpenInfo->pszFilename).c_str(), SEP_STRING,
     596             :              pszSuffix);
     597           0 :     VSILFILE *fpHH = VSIFOpenL(pszImgFile, "rb");
     598           0 :     if (fpHH != nullptr)
     599             :     {
     600           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 0, fpHH));
     601           0 :         nBandNum++;
     602             :     }
     603             : 
     604             :     /* HV */
     605           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-HV%s",
     606           0 :              CPLGetDirnameSafe(poOpenInfo->pszFilename).c_str(), SEP_STRING,
     607             :              pszSuffix);
     608           0 :     VSILFILE *fpHV = VSIFOpenL(pszImgFile, "rb");
     609           0 :     if (fpHV != nullptr)
     610             :     {
     611           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 1, fpHV));
     612           0 :         nBandNum++;
     613             :     }
     614             : 
     615             :     /* VH */
     616           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-VH%s",
     617           0 :              CPLGetDirnameSafe(poOpenInfo->pszFilename).c_str(), SEP_STRING,
     618             :              pszSuffix);
     619           0 :     VSILFILE *fpVH = VSIFOpenL(pszImgFile, "rb");
     620           0 :     if (fpVH != nullptr)
     621             :     {
     622           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 2, fpVH));
     623           0 :         nBandNum++;
     624             :     }
     625             : 
     626             :     /* VV */
     627           0 :     snprintf(pszImgFile, nImgFileLen, "%s%sIMG-VV%s",
     628           0 :              CPLGetDirnameSafe(poOpenInfo->pszFilename).c_str(), SEP_STRING,
     629             :              pszSuffix);
     630           0 :     VSILFILE *fpVV = VSIFOpenL(pszImgFile, "rb");
     631           0 :     if (fpVV != nullptr)
     632             :     {
     633           0 :         poDS->SetBand(nBandNum, new PALSARJaxaRasterBand(poDS, 3, fpVV));
     634             :         /* nBandNum++; */
     635             :     }
     636             : 
     637           0 :     VSIFree(pszImgFile);
     638             : 
     639             :     /* did we get at least one band? */
     640           0 :     if (fpVV == nullptr && fpVH == nullptr && fpHV == nullptr &&
     641             :         fpHH == nullptr)
     642             :     {
     643           0 :         CPLError(
     644             :             CE_Failure, CPLE_AppDefined,
     645             :             "Unable to find any image data. Aborting opening as PALSAR image.");
     646           0 :         delete poDS;
     647           0 :         VSIFree(pszSuffix);
     648           0 :         return nullptr;
     649             :     }
     650             : 
     651             :     /* Level 1.0 products are not supported */
     652           0 :     if (poDS->nFileType == level_10)
     653             :     {
     654           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     655             :                  "ALOS PALSAR Level 1.0 products are not supported. Aborting "
     656             :                  "opening as PALSAR image.");
     657           0 :         delete poDS;
     658           0 :         VSIFree(pszSuffix);
     659           0 :         return nullptr;
     660             :     }
     661             : 
     662             :     /* read metadata from Leader file. */
     663             :     const size_t nLeaderFilenameLen =
     664           0 :         strlen(CPLGetDirnameSafe(poOpenInfo->pszFilename).c_str()) +
     665           0 :         strlen(pszSuffix) + 5;
     666           0 :     char *pszLeaderFilename = (char *)CPLMalloc(nLeaderFilenameLen);
     667           0 :     snprintf(pszLeaderFilename, nLeaderFilenameLen, "%s%sLED%s",
     668           0 :              CPLGetDirnameSafe(poOpenInfo->pszFilename).c_str(), SEP_STRING,
     669             :              pszSuffix);
     670             : 
     671           0 :     VSILFILE *fpLeader = VSIFOpenL(pszLeaderFilename, "rb");
     672             :     /* check if the leader is actually present */
     673           0 :     if (fpLeader != nullptr)
     674             :     {
     675           0 :         ReadMetadata(poDS, fpLeader);
     676           0 :         VSIFCloseL(fpLeader);
     677             :     }
     678             : 
     679           0 :     VSIFree(pszLeaderFilename);
     680             : 
     681           0 :     VSIFree(pszSuffix);
     682             : 
     683             :     /* -------------------------------------------------------------------- */
     684             :     /*      Initialize any PAM information.                                 */
     685             :     /* -------------------------------------------------------------------- */
     686           0 :     poDS->SetDescription(poOpenInfo->pszFilename);
     687           0 :     poDS->TryLoadXML();
     688             : 
     689             :     /* -------------------------------------------------------------------- */
     690             :     /*      Check for overviews.                                            */
     691             :     /* -------------------------------------------------------------------- */
     692           0 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
     693             : 
     694           0 :     return poDS;
     695             : }
     696             : 
     697             : /************************************************************************/
     698             : /*                      GDALRegister_PALSARJaxa()                       */
     699             : /************************************************************************/
     700             : 
     701        2058 : void GDALRegister_PALSARJaxa()
     702             : 
     703             : {
     704        2058 :     if (GDALGetDriverByName("JAXAPALSAR") != nullptr)
     705         283 :         return;
     706             : 
     707        1775 :     GDALDriver *poDriver = new GDALDriver();
     708             : 
     709        1775 :     poDriver->SetDescription("JAXAPALSAR");
     710        1775 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     711        1775 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     712        1775 :                               "JAXA PALSAR Product Reader (Level 1.1/1.5)");
     713        1775 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/palsar.html");
     714             : 
     715        1775 :     poDriver->pfnOpen = PALSARJaxaDataset::Open;
     716        1775 :     poDriver->pfnIdentify = PALSARJaxaDataset::Identify;
     717        1775 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     718             : 
     719        1775 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     720             : }

Generated by: LCOV version 1.14