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 : }
|