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

Generated by: LCOV version 1.14