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