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