Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: ASI CEOS Translator
4 : * Purpose: GDALDataset driver for CEOS translator.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2000, Atlantis Scientific Inc.
9 : * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "ceos.h"
15 : #include "cpl_string.h"
16 : #include "gdal_frmts.h"
17 : #include "gdal_priv.h"
18 : #include "rawdataset.h"
19 : #include "ogr_srs_api.h"
20 :
21 : #include <algorithm>
22 :
23 0 : static GInt16 CastToGInt16(float val)
24 : {
25 0 : if (val < -32768.0)
26 0 : val = -32768.0;
27 :
28 0 : if (val > 32767)
29 0 : val = 32767.0;
30 :
31 0 : return static_cast<GInt16>(val);
32 : }
33 :
34 : static const char *const CeosExtension[][6] = {
35 : {"vol", "led", "img", "trl", "nul", "ext"},
36 : {"vol", "lea", "img", "trl", "nul", "ext"},
37 : {"vol", "led", "img", "tra", "nul", "ext"},
38 : {"vol", "lea", "img", "tra", "nul", "ext"},
39 : {"vdf", "slf", "sdf", "stf", "nvd", "ext"},
40 :
41 : {"vdf", "ldr", "img", "tra", "nul", "ext2"},
42 :
43 : /* Jers from Japan- not sure if this is generalized as much as it could be
44 : */
45 : {"VOLD", "Sarl_01", "Imop_%02d", "Sart_01", "NULL", "base"},
46 :
47 : /* Radarsat: basename, not extension */
48 : {"vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_vdf", "base"},
49 :
50 : /* Ers-1: basename, not extension */
51 : {"vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_dat", "base"},
52 :
53 : /* Ers-2 from Telaviv */
54 : {"volume", "leader", "image", "trailer", "nul_dat", "whole"},
55 :
56 : /* Ers-1 from D-PAF */
57 : {"VDF", "LF", "SLC", "", "", "ext"},
58 :
59 : /* Radarsat-1 per #2051 */
60 : {"vol", "sarl", "sard", "sart", "nvol", "ext"},
61 :
62 : /* Radarsat-1 ASF */
63 : {"", "L", "D", "", "", "ext"},
64 :
65 : /* end marker */
66 : {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
67 :
68 : static int ProcessData(VSILFILE *fp, int fileid, CeosSARVolume_t *sar,
69 : int max_records, vsi_l_offset max_bytes);
70 :
71 64 : static CeosTypeCode_t QuadToTC(int a, int b, int c, int d)
72 : {
73 : CeosTypeCode_t abcd;
74 :
75 64 : abcd.UCharCode.Subtype1 = (unsigned char)a;
76 64 : abcd.UCharCode.Type = (unsigned char)b;
77 64 : abcd.UCharCode.Subtype2 = (unsigned char)c;
78 64 : abcd.UCharCode.Subtype3 = (unsigned char)d;
79 :
80 64 : return abcd;
81 : }
82 :
83 : #define LEADER_DATASET_SUMMARY_TC QuadToTC(18, 10, 18, 20)
84 : #define LEADER_DATASET_SUMMARY_ERS2_TC QuadToTC(10, 10, 31, 20)
85 : #define LEADER_RADIOMETRIC_COMPENSATION_TC QuadToTC(18, 51, 18, 20)
86 : #define VOLUME_DESCRIPTOR_RECORD_TC QuadToTC(192, 192, 18, 18)
87 : #define IMAGE_HEADER_RECORD_TC QuadToTC(63, 192, 18, 18)
88 : #define LEADER_RADIOMETRIC_DATA_RECORD_TC QuadToTC(18, 50, 18, 20)
89 : #define LEADER_MAP_PROJ_RECORD_TC QuadToTC(10, 20, 31, 20)
90 :
91 : // TODO: recond?
92 : /* JERS from Japan has MAP_PROJ recond with different identifiers */
93 : /* see CEOS-SAR-CCT Iss/Rev: 2/0 February 10, 1989 */
94 : #define LEADER_MAP_PROJ_RECORD_JERS_TC QuadToTC(18, 20, 18, 20)
95 :
96 : /* Leader from ASF has different identifiers */
97 : #define LEADER_MAP_PROJ_RECORD_ASF_TC QuadToTC(10, 20, 18, 20)
98 : #define LEADER_DATASET_SUMMARY_ASF_TC QuadToTC(10, 10, 18, 20)
99 : #define LEADER_FACILITY_ASF_TC QuadToTC(90, 210, 18, 61)
100 :
101 : /* For ERS calibration and incidence angle information */
102 : #define ERS_GENERAL_FACILITY_DATA_TC QuadToTC(10, 200, 31, 50)
103 : #define ERS_GENERAL_FACILITY_DATA_ALT_TC QuadToTC(10, 216, 31, 50)
104 :
105 : #define RSAT_PROC_PARAM_TC QuadToTC(18, 120, 18, 20)
106 :
107 : /************************************************************************/
108 : /* ==================================================================== */
109 : /* SAR_CEOSDataset */
110 : /* ==================================================================== */
111 : /************************************************************************/
112 :
113 : class SAR_CEOSRasterBand;
114 : class CCPRasterBand;
115 : class PALSARRasterBand;
116 :
117 : class SAR_CEOSDataset final : public GDALPamDataset
118 : {
119 : friend class SAR_CEOSRasterBand;
120 : friend class CCPRasterBand;
121 : friend class PALSARRasterBand;
122 :
123 : CeosSARVolume_t sVolume;
124 :
125 : VSILFILE *fpImage;
126 :
127 : char **papszTempMD;
128 :
129 : OGRSpatialReference m_oSRS{};
130 : int nGCPCount;
131 : GDAL_GCP *pasGCPList;
132 :
133 : void ScanForGCPs();
134 : void ScanForMetadata();
135 : int ScanForMapProjection();
136 : char **papszExtraFiles;
137 :
138 : public:
139 : SAR_CEOSDataset();
140 : ~SAR_CEOSDataset() override;
141 :
142 : int GetGCPCount() override;
143 : const OGRSpatialReference *GetGCPSpatialRef() const override;
144 : const GDAL_GCP *GetGCPs() override;
145 :
146 : char **GetMetadataDomainList() override;
147 : char **GetMetadata(const char *pszDomain) override;
148 :
149 : static GDALDataset *Open(GDALOpenInfo *);
150 : virtual char **GetFileList(void) override;
151 : };
152 :
153 : /************************************************************************/
154 : /* ==================================================================== */
155 : /* CCPRasterBand */
156 : /* ==================================================================== */
157 : /************************************************************************/
158 :
159 : class CCPRasterBand final : public GDALPamRasterBand
160 : {
161 : friend class SAR_CEOSDataset;
162 :
163 : public:
164 : CCPRasterBand(SAR_CEOSDataset *, int, GDALDataType);
165 :
166 : CPLErr IReadBlock(int, int, void *) override;
167 : };
168 :
169 : /************************************************************************/
170 : /* ==================================================================== */
171 : /* PALSARRasterBand */
172 : /* ==================================================================== */
173 : /************************************************************************/
174 :
175 : class PALSARRasterBand final : public GDALPamRasterBand
176 : {
177 : friend class SAR_CEOSDataset;
178 :
179 : public:
180 : PALSARRasterBand(SAR_CEOSDataset *, int);
181 :
182 : CPLErr IReadBlock(int, int, void *) override;
183 : };
184 :
185 : /************************************************************************/
186 : /* ==================================================================== */
187 : /* SAR_CEOSRasterBand */
188 : /* ==================================================================== */
189 : /************************************************************************/
190 :
191 : class SAR_CEOSRasterBand final : public GDALPamRasterBand
192 : {
193 : friend class SAR_CEOSDataset;
194 :
195 : public:
196 : SAR_CEOSRasterBand(SAR_CEOSDataset *, int, GDALDataType);
197 :
198 : CPLErr IReadBlock(int, int, void *) override;
199 : };
200 :
201 : /************************************************************************/
202 : /* SAR_CEOSRasterBand() */
203 : /************************************************************************/
204 :
205 0 : SAR_CEOSRasterBand::SAR_CEOSRasterBand(SAR_CEOSDataset *poGDSIn, int nBandIn,
206 0 : GDALDataType eType)
207 :
208 : {
209 0 : poDS = poGDSIn;
210 0 : nBand = nBandIn;
211 :
212 0 : eDataType = eType;
213 :
214 0 : nBlockXSize = poGDSIn->nRasterXSize;
215 0 : nBlockYSize = 1;
216 0 : }
217 :
218 : /************************************************************************/
219 : /* IReadBlock() */
220 : /************************************************************************/
221 :
222 0 : CPLErr SAR_CEOSRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
223 : void *pImage)
224 : {
225 0 : SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *)poDS;
226 :
227 0 : struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
228 :
229 : int offset;
230 0 : CalcCeosSARImageFilePosition(&(poGDS->sVolume), nBand, nBlockYOff + 1,
231 : nullptr, &offset);
232 :
233 0 : offset += ImageDesc->ImageDataStart;
234 :
235 : /* -------------------------------------------------------------------- */
236 : /* Load all the pixel data associated with this scanline. */
237 : /* Ensure we handle multiple record scanlines properly. */
238 : /* -------------------------------------------------------------------- */
239 0 : int nPixelsRead = 0;
240 :
241 : GByte *pabyRecord =
242 0 : (GByte *)VSI_MALLOC2_VERBOSE(ImageDesc->BytesPerPixel, nBlockXSize);
243 0 : if (!pabyRecord)
244 0 : return CE_Failure;
245 :
246 0 : for (int iRecord = 0; iRecord < ImageDesc->RecordsPerLine; iRecord++)
247 : {
248 : int nPixelsToRead;
249 :
250 0 : if (nPixelsRead + ImageDesc->PixelsPerRecord > nBlockXSize)
251 0 : nPixelsToRead = nBlockXSize - nPixelsRead;
252 : else
253 0 : nPixelsToRead = ImageDesc->PixelsPerRecord;
254 :
255 0 : CPL_IGNORE_RET_VAL(VSIFSeekL(poGDS->fpImage, offset, SEEK_SET));
256 0 : CPL_IGNORE_RET_VAL(VSIFReadL(
257 0 : pabyRecord +
258 0 : static_cast<size_t>(nPixelsRead) * ImageDesc->BytesPerPixel,
259 0 : 1, static_cast<size_t>(nPixelsToRead) * ImageDesc->BytesPerPixel,
260 : poGDS->fpImage));
261 :
262 0 : nPixelsRead += nPixelsToRead;
263 0 : offset += ImageDesc->BytesPerRecord;
264 : }
265 :
266 : /* -------------------------------------------------------------------- */
267 : /* Copy the desired band out based on the size of the type, and */
268 : /* the interleaving mode. */
269 : /* -------------------------------------------------------------------- */
270 0 : const int nBytesPerSample = GDALGetDataTypeSizeBytes(eDataType);
271 :
272 0 : if (ImageDesc->ChannelInterleaving == CEOS_IL_PIXEL)
273 : {
274 0 : GDALCopyWords(pabyRecord + (nBand - 1) * nBytesPerSample, eDataType,
275 : ImageDesc->BytesPerPixel, pImage, eDataType,
276 : nBytesPerSample, nBlockXSize);
277 : }
278 0 : else if (ImageDesc->ChannelInterleaving == CEOS_IL_LINE)
279 : {
280 0 : GDALCopyWords(pabyRecord + (nBand - 1) * nBytesPerSample * nBlockXSize,
281 : eDataType, nBytesPerSample, pImage, eDataType,
282 : nBytesPerSample, nBlockXSize);
283 : }
284 0 : else if (ImageDesc->ChannelInterleaving == CEOS_IL_BAND)
285 : {
286 0 : memcpy(pImage, pabyRecord,
287 0 : static_cast<size_t>(nBytesPerSample) * nBlockXSize);
288 : }
289 :
290 : #ifdef CPL_LSB
291 0 : GDALSwapWords(pImage, nBytesPerSample, nBlockXSize, nBytesPerSample);
292 : #endif
293 :
294 0 : CPLFree(pabyRecord);
295 :
296 0 : return CE_None;
297 : }
298 :
299 : /************************************************************************/
300 : /* ==================================================================== */
301 : /* CCPRasterBand */
302 : /* ==================================================================== */
303 : /************************************************************************/
304 :
305 : /************************************************************************/
306 : /* CCPRasterBand() */
307 : /************************************************************************/
308 :
309 0 : CCPRasterBand::CCPRasterBand(SAR_CEOSDataset *poGDSIn, int nBandIn,
310 0 : GDALDataType eType)
311 :
312 : {
313 0 : poDS = poGDSIn;
314 0 : nBand = nBandIn;
315 :
316 0 : eDataType = eType;
317 :
318 0 : nBlockXSize = poGDSIn->nRasterXSize;
319 0 : nBlockYSize = 1;
320 :
321 0 : if (nBand == 1)
322 0 : SetMetadataItem("POLARIMETRIC_INTERP", "HH");
323 0 : else if (nBand == 2)
324 0 : SetMetadataItem("POLARIMETRIC_INTERP", "HV");
325 0 : else if (nBand == 3)
326 0 : SetMetadataItem("POLARIMETRIC_INTERP", "VH");
327 0 : else if (nBand == 4)
328 0 : SetMetadataItem("POLARIMETRIC_INTERP", "VV");
329 0 : }
330 :
331 : /************************************************************************/
332 : /* IReadBlock() */
333 : /************************************************************************/
334 :
335 : /* From: http://southport.jpl.nasa.gov/software/dcomp/dcomp.html
336 :
337 : ysca = sqrt{ [ (Byte(2) / 254 ) + 1.5] 2Byte(1) }
338 :
339 : Re(SHH) = byte(3) ysca/127
340 :
341 : Im(SHH) = byte(4) ysca/127
342 :
343 : Re(SHV) = byte(5) ysca/127
344 :
345 : Im(SHV) = byte(6) ysca/127
346 :
347 : Re(SVH) = byte(7) ysca/127
348 :
349 : Im(SVH) = byte(8) ysca/127
350 :
351 : Re(SVV) = byte(9) ysca/127
352 :
353 : Im(SVV) = byte(10) ysca/127
354 :
355 : */
356 :
357 0 : CPLErr CCPRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
358 : void *pImage)
359 : {
360 0 : SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *)poDS;
361 :
362 0 : struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
363 :
364 0 : int offset = ImageDesc->FileDescriptorLength +
365 0 : ImageDesc->BytesPerRecord * nBlockYOff +
366 0 : ImageDesc->ImageDataStart;
367 :
368 : /* -------------------------------------------------------------------- */
369 : /* Load all the pixel data associated with this scanline. */
370 : /* -------------------------------------------------------------------- */
371 0 : const int nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
372 :
373 0 : GByte *pabyRecord = (GByte *)CPLMalloc(nBytesToRead);
374 :
375 0 : if (VSIFSeekL(poGDS->fpImage, offset, SEEK_SET) != 0 ||
376 0 : (int)VSIFReadL(pabyRecord, 1, nBytesToRead, poGDS->fpImage) !=
377 : nBytesToRead)
378 : {
379 0 : CPLError(CE_Failure, CPLE_FileIO,
380 : "Error reading %d bytes of CEOS record data at offset %d.\n"
381 : "Reading file %s failed.",
382 0 : nBytesToRead, offset, poGDS->GetDescription());
383 0 : CPLFree(pabyRecord);
384 0 : return CE_Failure;
385 : }
386 :
387 : /* -------------------------------------------------------------------- */
388 : /* Initialize our power table if this is our first time through. */
389 : /* -------------------------------------------------------------------- */
390 : static float afPowTable[256];
391 : static bool bPowTableInitialized = false;
392 :
393 0 : if (!bPowTableInitialized)
394 : {
395 0 : bPowTableInitialized = true;
396 :
397 0 : for (int i = 0; i < 256; i++)
398 : {
399 0 : afPowTable[i] = (float)pow(2.0, i - 128);
400 : }
401 : }
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* Copy the desired band out based on the size of the type, and */
405 : /* the interleaving mode. */
406 : /* -------------------------------------------------------------------- */
407 0 : for (int iX = 0; iX < nBlockXSize; iX++)
408 : {
409 0 : unsigned char *pabyGroup = pabyRecord + iX * ImageDesc->BytesPerPixel;
410 0 : signed char *Byte =
411 : (signed char *)pabyGroup - 1; /* A ones based alias */
412 : double dfReSHH, dfImSHH, dfReSHV, dfImSHV, dfReSVH, dfImSVH, dfReSVV,
413 : dfImSVV;
414 :
415 : const double dfScale =
416 0 : sqrt((Byte[2] / 254.0 + 1.5) * afPowTable[Byte[1] + 128]);
417 :
418 0 : if (nBand == 1)
419 : {
420 0 : dfReSHH = Byte[3] * dfScale / 127.0;
421 0 : dfImSHH = Byte[4] * dfScale / 127.0;
422 :
423 0 : ((float *)pImage)[iX * 2] = (float)dfReSHH;
424 0 : ((float *)pImage)[iX * 2 + 1] = (float)dfImSHH;
425 : }
426 0 : else if (nBand == 2)
427 : {
428 0 : dfReSHV = Byte[5] * dfScale / 127.0;
429 0 : dfImSHV = Byte[6] * dfScale / 127.0;
430 :
431 0 : ((float *)pImage)[iX * 2] = (float)dfReSHV;
432 0 : ((float *)pImage)[iX * 2 + 1] = (float)dfImSHV;
433 : }
434 0 : else if (nBand == 3)
435 : {
436 0 : dfReSVH = Byte[7] * dfScale / 127.0;
437 0 : dfImSVH = Byte[8] * dfScale / 127.0;
438 :
439 0 : ((float *)pImage)[iX * 2] = (float)dfReSVH;
440 0 : ((float *)pImage)[iX * 2 + 1] = (float)dfImSVH;
441 : }
442 0 : else if (nBand == 4)
443 : {
444 0 : dfReSVV = Byte[9] * dfScale / 127.0;
445 0 : dfImSVV = Byte[10] * dfScale / 127.0;
446 :
447 0 : ((float *)pImage)[iX * 2] = (float)dfReSVV;
448 0 : ((float *)pImage)[iX * 2 + 1] = (float)dfImSVV;
449 : }
450 : }
451 :
452 0 : CPLFree(pabyRecord);
453 :
454 0 : return CE_None;
455 : }
456 :
457 : /************************************************************************/
458 : /* ==================================================================== */
459 : /* PALSARRasterBand */
460 : /* ==================================================================== */
461 : /************************************************************************/
462 :
463 : /************************************************************************/
464 : /* PALSARRasterBand() */
465 : /************************************************************************/
466 :
467 0 : PALSARRasterBand::PALSARRasterBand(SAR_CEOSDataset *poGDSIn, int nBandIn)
468 :
469 : {
470 0 : poDS = poGDSIn;
471 0 : nBand = nBandIn;
472 :
473 0 : eDataType = GDT_CInt16;
474 :
475 0 : nBlockXSize = poGDSIn->nRasterXSize;
476 0 : nBlockYSize = 1;
477 :
478 0 : if (nBand == 1)
479 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_11");
480 0 : else if (nBand == 2)
481 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_22");
482 0 : else if (nBand == 3)
483 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_33");
484 0 : else if (nBand == 4)
485 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_12");
486 0 : else if (nBand == 5)
487 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_13");
488 0 : else if (nBand == 6)
489 0 : SetMetadataItem("POLARIMETRIC_INTERP", "Covariance_23");
490 0 : }
491 :
492 : /************************************************************************/
493 : /* IReadBlock() */
494 : /* */
495 : /* Based on ERSDAC-VX-CEOS-004 */
496 : /************************************************************************/
497 :
498 0 : CPLErr PALSARRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff,
499 : void *pImage)
500 : {
501 0 : SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *)poDS;
502 :
503 0 : struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
504 :
505 0 : int offset = ImageDesc->FileDescriptorLength +
506 0 : ImageDesc->BytesPerRecord * nBlockYOff +
507 0 : ImageDesc->ImageDataStart;
508 :
509 : /* -------------------------------------------------------------------- */
510 : /* Load all the pixel data associated with this scanline. */
511 : /* -------------------------------------------------------------------- */
512 0 : const int nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
513 :
514 0 : GByte *pabyRecord = (GByte *)CPLMalloc(nBytesToRead);
515 :
516 0 : if (VSIFSeekL(poGDS->fpImage, offset, SEEK_SET) != 0 ||
517 0 : (int)VSIFReadL(pabyRecord, 1, nBytesToRead, poGDS->fpImage) !=
518 : nBytesToRead)
519 : {
520 0 : CPLError(CE_Failure, CPLE_FileIO,
521 : "Error reading %d bytes of CEOS record data at offset %d.\n"
522 : "Reading file %s failed.",
523 0 : nBytesToRead, offset, poGDS->GetDescription());
524 0 : CPLFree(pabyRecord);
525 0 : return CE_Failure;
526 : }
527 :
528 : /* -------------------------------------------------------------------- */
529 : /* Copy the desired band out based on the size of the type, and */
530 : /* the interleaving mode. */
531 : /* -------------------------------------------------------------------- */
532 0 : if (nBand == 1 || nBand == 2 || nBand == 3)
533 : {
534 : // we need to pre-initialize things to set the imaginary component to 0
535 0 : memset(pImage, 0, nBlockXSize * 4);
536 :
537 0 : GDALCopyWords(pabyRecord + 4 * (nBand - 1), GDT_Int16, 18, pImage,
538 : GDT_Int16, 4, nBlockXSize);
539 : #ifdef CPL_LSB
540 0 : GDALSwapWords(pImage, 2, nBlockXSize, 4);
541 : #endif
542 : }
543 : else
544 : {
545 0 : GDALCopyWords(pabyRecord + 6 + 4 * (nBand - 4), GDT_CInt16, 18, pImage,
546 : GDT_CInt16, 4, nBlockXSize);
547 : #ifdef CPL_LSB
548 0 : GDALSwapWords(pImage, 2, nBlockXSize * 2, 2);
549 : #endif
550 : }
551 0 : CPLFree(pabyRecord);
552 :
553 : /* -------------------------------------------------------------------- */
554 : /* Convert the values into covariance form as per: */
555 : /* -------------------------------------------------------------------- */
556 : /*
557 : ** 1) PALSAR- adjust so that it reads bands as a covariance matrix, and
558 : ** set polarimetric interpretation accordingly:
559 : **
560 : ** Covariance_11=HH*conj(HH): already there
561 : ** Covariance_22=2*HV*conj(HV): need a factor of 2
562 : ** Covariance_33=VV*conj(VV): already there
563 : ** Covariance_12=sqrt(2)*HH*conj(HV): need the sqrt(2) factor
564 : ** Covariance_13=HH*conj(VV): already there
565 : ** Covariance_23=sqrt(2)*HV*conj(VV): need to take the conjugate, then
566 : ** multiply by sqrt(2)
567 : **
568 : */
569 :
570 0 : if (nBand == 2)
571 : {
572 0 : GInt16 *panLine = (GInt16 *)pImage;
573 :
574 0 : for (int i = 0; i < nBlockXSize * 2; i++)
575 : {
576 0 : panLine[i] = (GInt16)CastToGInt16((float)2.0 * panLine[i]);
577 : }
578 : }
579 0 : else if (nBand == 4)
580 : {
581 0 : const double sqrt_2 = pow(2.0, 0.5);
582 0 : GInt16 *panLine = (GInt16 *)pImage;
583 :
584 0 : for (int i = 0; i < nBlockXSize * 2; i++)
585 : {
586 0 : panLine[i] =
587 0 : (GInt16)CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
588 : }
589 : }
590 0 : else if (nBand == 6)
591 : {
592 0 : GInt16 *panLine = (GInt16 *)pImage;
593 0 : const double sqrt_2 = pow(2.0, 0.5);
594 :
595 : // real portion - just multiple by sqrt(2)
596 0 : for (int i = 0; i < nBlockXSize * 2; i += 2)
597 : {
598 0 : panLine[i] =
599 0 : (GInt16)CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
600 : }
601 :
602 : // imaginary portion - conjugate and multiply
603 0 : for (int i = 1; i < nBlockXSize * 2; i += 2)
604 : {
605 0 : panLine[i] =
606 0 : (GInt16)CastToGInt16((float)floor(-panLine[i] * sqrt_2 + 0.5));
607 : }
608 : }
609 :
610 0 : return CE_None;
611 : }
612 :
613 : /************************************************************************/
614 : /* ==================================================================== */
615 : /* SAR_CEOSDataset */
616 : /* ==================================================================== */
617 : /************************************************************************/
618 :
619 : /************************************************************************/
620 : /* SAR_CEOSDataset() */
621 : /************************************************************************/
622 :
623 4 : SAR_CEOSDataset::SAR_CEOSDataset()
624 : : fpImage(nullptr), papszTempMD(nullptr), nGCPCount(0), pasGCPList(nullptr),
625 4 : papszExtraFiles(nullptr)
626 : {
627 4 : m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
628 4 : m_oSRS.importFromWkt(SRS_WKT_WGS84_LAT_LONG);
629 :
630 4 : sVolume.Flavor = 0;
631 4 : sVolume.Sensor = 0;
632 4 : sVolume.ProductType = 0;
633 4 : sVolume.FileNamingConvention = 0;
634 :
635 4 : sVolume.VolumeDirectoryFile = 0;
636 4 : sVolume.SARLeaderFile = 0;
637 4 : sVolume.ImagryOptionsFile = 0;
638 4 : sVolume.SARTrailerFile = 0;
639 4 : sVolume.NullVolumeDirectoryFile = 0;
640 :
641 4 : sVolume.ImageDesc.ImageDescValid = 0;
642 4 : sVolume.ImageDesc.NumChannels = 0;
643 4 : sVolume.ImageDesc.ChannelInterleaving = 0;
644 4 : sVolume.ImageDesc.DataType = 0;
645 4 : sVolume.ImageDesc.BytesPerRecord = 0;
646 4 : sVolume.ImageDesc.Lines = 0;
647 4 : sVolume.ImageDesc.TopBorderPixels = 0;
648 4 : sVolume.ImageDesc.BottomBorderPixels = 0;
649 4 : sVolume.ImageDesc.PixelsPerLine = 0;
650 4 : sVolume.ImageDesc.LeftBorderPixels = 0;
651 4 : sVolume.ImageDesc.RightBorderPixels = 0;
652 4 : sVolume.ImageDesc.BytesPerPixel = 0;
653 4 : sVolume.ImageDesc.RecordsPerLine = 0;
654 4 : sVolume.ImageDesc.PixelsPerRecord = 0;
655 4 : sVolume.ImageDesc.ImageDataStart = 0;
656 4 : sVolume.ImageDesc.ImageSuffixData = 0;
657 4 : sVolume.ImageDesc.FileDescriptorLength = 0;
658 4 : sVolume.ImageDesc.PixelOrder = 0;
659 4 : sVolume.ImageDesc.LineOrder = 0;
660 4 : sVolume.ImageDesc.PixelDataBytesPerRecord = 0;
661 :
662 4 : sVolume.RecordList = nullptr;
663 4 : }
664 :
665 : /************************************************************************/
666 : /* ~SAR_CEOSDataset() */
667 : /************************************************************************/
668 :
669 8 : SAR_CEOSDataset::~SAR_CEOSDataset()
670 :
671 : {
672 4 : FlushCache(true);
673 :
674 4 : CSLDestroy(papszTempMD);
675 :
676 4 : if (fpImage != nullptr)
677 4 : CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage));
678 :
679 4 : if (nGCPCount > 0)
680 : {
681 4 : GDALDeinitGCPs(nGCPCount, pasGCPList);
682 : }
683 4 : CPLFree(pasGCPList);
684 :
685 4 : if (sVolume.RecordList)
686 : {
687 40 : for (Link_t *Links = sVolume.RecordList; Links != nullptr;
688 36 : Links = Links->next)
689 : {
690 36 : if (Links->object)
691 : {
692 36 : DeleteCeosRecord((CeosRecord_t *)Links->object);
693 36 : Links->object = nullptr;
694 : }
695 : }
696 4 : DestroyList(sVolume.RecordList);
697 : }
698 4 : FreeRecipes();
699 4 : CSLDestroy(papszExtraFiles);
700 8 : }
701 :
702 : /************************************************************************/
703 : /* GetGCPCount() */
704 : /************************************************************************/
705 :
706 0 : int SAR_CEOSDataset::GetGCPCount()
707 :
708 : {
709 0 : return nGCPCount;
710 : }
711 :
712 : /************************************************************************/
713 : /* GetGCPSpatialRef() */
714 : /************************************************************************/
715 :
716 0 : const OGRSpatialReference *SAR_CEOSDataset::GetGCPSpatialRef() const
717 :
718 : {
719 0 : if (nGCPCount > 0)
720 0 : return &m_oSRS;
721 :
722 0 : return nullptr;
723 : }
724 :
725 : /************************************************************************/
726 : /* GetGCP() */
727 : /************************************************************************/
728 :
729 0 : const GDAL_GCP *SAR_CEOSDataset::GetGCPs()
730 :
731 : {
732 0 : return pasGCPList;
733 : }
734 :
735 : /************************************************************************/
736 : /* GetMetadataDomainList() */
737 : /************************************************************************/
738 :
739 0 : char **SAR_CEOSDataset::GetMetadataDomainList()
740 : {
741 0 : return CSLAddString(GDALDataset::GetMetadataDomainList(),
742 0 : "ceos-FFF-n-n-n-n:r");
743 : }
744 :
745 : /************************************************************************/
746 : /* GetMetadata() */
747 : /* */
748 : /* We provide our own GetMetadata() so that we can override */
749 : /* behavior for some very specialized domain names intended to */
750 : /* give us access to raw record data. */
751 : /* */
752 : /* The domain must look like: */
753 : /* ceos-FFF-n-n-n-n:r */
754 : /* */
755 : /* FFF - The file id - one of vol, lea, img, trl or nul. */
756 : /* n-n-n-n - the record type code such as 18-10-18-20 for the */
757 : /* dataset summary record in the leader file. */
758 : /* :r - The zero based record number to fetch (optional) */
759 : /* */
760 : /* Note that only records that are pre-loaded will be */
761 : /* accessible, and this normally means that most image records */
762 : /* are not available. */
763 : /************************************************************************/
764 :
765 2 : char **SAR_CEOSDataset::GetMetadata(const char *pszDomain)
766 :
767 : {
768 2 : if (pszDomain == nullptr || !STARTS_WITH_CI(pszDomain, "ceos-"))
769 2 : return GDALDataset::GetMetadata(pszDomain);
770 :
771 : /* -------------------------------------------------------------------- */
772 : /* Identify which file to fetch the file from. */
773 : /* -------------------------------------------------------------------- */
774 0 : int nFileId = -1;
775 :
776 0 : if (STARTS_WITH_CI(pszDomain, "ceos-vol"))
777 : {
778 0 : nFileId = CEOS_VOLUME_DIR_FILE;
779 : }
780 0 : else if (STARTS_WITH_CI(pszDomain, "ceos-lea"))
781 : {
782 0 : nFileId = CEOS_LEADER_FILE;
783 : }
784 0 : else if (STARTS_WITH_CI(pszDomain, "ceos-img"))
785 : {
786 0 : nFileId = CEOS_IMAGRY_OPT_FILE;
787 : }
788 0 : else if (STARTS_WITH_CI(pszDomain, "ceos-trl"))
789 : {
790 0 : nFileId = CEOS_TRAILER_FILE;
791 : }
792 0 : else if (STARTS_WITH_CI(pszDomain, "ceos-nul"))
793 : {
794 0 : nFileId = CEOS_NULL_VOL_FILE;
795 : }
796 : else
797 0 : return nullptr;
798 :
799 0 : pszDomain += 8;
800 :
801 : /* -------------------------------------------------------------------- */
802 : /* Identify the record type. */
803 : /* -------------------------------------------------------------------- */
804 0 : int a, b, c, d, nRecordIndex = -1;
805 :
806 0 : if (sscanf(pszDomain, "-%d-%d-%d-%d:%d", &a, &b, &c, &d, &nRecordIndex) !=
807 0 : 5 &&
808 0 : sscanf(pszDomain, "-%d-%d-%d-%d", &a, &b, &c, &d) != 4)
809 : {
810 0 : return nullptr;
811 : }
812 :
813 0 : CeosTypeCode_t sTypeCode = QuadToTC(a, b, c, d);
814 :
815 : /* -------------------------------------------------------------------- */
816 : /* Try to fetch the record. */
817 : /* -------------------------------------------------------------------- */
818 0 : CeosRecord_t *record = FindCeosRecord(sVolume.RecordList, sTypeCode,
819 : nFileId, -1, nRecordIndex);
820 :
821 0 : if (record == nullptr)
822 0 : return nullptr;
823 :
824 : /* -------------------------------------------------------------------- */
825 : /* Massage the data into a safe textual format. The RawRecord */
826 : /* just has zero bytes turned into spaces while the */
827 : /* EscapedRecord has regular backslash escaping applied to zero */
828 : /* chars, double quotes, and backslashes. */
829 : /* just turn zero bytes into spaces. */
830 : /* -------------------------------------------------------------------- */
831 :
832 0 : CSLDestroy(papszTempMD);
833 :
834 : // Escaped version
835 0 : char *pszSafeCopy = CPLEscapeString((char *)record->Buffer, record->Length,
836 : CPLES_BackslashQuotable);
837 0 : papszTempMD = CSLSetNameValue(nullptr, "EscapedRecord", pszSafeCopy);
838 0 : CPLFree(pszSafeCopy);
839 :
840 : // Copy with '\0' replaced by spaces.
841 :
842 0 : pszSafeCopy = (char *)CPLCalloc(1, record->Length + 1);
843 0 : memcpy(pszSafeCopy, record->Buffer, record->Length);
844 :
845 0 : for (int i = 0; i < record->Length; i++)
846 0 : if (pszSafeCopy[i] == '\0')
847 0 : pszSafeCopy[i] = ' ';
848 :
849 0 : papszTempMD = CSLSetNameValue(papszTempMD, "RawRecord", pszSafeCopy);
850 :
851 0 : CPLFree(pszSafeCopy);
852 :
853 0 : return papszTempMD;
854 : }
855 :
856 : /************************************************************************/
857 : /* ScanForMetadata() */
858 : /************************************************************************/
859 :
860 4 : void SAR_CEOSDataset::ScanForMetadata()
861 :
862 : {
863 : /* -------------------------------------------------------------------- */
864 : /* Get the volume id (with the sensor name) */
865 : /* -------------------------------------------------------------------- */
866 : CeosRecord_t *record =
867 4 : FindCeosRecord(sVolume.RecordList, VOLUME_DESCRIPTOR_RECORD_TC,
868 : CEOS_VOLUME_DIR_FILE, -1, -1);
869 :
870 : char szVolId[128];
871 4 : szVolId[0] = '\0';
872 : char szField[128];
873 4 : szField[0] = '\0';
874 4 : if (record != nullptr)
875 : {
876 0 : szVolId[16] = '\0';
877 :
878 0 : GetCeosField(record, 61, "A16", szVolId);
879 :
880 0 : SetMetadataItem("CEOS_LOGICAL_VOLUME_ID", szVolId);
881 :
882 : /* --------------------------------------------------------------------
883 : */
884 : /* Processing facility */
885 : /* --------------------------------------------------------------------
886 : */
887 0 : szField[0] = '\0';
888 0 : szField[12] = '\0';
889 :
890 0 : GetCeosField(record, 149, "A12", szField);
891 :
892 0 : if (!STARTS_WITH_CI(szField, " "))
893 0 : SetMetadataItem("CEOS_PROCESSING_FACILITY", szField);
894 :
895 : /* --------------------------------------------------------------------
896 : */
897 : /* Agency */
898 : /* --------------------------------------------------------------------
899 : */
900 0 : szField[8] = '\0';
901 :
902 0 : GetCeosField(record, 141, "A8", szField);
903 :
904 0 : if (!STARTS_WITH_CI(szField, " "))
905 0 : SetMetadataItem("CEOS_PROCESSING_AGENCY", szField);
906 :
907 : /* --------------------------------------------------------------------
908 : */
909 : /* Country */
910 : /* --------------------------------------------------------------------
911 : */
912 0 : szField[12] = '\0';
913 :
914 0 : GetCeosField(record, 129, "A12", szField);
915 :
916 0 : if (!STARTS_WITH_CI(szField, " "))
917 0 : SetMetadataItem("CEOS_PROCESSING_COUNTRY", szField);
918 :
919 : /* --------------------------------------------------------------------
920 : */
921 : /* software id. */
922 : /* --------------------------------------------------------------------
923 : */
924 0 : szField[12] = '\0';
925 :
926 0 : GetCeosField(record, 33, "A12", szField);
927 :
928 0 : if (!STARTS_WITH_CI(szField, " "))
929 0 : SetMetadataItem("CEOS_SOFTWARE_ID", szField);
930 :
931 : /* --------------------------------------------------------------------
932 : */
933 : /* product identifier. */
934 : /* --------------------------------------------------------------------
935 : */
936 0 : szField[8] = '\0';
937 :
938 0 : GetCeosField(record, 261, "A8", szField);
939 :
940 0 : if (!STARTS_WITH_CI(szField, " "))
941 0 : SetMetadataItem("CEOS_PRODUCT_ID", szField);
942 :
943 : /* --------------------------------------------------------------------
944 : */
945 : /* volume identifier. */
946 : /* --------------------------------------------------------------------
947 : */
948 0 : szField[16] = '\0';
949 :
950 0 : GetCeosField(record, 77, "A16", szField);
951 :
952 0 : if (!STARTS_WITH_CI(szField, " "))
953 0 : SetMetadataItem("CEOS_VOLSET_ID", szField);
954 : }
955 :
956 : /* ==================================================================== */
957 : /* Dataset summary record. */
958 : /* ==================================================================== */
959 4 : record = FindCeosRecord(sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
960 : CEOS_LEADER_FILE, -1, -1);
961 :
962 4 : if (record == nullptr)
963 : record =
964 4 : FindCeosRecord(sVolume.RecordList, LEADER_DATASET_SUMMARY_ASF_TC,
965 : CEOS_LEADER_FILE, -1, -1);
966 :
967 4 : if (record == nullptr)
968 2 : record = FindCeosRecord(sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
969 : CEOS_TRAILER_FILE, -1, -1);
970 :
971 4 : if (record == nullptr)
972 : record =
973 2 : FindCeosRecord(sVolume.RecordList, LEADER_DATASET_SUMMARY_ERS2_TC,
974 : CEOS_LEADER_FILE, -1, -1);
975 :
976 4 : if (record != nullptr)
977 : {
978 : /* --------------------------------------------------------------------
979 : */
980 : /* Get the acquisition date. */
981 : /* --------------------------------------------------------------------
982 : */
983 2 : szField[0] = '\0';
984 2 : szField[32] = '\0';
985 :
986 2 : GetCeosField(record, 69, "A32", szField);
987 :
988 2 : SetMetadataItem("CEOS_ACQUISITION_TIME", szField);
989 :
990 : /* --------------------------------------------------------------------
991 : */
992 : /* Ascending/Descending */
993 : /* --------------------------------------------------------------------
994 : */
995 2 : GetCeosField(record, 101, "A16", szField);
996 2 : szField[16] = '\0';
997 :
998 2 : if (strstr(szVolId, "RSAT") != nullptr &&
999 0 : !STARTS_WITH_CI(szField, " "))
1000 0 : SetMetadataItem("CEOS_ASC_DES", szField);
1001 :
1002 : /* --------------------------------------------------------------------
1003 : */
1004 : /* True heading - at least for ERS2. */
1005 : /* --------------------------------------------------------------------
1006 : */
1007 2 : GetCeosField(record, 149, "A16", szField);
1008 2 : szField[16] = '\0';
1009 :
1010 2 : if (!STARTS_WITH_CI(szField, " "))
1011 2 : SetMetadataItem("CEOS_TRUE_HEADING", szField);
1012 :
1013 : /* --------------------------------------------------------------------
1014 : */
1015 : /* Ellipsoid */
1016 : /* --------------------------------------------------------------------
1017 : */
1018 2 : GetCeosField(record, 165, "A16", szField);
1019 2 : szField[16] = '\0';
1020 :
1021 2 : if (!STARTS_WITH_CI(szField, " "))
1022 2 : SetMetadataItem("CEOS_ELLIPSOID", szField);
1023 :
1024 : /* --------------------------------------------------------------------
1025 : */
1026 : /* Semimajor, semiminor axis */
1027 : /* --------------------------------------------------------------------
1028 : */
1029 2 : GetCeosField(record, 181, "A16", szField);
1030 2 : szField[16] = '\0';
1031 :
1032 2 : if (!STARTS_WITH_CI(szField, " "))
1033 2 : SetMetadataItem("CEOS_SEMI_MAJOR", szField);
1034 :
1035 2 : GetCeosField(record, 197, "A16", szField);
1036 2 : szField[16] = '\0';
1037 :
1038 2 : if (!STARTS_WITH_CI(szField, " "))
1039 2 : SetMetadataItem("CEOS_SEMI_MINOR", szField);
1040 :
1041 : /* --------------------------------------------------------------------
1042 : */
1043 : /* SCENE LENGTH KM */
1044 : /* --------------------------------------------------------------------
1045 : */
1046 2 : GetCeosField(record, 341, "A16", szField);
1047 2 : szField[16] = '\0';
1048 :
1049 2 : if (!STARTS_WITH_CI(szField, " "))
1050 2 : SetMetadataItem("CEOS_SCENE_LENGTH_KM", szField);
1051 :
1052 : /* --------------------------------------------------------------------
1053 : */
1054 : /* SCENE WIDTH KM */
1055 : /* --------------------------------------------------------------------
1056 : */
1057 2 : GetCeosField(record, 357, "A16", szField);
1058 2 : szField[16] = '\0';
1059 :
1060 2 : if (!STARTS_WITH_CI(szField, " "))
1061 2 : SetMetadataItem("CEOS_SCENE_WIDTH_KM", szField);
1062 :
1063 : /* --------------------------------------------------------------------
1064 : */
1065 : /* MISSION ID */
1066 : /* --------------------------------------------------------------------
1067 : */
1068 2 : GetCeosField(record, 397, "A16", szField);
1069 2 : szField[16] = '\0';
1070 :
1071 2 : if (!STARTS_WITH_CI(szField, " "))
1072 2 : SetMetadataItem("CEOS_MISSION_ID", szField);
1073 :
1074 : /* --------------------------------------------------------------------
1075 : */
1076 : /* SENSOR ID */
1077 : /* --------------------------------------------------------------------
1078 : */
1079 2 : GetCeosField(record, 413, "A32", szField);
1080 2 : szField[32] = '\0';
1081 :
1082 2 : if (!STARTS_WITH_CI(szField, " "))
1083 2 : SetMetadataItem("CEOS_SENSOR_ID", szField);
1084 :
1085 : /* --------------------------------------------------------------------
1086 : */
1087 : /* ORBIT NUMBER */
1088 : /* --------------------------------------------------------------------
1089 : */
1090 2 : GetCeosField(record, 445, "A8", szField);
1091 2 : szField[8] = '\0';
1092 :
1093 2 : if (!STARTS_WITH_CI(szField, " "))
1094 2 : SetMetadataItem("CEOS_ORBIT_NUMBER", szField);
1095 :
1096 : /* --------------------------------------------------------------------
1097 : */
1098 : /* Platform latitude */
1099 : /* --------------------------------------------------------------------
1100 : */
1101 2 : GetCeosField(record, 453, "A8", szField);
1102 2 : szField[8] = '\0';
1103 :
1104 2 : if (!STARTS_WITH_CI(szField, " "))
1105 2 : SetMetadataItem("CEOS_PLATFORM_LATITUDE", szField);
1106 :
1107 : /* --------------------------------------------------------------------
1108 : */
1109 : /* Platform longitude */
1110 : /* --------------------------------------------------------------------
1111 : */
1112 2 : GetCeosField(record, 461, "A8", szField);
1113 2 : szField[8] = '\0';
1114 :
1115 2 : if (!STARTS_WITH_CI(szField, " "))
1116 2 : SetMetadataItem("CEOS_PLATFORM_LONGITUDE", szField);
1117 :
1118 : /* --------------------------------------------------------------------
1119 : */
1120 : /* Platform heading - at least for ERS2. */
1121 : /* --------------------------------------------------------------------
1122 : */
1123 2 : GetCeosField(record, 469, "A8", szField);
1124 2 : szField[8] = '\0';
1125 :
1126 2 : if (!STARTS_WITH_CI(szField, " "))
1127 2 : SetMetadataItem("CEOS_PLATFORM_HEADING", szField);
1128 :
1129 : /* --------------------------------------------------------------------
1130 : */
1131 : /* Look Angle. */
1132 : /* --------------------------------------------------------------------
1133 : */
1134 2 : GetCeosField(record, 477, "A8", szField);
1135 2 : szField[8] = '\0';
1136 :
1137 2 : if (!STARTS_WITH_CI(szField, " "))
1138 2 : SetMetadataItem("CEOS_SENSOR_CLOCK_ANGLE", szField);
1139 :
1140 : /* --------------------------------------------------------------------
1141 : */
1142 : /* Incidence angle */
1143 : /* --------------------------------------------------------------------
1144 : */
1145 2 : GetCeosField(record, 485, "A8", szField);
1146 2 : szField[8] = '\0';
1147 :
1148 2 : if (!STARTS_WITH_CI(szField, " "))
1149 2 : SetMetadataItem("CEOS_INC_ANGLE", szField);
1150 :
1151 : /* --------------------------------------------------------------------
1152 : */
1153 : /* Facility */
1154 : /* --------------------------------------------------------------------
1155 : */
1156 2 : GetCeosField(record, 1047, "A16", szField);
1157 2 : szField[16] = '\0';
1158 :
1159 2 : if (!STARTS_WITH_CI(szField, " "))
1160 2 : SetMetadataItem("CEOS_FACILITY", szField);
1161 : /* --------------------------------------------------------------------
1162 : */
1163 : /* Pixel time direction indicator */
1164 : /* --------------------------------------------------------------------
1165 : */
1166 2 : GetCeosField(record, 1527, "A8", szField);
1167 2 : szField[8] = '\0';
1168 :
1169 2 : if (!STARTS_WITH_CI(szField, " "))
1170 2 : SetMetadataItem("CEOS_PIXEL_TIME_DIR", szField);
1171 :
1172 : /* --------------------------------------------------------------------
1173 : */
1174 : /* Line spacing */
1175 : /* --------------------------------------------------------------------
1176 : */
1177 2 : GetCeosField(record, 1687, "A16", szField);
1178 2 : szField[16] = '\0';
1179 :
1180 2 : if (!STARTS_WITH_CI(szField, " "))
1181 2 : SetMetadataItem("CEOS_LINE_SPACING_METERS", szField);
1182 : /* --------------------------------------------------------------------
1183 : */
1184 : /* Pixel spacing */
1185 : /* --------------------------------------------------------------------
1186 : */
1187 2 : GetCeosField(record, 1703, "A16", szField);
1188 2 : szField[16] = '\0';
1189 :
1190 2 : if (!STARTS_WITH_CI(szField, " "))
1191 2 : SetMetadataItem("CEOS_PIXEL_SPACING_METERS", szField);
1192 : }
1193 :
1194 : /* -------------------------------------------------------------------- */
1195 : /* Get the beam mode, for radarsat. */
1196 : /* -------------------------------------------------------------------- */
1197 : record =
1198 4 : FindCeosRecord(sVolume.RecordList, LEADER_RADIOMETRIC_COMPENSATION_TC,
1199 : CEOS_LEADER_FILE, -1, -1);
1200 :
1201 4 : if (strstr(szVolId, "RSAT") != nullptr && record != nullptr)
1202 : {
1203 0 : szField[16] = '\0';
1204 :
1205 0 : GetCeosField(record, 4189, "A16", szField);
1206 :
1207 0 : SetMetadataItem("CEOS_BEAM_TYPE", szField);
1208 : }
1209 :
1210 : /* ==================================================================== */
1211 : /* ERS calibration and incidence angle info */
1212 : /* ==================================================================== */
1213 4 : record = FindCeosRecord(sVolume.RecordList, ERS_GENERAL_FACILITY_DATA_TC,
1214 : CEOS_LEADER_FILE, -1, -1);
1215 :
1216 4 : if (record == nullptr)
1217 : record =
1218 4 : FindCeosRecord(sVolume.RecordList, ERS_GENERAL_FACILITY_DATA_ALT_TC,
1219 : CEOS_LEADER_FILE, -1, -1);
1220 :
1221 4 : if (record != nullptr)
1222 : {
1223 0 : GetCeosField(record, 13, "A64", szField);
1224 0 : szField[64] = '\0';
1225 :
1226 : /* Avoid PCS records, which don't contain necessary info */
1227 0 : if (strstr(szField, "GENERAL") == nullptr)
1228 0 : record = nullptr;
1229 : }
1230 :
1231 4 : if (record != nullptr)
1232 : {
1233 0 : GetCeosField(record, 583, "A16", szField);
1234 0 : szField[16] = '\0';
1235 :
1236 0 : if (!STARTS_WITH_CI(szField, " "))
1237 0 : SetMetadataItem("CEOS_INC_ANGLE_FIRST_RANGE", szField);
1238 :
1239 0 : GetCeosField(record, 599, "A16", szField);
1240 0 : szField[16] = '\0';
1241 :
1242 0 : if (!STARTS_WITH_CI(szField, " "))
1243 0 : SetMetadataItem("CEOS_INC_ANGLE_CENTRE_RANGE", szField);
1244 :
1245 0 : GetCeosField(record, 615, "A16", szField);
1246 0 : szField[16] = '\0';
1247 :
1248 0 : if (!STARTS_WITH_CI(szField, " "))
1249 0 : SetMetadataItem("CEOS_INC_ANGLE_LAST_RANGE", szField);
1250 :
1251 0 : GetCeosField(record, 663, "A16", szField);
1252 0 : szField[16] = '\0';
1253 :
1254 0 : if (!STARTS_WITH_CI(szField, " "))
1255 0 : SetMetadataItem("CEOS_CALIBRATION_CONSTANT_K", szField);
1256 :
1257 0 : GetCeosField(record, 1855, "A20", szField);
1258 0 : szField[20] = '\0';
1259 :
1260 0 : if (!STARTS_WITH_CI(szField, " "))
1261 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C0", szField);
1262 :
1263 0 : GetCeosField(record, 1875, "A20", szField);
1264 0 : szField[20] = '\0';
1265 :
1266 0 : if (!STARTS_WITH_CI(szField, " "))
1267 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C1", szField);
1268 :
1269 0 : GetCeosField(record, 1895, "A20", szField);
1270 0 : szField[20] = '\0';
1271 :
1272 0 : if (!STARTS_WITH_CI(szField, " "))
1273 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C2", szField);
1274 :
1275 0 : GetCeosField(record, 1915, "A20", szField);
1276 0 : szField[20] = '\0';
1277 :
1278 0 : if (!STARTS_WITH_CI(szField, " "))
1279 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C3", szField);
1280 : }
1281 : /* -------------------------------------------------------------------- */
1282 : /* Detailed Processing Parameters (Radarsat) */
1283 : /* -------------------------------------------------------------------- */
1284 4 : record = FindCeosRecord(sVolume.RecordList, RSAT_PROC_PARAM_TC,
1285 : CEOS_LEADER_FILE, -1, -1);
1286 :
1287 4 : if (record == nullptr)
1288 4 : record = FindCeosRecord(sVolume.RecordList, RSAT_PROC_PARAM_TC,
1289 : CEOS_TRAILER_FILE, -1, -1);
1290 :
1291 4 : if (record != nullptr)
1292 : {
1293 0 : GetCeosField(record, 192, "A21", szField);
1294 0 : szField[21] = '\0';
1295 :
1296 0 : if (!STARTS_WITH_CI(szField, " "))
1297 0 : SetMetadataItem("CEOS_PROC_START", szField);
1298 :
1299 0 : GetCeosField(record, 213, "A21", szField);
1300 0 : szField[21] = '\0';
1301 :
1302 0 : if (!STARTS_WITH_CI(szField, " "))
1303 0 : SetMetadataItem("CEOS_PROC_STOP", szField);
1304 :
1305 0 : GetCeosField(record, 4649, "A16", szField);
1306 0 : szField[16] = '\0';
1307 :
1308 0 : if (!STARTS_WITH_CI(szField, " "))
1309 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_0", szField);
1310 :
1311 0 : GetCeosField(record, 4665, "A16", szField);
1312 0 : szField[16] = '\0';
1313 :
1314 0 : if (!STARTS_WITH_CI(szField, " "))
1315 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_1", szField);
1316 :
1317 0 : GetCeosField(record, 4681, "A16", szField);
1318 0 : szField[16] = '\0';
1319 :
1320 0 : if (!STARTS_WITH_CI(szField, " "))
1321 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_2", szField);
1322 :
1323 0 : GetCeosField(record, 4697, "A16", szField);
1324 0 : szField[16] = '\0';
1325 :
1326 0 : if (!STARTS_WITH_CI(szField, " "))
1327 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_3", szField);
1328 :
1329 0 : GetCeosField(record, 4713, "A16", szField);
1330 0 : szField[16] = '\0';
1331 :
1332 0 : if (!STARTS_WITH_CI(szField, " "))
1333 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_4", szField);
1334 :
1335 0 : GetCeosField(record, 4729, "A16", szField);
1336 0 : szField[16] = '\0';
1337 :
1338 0 : if (!STARTS_WITH_CI(szField, " "))
1339 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_5", szField);
1340 :
1341 0 : GetCeosField(record, 4745, "A16", szField);
1342 0 : szField[16] = '\0';
1343 :
1344 0 : if (!STARTS_WITH_CI(szField, " "))
1345 0 : SetMetadataItem("CEOS_EPH_ORB_DATA_6", szField);
1346 :
1347 0 : GetCeosField(record, 4908, "A16", szField);
1348 0 : szField[16] = '\0';
1349 :
1350 0 : if (!STARTS_WITH_CI(szField, " "))
1351 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C0", szField);
1352 :
1353 0 : GetCeosField(record, 4924, "A16", szField);
1354 0 : szField[16] = '\0';
1355 :
1356 0 : if (!STARTS_WITH_CI(szField, " "))
1357 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C1", szField);
1358 :
1359 0 : GetCeosField(record, 4940, "A16", szField);
1360 0 : szField[16] = '\0';
1361 :
1362 0 : if (!STARTS_WITH_CI(szField, " "))
1363 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C2", szField);
1364 :
1365 0 : GetCeosField(record, 4956, "A16", szField);
1366 0 : szField[16] = '\0';
1367 :
1368 0 : if (!STARTS_WITH_CI(szField, " "))
1369 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C3", szField);
1370 :
1371 0 : GetCeosField(record, 4972, "A16", szField);
1372 0 : szField[16] = '\0';
1373 :
1374 0 : if (!STARTS_WITH_CI(szField, " "))
1375 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C4", szField);
1376 :
1377 0 : GetCeosField(record, 4988, "A16", szField);
1378 0 : szField[16] = '\0';
1379 :
1380 0 : if (!STARTS_WITH_CI(szField, " "))
1381 0 : SetMetadataItem("CEOS_GROUND_TO_SLANT_C5", szField);
1382 :
1383 0 : GetCeosField(record, 7334, "A16", szField);
1384 0 : szField[16] = '\0';
1385 :
1386 0 : if (!STARTS_WITH_CI(szField, " "))
1387 0 : SetMetadataItem("CEOS_INC_ANGLE_FIRST_RANGE", szField);
1388 :
1389 0 : GetCeosField(record, 7350, "A16", szField);
1390 0 : szField[16] = '\0';
1391 :
1392 0 : if (!STARTS_WITH_CI(szField, " "))
1393 0 : SetMetadataItem("CEOS_INC_ANGLE_LAST_RANGE", szField);
1394 : }
1395 : /* -------------------------------------------------------------------- */
1396 : /* Get process-to-raw data coordinate translation values. These */
1397 : /* are likely specific to Atlantis APP products. */
1398 : /* -------------------------------------------------------------------- */
1399 4 : record = FindCeosRecord(sVolume.RecordList, IMAGE_HEADER_RECORD_TC,
1400 : CEOS_IMAGRY_OPT_FILE, -1, -1);
1401 :
1402 4 : if (record != nullptr)
1403 : {
1404 4 : GetCeosField(record, 449, "A4", szField);
1405 4 : szField[4] = '\0';
1406 :
1407 4 : if (!STARTS_WITH_CI(szField, " "))
1408 2 : SetMetadataItem("CEOS_DM_CORNER", szField);
1409 :
1410 4 : GetCeosField(record, 453, "A4", szField);
1411 4 : szField[4] = '\0';
1412 :
1413 4 : if (!STARTS_WITH_CI(szField, " "))
1414 2 : SetMetadataItem("CEOS_DM_TRANSPOSE", szField);
1415 :
1416 4 : GetCeosField(record, 457, "A4", szField);
1417 4 : szField[4] = '\0';
1418 :
1419 4 : if (!STARTS_WITH_CI(szField, " "))
1420 2 : SetMetadataItem("CEOS_DM_START_SAMPLE", szField);
1421 :
1422 4 : GetCeosField(record, 461, "A5", szField);
1423 4 : szField[5] = '\0';
1424 :
1425 4 : if (!STARTS_WITH_CI(szField, " "))
1426 2 : SetMetadataItem("CEOS_DM_START_PULSE", szField);
1427 :
1428 4 : GetCeosField(record, 466, "A16", szField);
1429 4 : szField[16] = '\0';
1430 :
1431 4 : if (!STARTS_WITH_CI(szField, " "))
1432 2 : SetMetadataItem("CEOS_DM_FAST_ALPHA", szField);
1433 :
1434 4 : GetCeosField(record, 482, "A16", szField);
1435 4 : szField[16] = '\0';
1436 :
1437 4 : if (!STARTS_WITH_CI(szField, " "))
1438 2 : SetMetadataItem("CEOS_DM_FAST_BETA", szField);
1439 :
1440 4 : GetCeosField(record, 498, "A16", szField);
1441 4 : szField[16] = '\0';
1442 :
1443 4 : if (!STARTS_WITH_CI(szField, " "))
1444 2 : SetMetadataItem("CEOS_DM_SLOW_ALPHA", szField);
1445 :
1446 4 : GetCeosField(record, 514, "A16", szField);
1447 4 : szField[16] = '\0';
1448 :
1449 4 : if (!STARTS_WITH_CI(szField, " "))
1450 2 : SetMetadataItem("CEOS_DM_SLOW_BETA", szField);
1451 :
1452 4 : GetCeosField(record, 530, "A16", szField);
1453 4 : szField[16] = '\0';
1454 :
1455 4 : if (!STARTS_WITH_CI(szField, " "))
1456 2 : SetMetadataItem("CEOS_DM_FAST_ALPHA_2", szField);
1457 : }
1458 :
1459 : /* -------------------------------------------------------------------- */
1460 : /* Try to find calibration information from Radiometric Data */
1461 : /* Record. */
1462 : /* -------------------------------------------------------------------- */
1463 : record =
1464 4 : FindCeosRecord(sVolume.RecordList, LEADER_RADIOMETRIC_DATA_RECORD_TC,
1465 : CEOS_LEADER_FILE, -1, -1);
1466 :
1467 4 : if (record == nullptr)
1468 4 : record = FindCeosRecord(sVolume.RecordList,
1469 : LEADER_RADIOMETRIC_DATA_RECORD_TC,
1470 : CEOS_TRAILER_FILE, -1, -1);
1471 :
1472 4 : if (record != nullptr)
1473 : {
1474 0 : GetCeosField(record, 8317, "A16", szField);
1475 0 : szField[16] = '\0';
1476 :
1477 0 : if (!STARTS_WITH_CI(szField, " "))
1478 0 : SetMetadataItem("CEOS_CALIBRATION_OFFSET", szField);
1479 : }
1480 :
1481 : /* -------------------------------------------------------------------- */
1482 : /* For ERS Standard Format Landsat scenes we pick up the */
1483 : /* calibration offset and gain from the Radiometric Ancillary */
1484 : /* Record. */
1485 : /* -------------------------------------------------------------------- */
1486 : record =
1487 4 : FindCeosRecord(sVolume.RecordList, QuadToTC(0x3f, 0x24, 0x12, 0x09),
1488 : CEOS_LEADER_FILE, -1, -1);
1489 4 : if (record != nullptr)
1490 : {
1491 0 : GetCeosField(record, 29, "A20", szField);
1492 0 : szField[20] = '\0';
1493 :
1494 0 : if (!STARTS_WITH_CI(szField, " "))
1495 0 : SetMetadataItem("CEOS_OFFSET_A0", szField);
1496 :
1497 0 : GetCeosField(record, 49, "A20", szField);
1498 0 : szField[20] = '\0';
1499 :
1500 0 : if (!STARTS_WITH_CI(szField, " "))
1501 0 : SetMetadataItem("CEOS_GAIN_A1", szField);
1502 : }
1503 :
1504 : /* -------------------------------------------------------------------- */
1505 : /* For ERS Standard Format Landsat scenes we pick up the */
1506 : /* gain setting from the Scene Header Record. */
1507 : /* -------------------------------------------------------------------- */
1508 : record =
1509 4 : FindCeosRecord(sVolume.RecordList, QuadToTC(0x12, 0x12, 0x12, 0x09),
1510 : CEOS_LEADER_FILE, -1, -1);
1511 4 : if (record != nullptr)
1512 : {
1513 0 : GetCeosField(record, 1486, "A1", szField);
1514 0 : szField[1] = '\0';
1515 :
1516 0 : if (szField[0] == 'H' || szField[0] == 'V')
1517 0 : SetMetadataItem("CEOS_GAIN_SETTING", szField);
1518 : }
1519 4 : }
1520 :
1521 : /************************************************************************/
1522 : /* ScanForMapProjection() */
1523 : /* */
1524 : /* Try to find a map projection record, and read corner points */
1525 : /* from it. This has only been tested with ERS products. */
1526 : /************************************************************************/
1527 :
1528 2 : int SAR_CEOSDataset::ScanForMapProjection()
1529 :
1530 : {
1531 : /* -------------------------------------------------------------------- */
1532 : /* Find record, and try to determine if it has useful GCPs. */
1533 : /* -------------------------------------------------------------------- */
1534 :
1535 : CeosRecord_t *record =
1536 2 : FindCeosRecord(sVolume.RecordList, LEADER_MAP_PROJ_RECORD_TC,
1537 : CEOS_LEADER_FILE, -1, -1);
1538 :
1539 2 : int gcp_ordering_mode = CEOS_STD_MAPREC_GCP_ORDER;
1540 : /* JERS from Japan */
1541 2 : if (record == nullptr)
1542 : record =
1543 2 : FindCeosRecord(sVolume.RecordList, LEADER_MAP_PROJ_RECORD_JERS_TC,
1544 : CEOS_LEADER_FILE, -1, -1);
1545 :
1546 2 : if (record == nullptr)
1547 : {
1548 : record =
1549 2 : FindCeosRecord(sVolume.RecordList, LEADER_MAP_PROJ_RECORD_ASF_TC,
1550 : CEOS_LEADER_FILE, -1, -1);
1551 2 : gcp_ordering_mode = CEOS_ASF_MAPREC_GCP_ORDER;
1552 : }
1553 2 : if (record == nullptr)
1554 : {
1555 2 : record = FindCeosRecord(sVolume.RecordList, LEADER_FACILITY_ASF_TC,
1556 : CEOS_LEADER_FILE, -1, -1);
1557 2 : gcp_ordering_mode = CEOS_ASF_FACREC_GCP_ORDER;
1558 : }
1559 :
1560 2 : if (record == nullptr)
1561 0 : return FALSE;
1562 :
1563 : char szField[100];
1564 2 : memset(szField, 0, 17);
1565 2 : GetCeosField(record, 29, "A16", szField);
1566 :
1567 2 : int GCPFieldSize = 16;
1568 2 : int GCPOffset = 1073;
1569 :
1570 2 : if (!STARTS_WITH_CI(szField, "Slant Range") &&
1571 2 : !STARTS_WITH_CI(szField, "Ground Range") &&
1572 2 : !STARTS_WITH_CI(szField, "GEOCODED"))
1573 : {
1574 : /* detect ASF map projection record */
1575 2 : GetCeosField(record, 1079, "A7", szField);
1576 2 : if (!STARTS_WITH_CI(szField, "Slant") &&
1577 2 : !STARTS_WITH_CI(szField, "Ground"))
1578 : {
1579 0 : return FALSE;
1580 : }
1581 : else
1582 : {
1583 2 : GCPFieldSize = 17;
1584 2 : GCPOffset = 157;
1585 : }
1586 : }
1587 :
1588 : char FieldSize[4];
1589 2 : snprintf(FieldSize, sizeof(FieldSize), "A%d", GCPFieldSize);
1590 :
1591 2 : GetCeosField(record, GCPOffset, FieldSize, szField);
1592 2 : if (STARTS_WITH_CI(szField, " "))
1593 0 : return FALSE;
1594 :
1595 : /* -------------------------------------------------------------------- */
1596 : /* Read corner points. */
1597 : /* -------------------------------------------------------------------- */
1598 2 : nGCPCount = 4;
1599 2 : pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP), nGCPCount);
1600 :
1601 2 : GDALInitGCPs(nGCPCount, pasGCPList);
1602 :
1603 10 : for (int i = 0; i < nGCPCount; i++)
1604 : {
1605 : char szId[32];
1606 :
1607 8 : snprintf(szId, sizeof(szId), "%d", i + 1);
1608 8 : CPLFree(pasGCPList[i].pszId);
1609 8 : pasGCPList[i].pszId = CPLStrdup(szId);
1610 :
1611 8 : GetCeosField(record, GCPOffset + (GCPFieldSize * 2) * i, FieldSize,
1612 : szField);
1613 8 : pasGCPList[i].dfGCPY = CPLAtof(szField);
1614 8 : GetCeosField(record, GCPOffset + GCPFieldSize + (GCPFieldSize * 2) * i,
1615 : FieldSize, szField);
1616 8 : pasGCPList[i].dfGCPX = CPLAtof(szField);
1617 8 : pasGCPList[i].dfGCPZ = 0.0;
1618 : }
1619 :
1620 : /* Map Projection Record has the order UL UR LR LL
1621 : ASF Facility Data Record has the order UL,LL,UR,LR
1622 : ASF Map Projection Record has the order LL, LR, UR, UL */
1623 :
1624 2 : pasGCPList[0].dfGCPLine = 0.5;
1625 2 : pasGCPList[0].dfGCPPixel = 0.5;
1626 :
1627 2 : switch (gcp_ordering_mode)
1628 : {
1629 2 : case CEOS_ASF_FACREC_GCP_ORDER:
1630 2 : pasGCPList[1].dfGCPLine = nRasterYSize - 0.5;
1631 2 : pasGCPList[1].dfGCPPixel = 0.5;
1632 :
1633 2 : pasGCPList[2].dfGCPLine = 0.5;
1634 2 : pasGCPList[2].dfGCPPixel = nRasterXSize - 0.5;
1635 :
1636 2 : pasGCPList[3].dfGCPLine = nRasterYSize - 0.5;
1637 2 : pasGCPList[3].dfGCPPixel = nRasterXSize - 0.5;
1638 2 : break;
1639 0 : case CEOS_STD_MAPREC_GCP_ORDER:
1640 0 : pasGCPList[1].dfGCPLine = 0.5;
1641 0 : pasGCPList[1].dfGCPPixel = nRasterXSize - 0.5;
1642 :
1643 0 : pasGCPList[2].dfGCPLine = nRasterYSize - 0.5;
1644 0 : pasGCPList[2].dfGCPPixel = nRasterXSize - 0.5;
1645 :
1646 0 : pasGCPList[3].dfGCPLine = nRasterYSize - 0.5;
1647 0 : pasGCPList[3].dfGCPPixel = 0.5;
1648 0 : break;
1649 0 : case CEOS_ASF_MAPREC_GCP_ORDER:
1650 0 : pasGCPList[0].dfGCPLine = nRasterYSize - 0.5;
1651 0 : pasGCPList[0].dfGCPPixel = 0.5;
1652 :
1653 0 : pasGCPList[1].dfGCPLine = nRasterYSize - 0.5;
1654 0 : pasGCPList[1].dfGCPPixel = nRasterXSize - 0.5;
1655 :
1656 0 : pasGCPList[2].dfGCPLine = 0.5;
1657 0 : pasGCPList[2].dfGCPPixel = nRasterXSize - 0.5;
1658 :
1659 0 : pasGCPList[3].dfGCPLine = 0.5;
1660 0 : pasGCPList[3].dfGCPPixel = 0.5;
1661 0 : break;
1662 : }
1663 :
1664 2 : return TRUE;
1665 : }
1666 :
1667 : /************************************************************************/
1668 : /* ScanForGCPs() */
1669 : /************************************************************************/
1670 :
1671 4 : void SAR_CEOSDataset::ScanForGCPs()
1672 :
1673 : {
1674 : /* -------------------------------------------------------------------- */
1675 : /* Do we have a standard 180 bytes of prefix data (192 bytes */
1676 : /* including the record marker information)? If not, it is */
1677 : /* unlikely that the GCPs are available. */
1678 : /* -------------------------------------------------------------------- */
1679 4 : if (sVolume.ImageDesc.ImageDataStart < 192)
1680 : {
1681 0 : ScanForMapProjection();
1682 0 : return;
1683 : }
1684 :
1685 : /* ASF L1 products do not have valid data
1686 : in the lat/long first/mid/last fields */
1687 4 : const char *pszValue = GetMetadataItem("CEOS_FACILITY");
1688 4 : if ((pszValue != nullptr) && (strncmp(pszValue, "ASF", 3) == 0))
1689 : {
1690 2 : ScanForMapProjection();
1691 2 : return;
1692 : }
1693 :
1694 : /* -------------------------------------------------------------------- */
1695 : /* Just sample fix scanlines through the image for GCPs, to */
1696 : /* return 15 GCPs. That is an adequate coverage for most */
1697 : /* purposes. A GCP is collected from the beginning, middle and */
1698 : /* end of each scanline. */
1699 : /* -------------------------------------------------------------------- */
1700 2 : nGCPCount = 0;
1701 2 : int nGCPMax = 15;
1702 2 : pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP), nGCPMax);
1703 :
1704 2 : int nStep = (GetRasterYSize() - 1) / (nGCPMax / 3 - 1);
1705 4 : for (int iScanline = 0; iScanline < GetRasterYSize(); iScanline += nStep)
1706 : {
1707 4 : if (nGCPCount > nGCPMax - 3)
1708 2 : break;
1709 :
1710 : int nFileOffset;
1711 4 : CalcCeosSARImageFilePosition(&sVolume, 1, iScanline + 1, nullptr,
1712 : &nFileOffset);
1713 :
1714 : GInt32 anRecord[192 / 4];
1715 8 : if (VSIFSeekL(fpImage, nFileOffset, SEEK_SET) != 0 ||
1716 4 : VSIFReadL(anRecord, 1, 192, fpImage) != 192)
1717 2 : break;
1718 :
1719 : /* loop over first, middle and last pixel gcps */
1720 :
1721 8 : for (int iGCP = 0; iGCP < 3; iGCP++)
1722 : {
1723 6 : const int nLat = CPL_MSBWORD32(anRecord[132 / 4 + iGCP]);
1724 6 : const int nLong = CPL_MSBWORD32(anRecord[144 / 4 + iGCP]);
1725 :
1726 6 : if (nLat != 0 || nLong != 0)
1727 : {
1728 6 : GDALInitGCPs(1, pasGCPList + nGCPCount);
1729 :
1730 6 : CPLFree(pasGCPList[nGCPCount].pszId);
1731 :
1732 : char szId[32];
1733 6 : snprintf(szId, sizeof(szId), "%d", nGCPCount + 1);
1734 6 : pasGCPList[nGCPCount].pszId = CPLStrdup(szId);
1735 :
1736 6 : pasGCPList[nGCPCount].dfGCPX = nLong / 1000000.0;
1737 6 : pasGCPList[nGCPCount].dfGCPY = nLat / 1000000.0;
1738 6 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
1739 :
1740 6 : pasGCPList[nGCPCount].dfGCPLine = iScanline + 0.5;
1741 :
1742 6 : if (iGCP == 0)
1743 2 : pasGCPList[nGCPCount].dfGCPPixel = 0.5;
1744 4 : else if (iGCP == 1)
1745 2 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize() / 2.0;
1746 : else
1747 2 : pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize() - 0.5;
1748 :
1749 6 : nGCPCount++;
1750 : }
1751 : }
1752 : }
1753 : /* If general GCP's were not found, look for Map Projection (e.g. JERS) */
1754 2 : if (nGCPCount == 0)
1755 : {
1756 0 : CPLFree(pasGCPList);
1757 0 : pasGCPList = nullptr;
1758 0 : ScanForMapProjection();
1759 0 : return;
1760 : }
1761 : }
1762 :
1763 : /************************************************************************/
1764 : /* Open() */
1765 : /************************************************************************/
1766 :
1767 35868 : GDALDataset *SAR_CEOSDataset::Open(GDALOpenInfo *poOpenInfo)
1768 :
1769 : {
1770 : /* -------------------------------------------------------------------- */
1771 : /* Does this appear to be a valid ceos leader record? */
1772 : /* -------------------------------------------------------------------- */
1773 35868 : if (poOpenInfo->nHeaderBytes < CEOS_HEADER_LENGTH ||
1774 7254 : poOpenInfo->fpL == nullptr)
1775 28634 : return nullptr;
1776 :
1777 7234 : if ((poOpenInfo->pabyHeader[4] != 0x3f &&
1778 7226 : poOpenInfo->pabyHeader[4] != 0x32) ||
1779 12 : poOpenInfo->pabyHeader[5] != 0xc0 ||
1780 7 : poOpenInfo->pabyHeader[6] != 0x12 || poOpenInfo->pabyHeader[7] != 0x12)
1781 7227 : return nullptr;
1782 :
1783 : // some products (#1862) have byte swapped record length/number
1784 : // values and will blow stuff up -- explicitly ignore if record index
1785 : // value appears to be little endian.
1786 7 : if (poOpenInfo->pabyHeader[0] != 0)
1787 3 : return nullptr;
1788 :
1789 : /* -------------------------------------------------------------------- */
1790 : /* Confirm the requested access is supported. */
1791 : /* -------------------------------------------------------------------- */
1792 4 : if (poOpenInfo->eAccess == GA_Update)
1793 : {
1794 0 : CPLError(
1795 : CE_Failure, CPLE_NotSupported,
1796 : "The SAR_CEOS driver does not support update access to existing"
1797 : " datasets.\n");
1798 0 : return nullptr;
1799 : }
1800 :
1801 : /* -------------------------------------------------------------------- */
1802 : /* Create a corresponding GDALDataset. */
1803 : /* -------------------------------------------------------------------- */
1804 :
1805 8 : auto poDS = std::make_unique<SAR_CEOSDataset>();
1806 4 : std::swap(poDS->fpImage, poOpenInfo->fpL);
1807 :
1808 4 : CeosSARVolume_t *psVolume = &(poDS->sVolume);
1809 4 : InitCeosSARVolume(psVolume, 0);
1810 :
1811 : /* -------------------------------------------------------------------- */
1812 : /* Try to read the current file as an imagery file. */
1813 : /* -------------------------------------------------------------------- */
1814 :
1815 4 : psVolume->ImagryOptionsFile = TRUE;
1816 4 : if (ProcessData(poDS->fpImage, CEOS_IMAGRY_OPT_FILE, psVolume, 4,
1817 4 : VSI_L_OFFSET_MAX) != CE_None)
1818 : {
1819 0 : return nullptr;
1820 : }
1821 :
1822 : /* -------------------------------------------------------------------- */
1823 : /* Try the various filenames. */
1824 : /* -------------------------------------------------------------------- */
1825 4 : char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
1826 4 : char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
1827 4 : char *pszExtension = CPLStrdup(CPLGetExtension(poOpenInfo->pszFilename));
1828 :
1829 : int nBand;
1830 4 : if (strlen(pszBasename) > 4)
1831 4 : nBand = atoi(pszBasename + 4);
1832 : else
1833 0 : nBand = 0;
1834 :
1835 24 : for (int iFile = 0; iFile < 5; iFile++)
1836 : {
1837 : /* skip image file ... we already did it */
1838 20 : if (iFile == 2)
1839 4 : continue;
1840 :
1841 16 : int e = 0;
1842 222 : while (CeosExtension[e][iFile] != nullptr)
1843 : {
1844 208 : char *pszFilename = nullptr;
1845 :
1846 : /* build filename */
1847 208 : if (EQUAL(CeosExtension[e][5], "base"))
1848 : {
1849 : char szMadeBasename[32];
1850 :
1851 48 : snprintf(szMadeBasename, sizeof(szMadeBasename),
1852 48 : CeosExtension[e][iFile], nBand);
1853 48 : pszFilename = CPLStrdup(
1854 : CPLFormFilename(pszPath, szMadeBasename, pszExtension));
1855 : }
1856 160 : else if (EQUAL(CeosExtension[e][5], "ext"))
1857 : {
1858 128 : pszFilename = CPLStrdup(CPLFormFilename(
1859 128 : pszPath, pszBasename, CeosExtension[e][iFile]));
1860 : }
1861 32 : else if (EQUAL(CeosExtension[e][5], "whole"))
1862 : {
1863 16 : pszFilename = CPLStrdup(
1864 16 : CPLFormFilename(pszPath, CeosExtension[e][iFile], ""));
1865 : }
1866 :
1867 : // This is for SAR SLC as per the SAR Toolbox (from ASF).
1868 16 : else if (EQUAL(CeosExtension[e][5], "ext2"))
1869 : {
1870 : char szThisExtension[32];
1871 :
1872 16 : if (strlen(pszExtension) > 3)
1873 0 : snprintf(szThisExtension, sizeof(szThisExtension), "%s%s",
1874 0 : CeosExtension[e][iFile], pszExtension + 3);
1875 : else
1876 16 : snprintf(szThisExtension, sizeof(szThisExtension), "%s",
1877 16 : CeosExtension[e][iFile]);
1878 :
1879 16 : pszFilename = CPLStrdup(
1880 : CPLFormFilename(pszPath, pszBasename, szThisExtension));
1881 : }
1882 :
1883 208 : CPLAssert(pszFilename != nullptr);
1884 208 : if (pszFilename == nullptr)
1885 0 : return nullptr;
1886 :
1887 : /* try to open */
1888 208 : VSILFILE *process_fp = VSIFOpenL(pszFilename, "rb");
1889 :
1890 : /* try upper case */
1891 208 : if (process_fp == nullptr)
1892 : {
1893 3312 : for (int i = static_cast<int>(strlen(pszFilename)) - 1;
1894 3312 : i >= 0 && pszFilename[i] != '/' && pszFilename[i] != '\\';
1895 : i--)
1896 : {
1897 3106 : if (pszFilename[i] >= 'a' && pszFilename[i] <= 'z')
1898 1480 : pszFilename[i] = pszFilename[i] - 'a' + 'A';
1899 : }
1900 :
1901 206 : process_fp = VSIFOpenL(pszFilename, "rb");
1902 : }
1903 :
1904 208 : if (process_fp != nullptr)
1905 : {
1906 2 : CPLDebug("CEOS", "Opened %s.\n", pszFilename);
1907 :
1908 4 : poDS->papszExtraFiles =
1909 2 : CSLAddString(poDS->papszExtraFiles, pszFilename);
1910 :
1911 2 : CPL_IGNORE_RET_VAL(VSIFSeekL(process_fp, 0, SEEK_END));
1912 2 : if (ProcessData(process_fp, iFile, psVolume, -1,
1913 2 : VSIFTellL(process_fp)) == 0)
1914 : {
1915 2 : switch (iFile)
1916 : {
1917 0 : case 0:
1918 0 : psVolume->VolumeDirectoryFile = TRUE;
1919 0 : break;
1920 2 : case 1:
1921 2 : psVolume->SARLeaderFile = TRUE;
1922 2 : break;
1923 0 : case 3:
1924 0 : psVolume->SARTrailerFile = TRUE;
1925 0 : break;
1926 0 : case 4:
1927 0 : psVolume->NullVolumeDirectoryFile = TRUE;
1928 0 : break;
1929 : }
1930 :
1931 2 : CPL_IGNORE_RET_VAL(VSIFCloseL(process_fp));
1932 2 : CPLFree(pszFilename);
1933 2 : break; /* Exit the while loop, we have this data type*/
1934 : }
1935 :
1936 0 : CPL_IGNORE_RET_VAL(VSIFCloseL(process_fp));
1937 : }
1938 :
1939 206 : CPLFree(pszFilename);
1940 :
1941 206 : e++;
1942 : }
1943 : }
1944 :
1945 4 : CPLFree(pszPath);
1946 4 : CPLFree(pszBasename);
1947 4 : CPLFree(pszExtension);
1948 :
1949 : /* -------------------------------------------------------------------- */
1950 : /* Check that we have an image description. */
1951 : /* -------------------------------------------------------------------- */
1952 4 : GetCeosSARImageDesc(psVolume);
1953 4 : struct CeosSARImageDesc *psImageDesc = &(psVolume->ImageDesc);
1954 4 : if (!psImageDesc->ImageDescValid)
1955 : {
1956 0 : CPLDebug("CEOS",
1957 : "Unable to extract CEOS image description\n"
1958 : "from %s.",
1959 : poOpenInfo->pszFilename);
1960 :
1961 0 : return nullptr;
1962 : }
1963 :
1964 : /* -------------------------------------------------------------------- */
1965 : /* Establish image type. */
1966 : /* -------------------------------------------------------------------- */
1967 : GDALDataType eType;
1968 :
1969 4 : switch (psImageDesc->DataType)
1970 : {
1971 2 : case CEOS_TYP_CHAR:
1972 : case CEOS_TYP_UCHAR:
1973 2 : eType = GDT_Byte;
1974 2 : break;
1975 :
1976 0 : case CEOS_TYP_SHORT:
1977 0 : eType = GDT_Int16;
1978 0 : break;
1979 :
1980 0 : case CEOS_TYP_COMPLEX_SHORT:
1981 : case CEOS_TYP_PALSAR_COMPLEX_SHORT:
1982 0 : eType = GDT_CInt16;
1983 0 : break;
1984 :
1985 2 : case CEOS_TYP_USHORT:
1986 2 : eType = GDT_UInt16;
1987 2 : break;
1988 :
1989 0 : case CEOS_TYP_LONG:
1990 0 : eType = GDT_Int32;
1991 0 : break;
1992 :
1993 0 : case CEOS_TYP_ULONG:
1994 0 : eType = GDT_UInt32;
1995 0 : break;
1996 :
1997 0 : case CEOS_TYP_FLOAT:
1998 0 : eType = GDT_Float32;
1999 0 : break;
2000 :
2001 0 : case CEOS_TYP_DOUBLE:
2002 0 : eType = GDT_Float64;
2003 0 : break;
2004 :
2005 0 : case CEOS_TYP_COMPLEX_FLOAT:
2006 : case CEOS_TYP_CCP_COMPLEX_FLOAT:
2007 0 : eType = GDT_CFloat32;
2008 0 : break;
2009 :
2010 0 : default:
2011 0 : CPLError(CE_Failure, CPLE_AppDefined,
2012 : "Unsupported CEOS image data type %d.\n",
2013 : psImageDesc->DataType);
2014 0 : return nullptr;
2015 : }
2016 :
2017 : /* -------------------------------------------------------------------- */
2018 : /* Capture some information from the file that is of interest. */
2019 : /* -------------------------------------------------------------------- */
2020 8 : poDS->nRasterXSize = psImageDesc->PixelsPerLine +
2021 4 : psImageDesc->LeftBorderPixels +
2022 4 : psImageDesc->RightBorderPixels;
2023 4 : poDS->nRasterYSize = psImageDesc->Lines;
2024 :
2025 : /* -------------------------------------------------------------------- */
2026 : /* Special case for compressed cross products. */
2027 : /* -------------------------------------------------------------------- */
2028 4 : if (psImageDesc->DataType == CEOS_TYP_CCP_COMPLEX_FLOAT)
2029 : {
2030 0 : for (int iBand = 0; iBand < psImageDesc->NumChannels; iBand++)
2031 : {
2032 0 : poDS->SetBand(
2033 0 : poDS->nBands + 1,
2034 0 : new CCPRasterBand(poDS.get(), poDS->nBands + 1, eType));
2035 : }
2036 :
2037 : /* mark this as a Scattering Matrix product */
2038 0 : if (poDS->GetRasterCount() == 4)
2039 : {
2040 0 : poDS->SetMetadataItem("MATRIX_REPRESENTATION", "SCATTERING");
2041 : }
2042 : }
2043 :
2044 : /* -------------------------------------------------------------------- */
2045 : /* Special case for PALSAR data. */
2046 : /* -------------------------------------------------------------------- */
2047 4 : else if (psImageDesc->DataType == CEOS_TYP_PALSAR_COMPLEX_SHORT)
2048 : {
2049 0 : for (int iBand = 0; iBand < psImageDesc->NumChannels; iBand++)
2050 : {
2051 0 : poDS->SetBand(poDS->nBands + 1,
2052 0 : new PALSARRasterBand(poDS.get(), poDS->nBands + 1));
2053 : }
2054 :
2055 : /* mark this as a Symmetrized Covariance product if appropriate */
2056 0 : if (poDS->GetRasterCount() == 6)
2057 : {
2058 0 : poDS->SetMetadataItem("MATRIX_REPRESENTATION",
2059 0 : "SYMMETRIZED_COVARIANCE");
2060 : }
2061 : }
2062 :
2063 : /* -------------------------------------------------------------------- */
2064 : /* Roll our own ... */
2065 : /* -------------------------------------------------------------------- */
2066 4 : else if (psImageDesc->RecordsPerLine > 1 ||
2067 4 : psImageDesc->DataType == CEOS_TYP_CHAR ||
2068 4 : psImageDesc->DataType == CEOS_TYP_LONG ||
2069 4 : psImageDesc->DataType == CEOS_TYP_ULONG ||
2070 4 : psImageDesc->DataType == CEOS_TYP_DOUBLE)
2071 : {
2072 0 : for (int iBand = 0; iBand < psImageDesc->NumChannels; iBand++)
2073 : {
2074 0 : poDS->SetBand(
2075 0 : poDS->nBands + 1,
2076 0 : new SAR_CEOSRasterBand(poDS.get(), poDS->nBands + 1, eType));
2077 0 : }
2078 : }
2079 :
2080 : /* -------------------------------------------------------------------- */
2081 : /* Use raw services for well behaved files. */
2082 : /* -------------------------------------------------------------------- */
2083 : else
2084 : {
2085 : int StartData;
2086 4 : CalcCeosSARImageFilePosition(psVolume, 1, 1, nullptr, &StartData);
2087 :
2088 : /*StartData += psImageDesc->ImageDataStart; */
2089 :
2090 : int nLineSize, nLineSize2;
2091 4 : CalcCeosSARImageFilePosition(psVolume, 1, 1, nullptr, &nLineSize);
2092 4 : CalcCeosSARImageFilePosition(psVolume, 1, 2, nullptr, &nLineSize2);
2093 :
2094 4 : nLineSize = nLineSize2 - nLineSize;
2095 :
2096 8 : for (int iBand = 0; iBand < psImageDesc->NumChannels; iBand++)
2097 : {
2098 : int nStartData, nPixelOffset, nLineOffset;
2099 :
2100 4 : if (psImageDesc->ChannelInterleaving == CEOS_IL_PIXEL)
2101 : {
2102 0 : CalcCeosSARImageFilePosition(psVolume, 1, 1, nullptr,
2103 : &nStartData);
2104 :
2105 0 : nStartData += psImageDesc->ImageDataStart;
2106 0 : nStartData += psImageDesc->BytesPerPixel * iBand;
2107 :
2108 0 : nPixelOffset =
2109 0 : psImageDesc->BytesPerPixel * psImageDesc->NumChannels;
2110 0 : nLineOffset = nLineSize;
2111 : }
2112 4 : else if (psImageDesc->ChannelInterleaving == CEOS_IL_LINE)
2113 : {
2114 0 : CalcCeosSARImageFilePosition(psVolume, iBand + 1, 1, nullptr,
2115 : &nStartData);
2116 :
2117 0 : nStartData += psImageDesc->ImageDataStart;
2118 0 : nPixelOffset = psImageDesc->BytesPerPixel;
2119 0 : nLineOffset = nLineSize * psImageDesc->NumChannels;
2120 : }
2121 4 : else if (psImageDesc->ChannelInterleaving == CEOS_IL_BAND)
2122 : {
2123 4 : CalcCeosSARImageFilePosition(psVolume, iBand + 1, 1, nullptr,
2124 : &nStartData);
2125 :
2126 4 : nStartData += psImageDesc->ImageDataStart;
2127 4 : nPixelOffset = psImageDesc->BytesPerPixel;
2128 4 : nLineOffset = nLineSize;
2129 : }
2130 : else
2131 : {
2132 0 : CPLAssert(false);
2133 0 : return nullptr;
2134 : }
2135 :
2136 : auto poBand = RawRasterBand::Create(
2137 12 : poDS.get(), poDS->nBands + 1, poDS->fpImage, nStartData,
2138 : nPixelOffset, nLineOffset, eType,
2139 : RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN,
2140 4 : RawRasterBand::OwnFP::NO);
2141 4 : if (!poBand)
2142 0 : return nullptr;
2143 4 : poDS->SetBand(poDS->nBands + 1, std::move(poBand));
2144 : }
2145 : }
2146 :
2147 : /* -------------------------------------------------------------------- */
2148 : /* Collect metadata. */
2149 : /* -------------------------------------------------------------------- */
2150 4 : poDS->ScanForMetadata();
2151 :
2152 : /* -------------------------------------------------------------------- */
2153 : /* Check for GCPs. */
2154 : /* -------------------------------------------------------------------- */
2155 4 : poDS->ScanForGCPs();
2156 :
2157 : /* -------------------------------------------------------------------- */
2158 : /* Initialize any PAM information. */
2159 : /* -------------------------------------------------------------------- */
2160 4 : poDS->SetDescription(poOpenInfo->pszFilename);
2161 4 : poDS->TryLoadXML();
2162 :
2163 : /* -------------------------------------------------------------------- */
2164 : /* Open overviews. */
2165 : /* -------------------------------------------------------------------- */
2166 4 : poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
2167 :
2168 4 : return poDS.release();
2169 : }
2170 :
2171 : /************************************************************************/
2172 : /* ProcessData() */
2173 : /************************************************************************/
2174 6 : static int ProcessData(VSILFILE *fp, int fileid, CeosSARVolume_t *sar,
2175 : int max_records, vsi_l_offset max_bytes)
2176 :
2177 : {
2178 : unsigned char temp_buffer[CEOS_HEADER_LENGTH];
2179 6 : unsigned char *temp_body = nullptr;
2180 6 : int start = 0;
2181 6 : int CurrentBodyLength = 0;
2182 6 : int CurrentType = 0;
2183 6 : int CurrentSequence = 0;
2184 6 : int iThisRecord = 0;
2185 :
2186 42 : while (max_records != 0 && max_bytes != 0)
2187 : {
2188 36 : iThisRecord++;
2189 :
2190 72 : if (VSIFSeekL(fp, start, SEEK_SET) != 0 ||
2191 36 : VSIFReadL(temp_buffer, 1, CEOS_HEADER_LENGTH, fp) !=
2192 : CEOS_HEADER_LENGTH)
2193 : {
2194 0 : CPLError(CE_Failure, CPLE_AppDefined,
2195 : "Corrupt CEOS File - cannot read record %d.", iThisRecord);
2196 0 : CPLFree(temp_body);
2197 0 : return CE_Failure;
2198 : }
2199 36 : CeosRecord_t *record = (CeosRecord_t *)CPLMalloc(sizeof(CeosRecord_t));
2200 36 : record->Length = DetermineCeosRecordBodyLength(temp_buffer);
2201 :
2202 36 : CeosToNative(&(record->Sequence), temp_buffer, 4, 4);
2203 :
2204 36 : if (iThisRecord != record->Sequence)
2205 : {
2206 0 : if (fileid == CEOS_IMAGRY_OPT_FILE && iThisRecord == 2)
2207 : {
2208 0 : CPLDebug("SAR_CEOS",
2209 : "Ignoring CEOS file with wrong second record sequence "
2210 : "number - likely it has padded records.");
2211 0 : CPLFree(record);
2212 0 : CPLFree(temp_body);
2213 0 : return CE_Warning;
2214 : }
2215 : else
2216 : {
2217 0 : CPLError(CE_Failure, CPLE_AppDefined,
2218 : "Corrupt CEOS File - got record seq# %d instead of "
2219 : "the expected %d.",
2220 : record->Sequence, iThisRecord);
2221 0 : CPLFree(record);
2222 0 : CPLFree(temp_body);
2223 0 : return CE_Failure;
2224 : }
2225 : }
2226 :
2227 36 : if (record->Length <= CEOS_HEADER_LENGTH)
2228 : {
2229 0 : CPLError(CE_Failure, CPLE_AppDefined,
2230 : "Corrupt CEOS File - cannot read record %d.", iThisRecord);
2231 0 : CPLFree(record);
2232 0 : CPLFree(temp_body);
2233 0 : return CE_Failure;
2234 : }
2235 :
2236 36 : if (record->Length > CurrentBodyLength)
2237 : {
2238 : unsigned char *temp_body_new =
2239 14 : (unsigned char *)VSI_REALLOC_VERBOSE(temp_body, record->Length);
2240 14 : if (temp_body_new == nullptr)
2241 : {
2242 0 : CPLFree(record);
2243 0 : CPLFree(temp_body);
2244 0 : return CE_Failure;
2245 : }
2246 14 : temp_body = temp_body_new;
2247 14 : CurrentBodyLength = record->Length;
2248 : }
2249 :
2250 36 : int nToRead = record->Length - CEOS_HEADER_LENGTH;
2251 36 : if ((int)VSIFReadL(temp_body, 1, nToRead, fp) != nToRead)
2252 : {
2253 0 : CPLError(CE_Failure, CPLE_AppDefined,
2254 : "Corrupt CEOS File - cannot read record %d.", iThisRecord);
2255 0 : CPLFree(record);
2256 0 : CPLFree(temp_body);
2257 0 : return CE_Failure;
2258 : }
2259 :
2260 36 : InitCeosRecordWithHeader(record, temp_buffer, temp_body);
2261 36 : if (record->Length == 0)
2262 : {
2263 0 : CPLError(CE_Failure, CPLE_AppDefined,
2264 : "Corrupt CEOS File - invalid record %d.", iThisRecord);
2265 0 : CPLFree(record);
2266 0 : CPLFree(temp_body);
2267 0 : return CE_Failure;
2268 : }
2269 :
2270 36 : if (CurrentType == record->TypeCode.Int32Code)
2271 10 : record->Subsequence = ++CurrentSequence;
2272 : else
2273 : {
2274 26 : CurrentType = record->TypeCode.Int32Code;
2275 26 : record->Subsequence = 0;
2276 26 : CurrentSequence = 0;
2277 : }
2278 :
2279 36 : record->FileId = fileid;
2280 :
2281 36 : Link_t *TheLink = ceos2CreateLink(record);
2282 :
2283 36 : if (sar->RecordList == nullptr)
2284 4 : sar->RecordList = TheLink;
2285 : else
2286 32 : sar->RecordList = InsertLink(sar->RecordList, TheLink);
2287 :
2288 36 : start += record->Length;
2289 :
2290 36 : if (max_records > 0)
2291 16 : max_records--;
2292 36 : if (max_bytes > 0)
2293 : {
2294 36 : if ((vsi_l_offset)record->Length <= max_bytes)
2295 36 : max_bytes -= record->Length;
2296 : else
2297 : {
2298 0 : CPLDebug("SAR_CEOS",
2299 : "Partial record found. %d > " CPL_FRMT_GUIB,
2300 : record->Length, max_bytes);
2301 0 : max_bytes = 0;
2302 : }
2303 : }
2304 : }
2305 :
2306 6 : CPLFree(temp_body);
2307 :
2308 6 : return CE_None;
2309 : }
2310 :
2311 : /************************************************************************/
2312 : /* GDALRegister_SAR_CEOS() */
2313 : /************************************************************************/
2314 :
2315 1595 : void GDALRegister_SAR_CEOS()
2316 :
2317 : {
2318 1595 : if (GDALGetDriverByName("SAR_CEOS") != nullptr)
2319 302 : return;
2320 :
2321 1293 : GDALDriver *poDriver = new GDALDriver();
2322 :
2323 1293 : poDriver->SetDescription("SAR_CEOS");
2324 1293 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
2325 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "CEOS SAR Image");
2326 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
2327 1293 : "drivers/raster/sar_ceos.html");
2328 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
2329 :
2330 1293 : poDriver->pfnOpen = SAR_CEOSDataset::Open;
2331 :
2332 1293 : GetGDALDriverManager()->RegisterDriver(poDriver);
2333 : }
2334 :
2335 : /************************************************************************/
2336 : /* GetFileList() */
2337 : /************************************************************************/
2338 :
2339 2 : char **SAR_CEOSDataset::GetFileList()
2340 :
2341 : {
2342 2 : char **papszFileList = GDALPamDataset::GetFileList();
2343 :
2344 2 : papszFileList = CSLInsertStrings(papszFileList, -1, papszExtraFiles);
2345 :
2346 2 : return papszFileList;
2347 : }
|