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