Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: AirSAR Reader
4 : * Purpose: Implements read support for AirSAR Polarimetric data.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2007-2009, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_vsi.h"
33 : #include "gdal_frmts.h"
34 : #include "gdal_pam.h"
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* AirSARDataset */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : class AirSARRasterBand;
43 :
44 : class AirSARDataset final : public GDALPamDataset
45 : {
46 : friend class AirSARRasterBand;
47 :
48 : VSILFILE *fp;
49 :
50 : int nLoadedLine;
51 : GByte *pabyCompressedLine;
52 : double *padfMatrix;
53 :
54 : int nDataStart;
55 : int nRecordLength;
56 :
57 : CPLErr LoadLine(int iLine);
58 :
59 : static char **ReadHeader(VSILFILE *fp, int nFileOffset,
60 : const char *pszPrefix, int nMaxLines);
61 :
62 : public:
63 : AirSARDataset();
64 : ~AirSARDataset();
65 :
66 : static GDALDataset *Open(GDALOpenInfo *);
67 : };
68 :
69 : /************************************************************************/
70 : /* ==================================================================== */
71 : /* AirSARRasterBand */
72 : /* ==================================================================== */
73 : /************************************************************************/
74 :
75 : class AirSARRasterBand final : public GDALPamRasterBand
76 : {
77 : public:
78 : AirSARRasterBand(AirSARDataset *, int);
79 : ~AirSARRasterBand() override;
80 :
81 : CPLErr IReadBlock(int, int, void *) override;
82 : };
83 :
84 : /* locations of stokes matrix values within padfMatrix ... same order as they
85 : are computed in the document. */
86 :
87 : constexpr int M11 = 0;
88 : constexpr int M12 = 1;
89 : constexpr int M13 = 2;
90 : constexpr int M14 = 3;
91 : constexpr int M23 = 4;
92 : constexpr int M24 = 5;
93 : constexpr int M33 = 6;
94 : constexpr int M34 = 7;
95 : constexpr int M44 = 8;
96 : constexpr int M22 = 9;
97 :
98 : /************************************************************************/
99 : /* AirSARRasterBand() */
100 : /************************************************************************/
101 :
102 0 : AirSARRasterBand::AirSARRasterBand(AirSARDataset *poDSIn, int nBandIn)
103 :
104 : {
105 0 : poDS = poDSIn;
106 0 : nBand = nBandIn;
107 :
108 0 : nBlockXSize = poDS->GetRasterXSize();
109 0 : nBlockYSize = 1;
110 :
111 0 : if (this->nBand == 2 || this->nBand == 3 || this->nBand == 5)
112 0 : eDataType = GDT_CFloat32;
113 : else
114 0 : eDataType = GDT_Float32;
115 :
116 0 : switch (nBand)
117 : {
118 0 : case 1:
119 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_11");
120 0 : SetDescription("Covariance_11");
121 0 : eDataType = GDT_CFloat32;
122 0 : break;
123 :
124 0 : case 2:
125 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_12");
126 0 : SetDescription("Covariance_12");
127 0 : eDataType = GDT_CFloat32;
128 0 : break;
129 :
130 0 : case 3:
131 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_13");
132 0 : SetDescription("Covariance_13");
133 0 : eDataType = GDT_CFloat32;
134 0 : break;
135 :
136 0 : case 4:
137 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_22");
138 0 : SetDescription("Covariance_22");
139 0 : eDataType = GDT_CFloat32;
140 0 : break;
141 :
142 0 : case 5:
143 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_23");
144 0 : SetDescription("Covariance_23");
145 0 : eDataType = GDT_CFloat32;
146 0 : break;
147 :
148 0 : case 6:
149 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_33");
150 0 : SetDescription("Covariance_33");
151 0 : eDataType = GDT_CFloat32;
152 0 : break;
153 : }
154 0 : }
155 :
156 : /************************************************************************/
157 : /* ~AirSARRasterBand() */
158 : /************************************************************************/
159 :
160 0 : AirSARRasterBand::~AirSARRasterBand()
161 :
162 : {
163 0 : }
164 :
165 : /************************************************************************/
166 : /* IReadBlock() */
167 : /************************************************************************/
168 :
169 0 : CPLErr AirSARRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
170 : void *pImage)
171 : {
172 0 : float *pafLine = (float *)pImage;
173 0 : const double SQRT_2 = 1.4142135623730951;
174 :
175 0 : CPLErr eErr = ((AirSARDataset *)poDS)->LoadLine(nBlockYOff);
176 0 : if (eErr != CE_None)
177 0 : return eErr;
178 :
179 0 : double *padfMatrix = ((AirSARDataset *)poDS)->padfMatrix;
180 :
181 0 : if (nBand == 1) /* C11 */
182 : {
183 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
184 : {
185 0 : double *m = padfMatrix + 10 * iPixel;
186 :
187 0 : pafLine[iPixel * 2 + 0] = (float)(m[M11] + m[M22] + 2 * m[M12]);
188 0 : pafLine[iPixel * 2 + 1] = 0.0;
189 : }
190 : }
191 0 : else if (nBand == 2) /* C12 */
192 : {
193 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
194 : {
195 0 : double *m = padfMatrix + 10 * iPixel;
196 :
197 : // real
198 0 : pafLine[iPixel * 2 + 0] = (float)(SQRT_2 * (m[M13] + m[M23]));
199 :
200 : // imaginary
201 0 : pafLine[iPixel * 2 + 1] = (float)(-SQRT_2 * (m[M24] + m[M14]));
202 : }
203 : }
204 0 : else if (nBand == 3) /* C13 */
205 : {
206 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
207 : {
208 0 : double *m = padfMatrix + 10 * iPixel;
209 :
210 : // real
211 0 : pafLine[iPixel * 2 + 0] = (float)(2 * m[M33] + m[M22] - m[M11]);
212 :
213 : // imaginary
214 0 : pafLine[iPixel * 2 + 1] = (float)(-2 * m[M34]);
215 : }
216 : }
217 0 : else if (nBand == 4) /* C22 */
218 : {
219 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
220 : {
221 0 : double *m = padfMatrix + 10 * iPixel;
222 :
223 0 : pafLine[iPixel * 2 + 0] = (float)(2 * (m[M11] - m[M22]));
224 0 : pafLine[iPixel * 2 + 1] = 0.0;
225 : }
226 : }
227 0 : else if (nBand == 5) /* C23 */
228 : {
229 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
230 : {
231 0 : double *m = padfMatrix + 10 * iPixel;
232 :
233 : // real
234 0 : pafLine[iPixel * 2 + 0] = (float)(SQRT_2 * (m[M13] - m[M23]));
235 :
236 : // imaginary
237 0 : pafLine[iPixel * 2 + 1] = (float)(SQRT_2 * (m[M24] - m[M14]));
238 : }
239 : }
240 0 : else if (nBand == 6) /* C33 */
241 : {
242 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
243 : {
244 0 : double *m = padfMatrix + 10 * iPixel;
245 :
246 0 : pafLine[iPixel * 2 + 0] = (float)(m[M11] + m[M22] - 2 * m[M12]);
247 0 : pafLine[iPixel * 2 + 1] = 0.0;
248 : }
249 : }
250 :
251 0 : return CE_None;
252 : }
253 :
254 : /************************************************************************/
255 : /* ==================================================================== */
256 : /* AirSARDataset */
257 : /* ==================================================================== */
258 : /************************************************************************/
259 :
260 : /************************************************************************/
261 : /* AirSARDataset() */
262 : /************************************************************************/
263 :
264 0 : AirSARDataset::AirSARDataset()
265 : : fp(nullptr), nLoadedLine(-1), pabyCompressedLine(nullptr),
266 0 : padfMatrix(nullptr), nDataStart(0), nRecordLength(0)
267 : {
268 0 : }
269 :
270 : /************************************************************************/
271 : /* ~AirSARDataset() */
272 : /************************************************************************/
273 :
274 0 : AirSARDataset::~AirSARDataset()
275 :
276 : {
277 0 : FlushCache(true);
278 0 : CPLFree(pabyCompressedLine);
279 0 : CPLFree(padfMatrix);
280 :
281 0 : if (fp != nullptr)
282 : {
283 0 : VSIFCloseL(fp);
284 0 : fp = nullptr;
285 : }
286 0 : }
287 :
288 : /************************************************************************/
289 : /* LoadLine() */
290 : /************************************************************************/
291 :
292 0 : CPLErr AirSARDataset::LoadLine(int iLine)
293 :
294 : {
295 0 : if (iLine == nLoadedLine)
296 0 : return CE_None;
297 :
298 : /* -------------------------------------------------------------------- */
299 : /* allocate working buffers if we don't have them already. */
300 : /* -------------------------------------------------------------------- */
301 0 : if (pabyCompressedLine == nullptr)
302 : {
303 0 : pabyCompressedLine = (GByte *)VSI_MALLOC2_VERBOSE(nRasterXSize, 10);
304 :
305 0 : padfMatrix =
306 0 : (double *)VSI_MALLOC2_VERBOSE(10 * sizeof(double), nRasterXSize);
307 0 : if (pabyCompressedLine == nullptr || padfMatrix == nullptr)
308 : {
309 0 : CPLFree(pabyCompressedLine);
310 0 : CPLFree(padfMatrix);
311 0 : return CE_Failure;
312 : }
313 : }
314 :
315 0 : CPLAssert(nRecordLength == nRasterXSize * 10);
316 :
317 : /* -------------------------------------------------------------------- */
318 : /* Load raw compressed data. */
319 : /* -------------------------------------------------------------------- */
320 0 : if (VSIFSeekL(fp, nDataStart + iLine * nRecordLength, SEEK_SET) != 0 ||
321 0 : ((int)VSIFReadL(pabyCompressedLine, 10, nRasterXSize, fp)) !=
322 0 : nRasterXSize)
323 : {
324 0 : CPLError(CE_Failure, CPLE_FileIO,
325 : "Error reading %d bytes for line %d at offset %d.\n%s",
326 0 : nRasterXSize * 10, iLine, nDataStart + iLine * nRecordLength,
327 0 : VSIStrerror(errno));
328 0 : return CE_Failure;
329 : }
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* Build stokes matrix */
333 : /* -------------------------------------------------------------------- */
334 0 : for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
335 : {
336 0 : double *M = padfMatrix + 10 * iPixel;
337 0 : signed char *byte = (signed char *)pabyCompressedLine + 10 * iPixel - 1;
338 0 : const double gen_fac = 1.0; // should we have a general scale factor?
339 :
340 0 : M[M11] = (byte[2] / 254.0 + 1.5) * pow(2.0, byte[1]) * gen_fac;
341 0 : M[M12] = byte[3] * M[M11] / 127.0;
342 0 : M[M13] = byte[4] * fabs((double)byte[4]) * M[M11] / (127 * 127);
343 0 : M[M14] = byte[5] * fabs((double)byte[5]) * M[M11] / (127 * 127);
344 0 : M[M23] = byte[6] * fabs((double)byte[6]) * M[M11] / (127 * 127);
345 0 : M[M24] = byte[7] * fabs((double)byte[7]) * M[M11] / (127 * 127);
346 0 : M[M33] = byte[8] * M[M11] / 127;
347 0 : M[M34] = byte[9] * M[M11] / 127;
348 0 : M[M44] = byte[10] * M[M11] / 127;
349 0 : M[M22] = M[M11] - M[M33] - M[M44];
350 : }
351 :
352 0 : return CE_None;
353 : }
354 :
355 : /************************************************************************/
356 : /* ReadHeader() */
357 : /* */
358 : /* Read the AirSAR header. We assume an equal sign separates */
359 : /* the keyword name from the value. If not, assume the last */
360 : /* "blank delimited" word is the value and everything else is a */
361 : /* keyword. */
362 : /* */
363 : /* The records are 50 characters each. Read till we get an all */
364 : /* blank record or some zero bytes. */
365 : /************************************************************************/
366 :
367 0 : char **AirSARDataset::ReadHeader(VSILFILE *fp, int nFileOffset,
368 : const char *pszPrefix, int nMaxLines)
369 :
370 : {
371 0 : char **papszHeadInfo = nullptr;
372 : char szLine[51];
373 :
374 0 : VSIFSeekL(fp, nFileOffset, SEEK_SET);
375 :
376 : /* ==================================================================== */
377 : /* Loop collecting one line at a time. */
378 : /* ==================================================================== */
379 0 : for (int iLine = 0; iLine < nMaxLines; iLine++)
380 : {
381 : /* --------------------------------------------------------------------
382 : */
383 : /* Read a 50 byte header record. */
384 : /* --------------------------------------------------------------------
385 : */
386 0 : if (VSIFReadL(szLine, 1, 50, fp) != 50)
387 : {
388 0 : CPLError(CE_Failure, CPLE_FileIO,
389 : "Read error collecting AirSAR header.");
390 0 : CSLDestroy(papszHeadInfo);
391 0 : return nullptr;
392 : }
393 :
394 0 : szLine[50] = '\0';
395 :
396 : /* --------------------------------------------------------------------
397 : */
398 : /* Is it all spaces, or does it have a zero byte? */
399 : /* --------------------------------------------------------------------
400 : */
401 0 : bool bAllSpaces = true;
402 0 : bool bHasIllegalChars = false;
403 :
404 0 : for (int i = 0; i < 50; i++)
405 : {
406 0 : if (szLine[i] == '\0')
407 0 : break;
408 :
409 0 : if (szLine[i] != ' ')
410 0 : bAllSpaces = false;
411 :
412 0 : if (((unsigned char *)szLine)[i] > 127 ||
413 0 : ((unsigned char *)szLine)[i] < 10)
414 0 : bHasIllegalChars = true;
415 : }
416 :
417 0 : if (bAllSpaces || bHasIllegalChars)
418 : break;
419 :
420 : /* --------------------------------------------------------------------
421 : */
422 : /* Find the pivot between the keyword name and value. */
423 : /* --------------------------------------------------------------------
424 : */
425 0 : int iPivot = -1;
426 :
427 0 : for (int i = 0; i < 50; i++)
428 : {
429 0 : if (szLine[i] == '=')
430 : {
431 0 : iPivot = i;
432 0 : break;
433 : }
434 : }
435 :
436 : // If no "=" found, split on first double white space
437 0 : if (iPivot == -1)
438 : {
439 0 : for (int i = 48; i >= 0; i--)
440 : {
441 0 : if (szLine[i] == ' ' && szLine[i + 1] == ' ')
442 : {
443 0 : iPivot = i;
444 0 : break;
445 : }
446 : }
447 : }
448 :
449 0 : if (iPivot == -1) // Yikes!
450 : {
451 0 : CPLDebug("AIRSAR", "No pivot in line `%s'.", szLine);
452 0 : CPLAssert(iPivot != -1);
453 0 : break;
454 : }
455 :
456 : /* --------------------------------------------------------------------
457 : */
458 : /* Trace ahead to the first non-white space value character. */
459 : /* --------------------------------------------------------------------
460 : */
461 0 : int iValue = iPivot + 1;
462 :
463 0 : while (iValue < 50 && szLine[iValue] == ' ')
464 0 : iValue++;
465 :
466 : /* --------------------------------------------------------------------
467 : */
468 : /* Strip any white space off the keyword. */
469 : /* --------------------------------------------------------------------
470 : */
471 0 : int iKeyEnd = iPivot - 1;
472 :
473 0 : while (iKeyEnd > 0 && szLine[iKeyEnd] == ' ')
474 0 : iKeyEnd--;
475 :
476 0 : szLine[iKeyEnd + 1] = '\0';
477 :
478 : /* --------------------------------------------------------------------
479 : */
480 : /* Convert spaces or colons into underscores in the key name. */
481 : /* --------------------------------------------------------------------
482 : */
483 0 : for (int i = 0; szLine[i] != '\0'; i++)
484 : {
485 0 : if (szLine[i] == ' ' || szLine[i] == ':' || szLine[i] == ',')
486 0 : szLine[i] = '_';
487 : }
488 :
489 : /* --------------------------------------------------------------------
490 : */
491 : /* Prefix key name with provided prefix string. */
492 : /* --------------------------------------------------------------------
493 : */
494 : char szPrefixedKeyName[55];
495 :
496 0 : snprintf(szPrefixedKeyName, sizeof(szPrefixedKeyName), "%s_%s",
497 : pszPrefix, szLine);
498 :
499 : papszHeadInfo =
500 0 : CSLSetNameValue(papszHeadInfo, szPrefixedKeyName, szLine + iValue);
501 : }
502 :
503 0 : return papszHeadInfo;
504 : }
505 :
506 : /************************************************************************/
507 : /* Open() */
508 : /************************************************************************/
509 :
510 32964 : GDALDataset *AirSARDataset::Open(GDALOpenInfo *poOpenInfo)
511 :
512 : {
513 32964 : if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 800)
514 28835 : return nullptr;
515 :
516 : /* -------------------------------------------------------------------- */
517 : /* Check for AirSAR/ keyword. */
518 : /* -------------------------------------------------------------------- */
519 4129 : if (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader,
520 : "RECORD LENGTH IN BYTES"))
521 4129 : return nullptr;
522 :
523 0 : if (strstr((char *)poOpenInfo->pabyHeader, "COMPRESSED") == nullptr ||
524 0 : strstr((char *)poOpenInfo->pabyHeader, "JPL AIRCRAFT") == nullptr)
525 0 : return nullptr;
526 :
527 : /* -------------------------------------------------------------------- */
528 : /* Parse the header fields. We turn all the transform the */
529 : /* keywords by converting spaces to underscores so they will be */
530 : /* "well behaved" as metadata keywords. */
531 : /* -------------------------------------------------------------------- */
532 0 : char **papszMD = ReadHeader(poOpenInfo->fpL, 0, "MH", 20);
533 :
534 0 : if (papszMD == nullptr)
535 0 : return nullptr;
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Confirm the requested access is supported. */
539 : /* -------------------------------------------------------------------- */
540 0 : if (poOpenInfo->eAccess == GA_Update)
541 : {
542 0 : CPLError(CE_Failure, CPLE_NotSupported,
543 : "The AIRSAR driver does not support update access to existing"
544 : " datasets.\n");
545 0 : CSLDestroy(papszMD);
546 0 : return nullptr;
547 : }
548 : /* -------------------------------------------------------------------- */
549 : /* Create a corresponding GDALDataset. */
550 : /* -------------------------------------------------------------------- */
551 0 : AirSARDataset *poDS = new AirSARDataset();
552 :
553 : /* -------------------------------------------------------------------- */
554 : /* Extract some key information. */
555 : /* -------------------------------------------------------------------- */
556 :
557 0 : poDS->nRasterXSize =
558 0 : atoi(CSLFetchNameValue(papszMD, "MH_NUMBER_OF_SAMPLES_PER_RECORD"));
559 0 : poDS->nRasterYSize =
560 0 : atoi(CSLFetchNameValue(papszMD, "MH_NUMBER_OF_LINES_IN_IMAGE"));
561 :
562 0 : poDS->nRecordLength =
563 0 : atoi(CSLFetchNameValue(papszMD, "MH_RECORD_LENGTH_IN_BYTES"));
564 :
565 0 : poDS->nDataStart =
566 0 : atoi(CSLFetchNameValue(papszMD, "MH_BYTE_OFFSET_OF_FIRST_DATA_RECORD"));
567 :
568 : /* -------------------------------------------------------------------- */
569 : /* Adopt the openinfo file pointer. */
570 : /* -------------------------------------------------------------------- */
571 0 : poDS->fp = poOpenInfo->fpL;
572 0 : poOpenInfo->fpL = nullptr;
573 :
574 : /* -------------------------------------------------------------------- */
575 : /* Read and merge parameter header into metadata. Prefix */
576 : /* parameter header values with PH_. */
577 : /* -------------------------------------------------------------------- */
578 0 : int nPHOffset = 0;
579 :
580 0 : if (CSLFetchNameValue(papszMD, "MH_BYTE_OFFSET_OF_PARAMETER_HEADER") !=
581 : nullptr)
582 : {
583 0 : nPHOffset = atoi(
584 : CSLFetchNameValue(papszMD, "MH_BYTE_OFFSET_OF_PARAMETER_HEADER"));
585 0 : char **papszPHInfo = ReadHeader(poDS->fp, nPHOffset, "PH", 100);
586 :
587 0 : papszMD = CSLInsertStrings(papszMD, CSLCount(papszMD), papszPHInfo);
588 :
589 0 : CSLDestroy(papszPHInfo);
590 : }
591 :
592 : /* -------------------------------------------------------------------- */
593 : /* Read and merge calibration header into metadata. Prefix */
594 : /* parameter header values with CH_. */
595 : /* -------------------------------------------------------------------- */
596 0 : if (nPHOffset != 0)
597 : {
598 : char **papszCHInfo =
599 0 : ReadHeader(poDS->fp, nPHOffset + poDS->nRecordLength, "CH", 18);
600 :
601 0 : papszMD = CSLInsertStrings(papszMD, CSLCount(papszMD), papszCHInfo);
602 :
603 0 : CSLDestroy(papszCHInfo);
604 : }
605 :
606 : /* -------------------------------------------------------------------- */
607 : /* Assign metadata to dataset. */
608 : /* -------------------------------------------------------------------- */
609 0 : poDS->SetMetadata(papszMD);
610 0 : CSLDestroy(papszMD);
611 :
612 : /* -------------------------------------------------------------------- */
613 : /* Create band information objects. */
614 : /* -------------------------------------------------------------------- */
615 0 : poDS->SetBand(1, new AirSARRasterBand(poDS, 1));
616 0 : poDS->SetBand(2, new AirSARRasterBand(poDS, 2));
617 0 : poDS->SetBand(3, new AirSARRasterBand(poDS, 3));
618 0 : poDS->SetBand(4, new AirSARRasterBand(poDS, 4));
619 0 : poDS->SetBand(5, new AirSARRasterBand(poDS, 5));
620 0 : poDS->SetBand(6, new AirSARRasterBand(poDS, 6));
621 :
622 0 : poDS->SetMetadataItem("MATRIX_REPRESENTATION", "SYMMETRIZED_COVARIANCE");
623 :
624 : /* -------------------------------------------------------------------- */
625 : /* Initialize any PAM information. */
626 : /* -------------------------------------------------------------------- */
627 0 : poDS->SetDescription(poOpenInfo->pszFilename);
628 0 : poDS->TryLoadXML();
629 :
630 0 : poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
631 :
632 0 : return poDS;
633 : }
634 :
635 : /************************************************************************/
636 : /* GDALRegister_AirSAR() */
637 : /************************************************************************/
638 :
639 1520 : void GDALRegister_AirSAR()
640 :
641 : {
642 1520 : if (GDALGetDriverByName("AirSAR") != nullptr)
643 301 : return;
644 :
645 1219 : GDALDriver *poDriver = new GDALDriver();
646 :
647 1219 : poDriver->SetDescription("AirSAR");
648 1219 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
649 1219 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "AirSAR Polarimetric Image");
650 1219 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/airsar.html");
651 :
652 1219 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
653 :
654 1219 : poDriver->pfnOpen = AirSARDataset::Open;
655 :
656 1219 : GetGDALDriverManager()->RegisterDriver(poDriver);
657 : }
|