1 : /******************************************************************************
2 : * $Id: envisatdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Project: APP ENVISAT Support
5 : * Purpose: Reader for ENVISAT format image data.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001, 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 "rawdataset.h"
31 : #include "cpl_string.h"
32 : #include "ogr_srs_api.h"
33 :
34 : CPL_CVSID("$Id: envisatdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
35 :
36 : CPL_C_START
37 : #include "EnvisatFile.h"
38 : CPL_C_END
39 :
40 : CPL_C_START
41 : void GDALRegister_Envisat(void);
42 : CPL_C_END
43 :
44 : /************************************************************************/
45 : /* ==================================================================== */
46 : /* EnvisatDataset */
47 : /* ==================================================================== */
48 : /************************************************************************/
49 :
50 : class EnvisatDataset : public RawDataset
51 : {
52 : EnvisatFile *hEnvisatFile;
53 : FILE *fpImage;
54 :
55 : int nGCPCount;
56 : GDAL_GCP *pasGCPList;
57 :
58 : char **papszTempMD;
59 :
60 : void ScanForGCPs_ASAR();
61 : void ScanForGCPs_MERIS();
62 :
63 : void CollectMetadata( EnvisatFile_HeaderFlag );
64 : void CollectDSDMetadata();
65 :
66 : public:
67 : EnvisatDataset();
68 : ~EnvisatDataset();
69 :
70 : virtual int GetGCPCount();
71 : virtual const char *GetGCPProjection();
72 : virtual const GDAL_GCP *GetGCPs();
73 : virtual char **GetMetadata( const char * pszDomain );
74 :
75 :
76 : static GDALDataset *Open( GDALOpenInfo * );
77 : };
78 :
79 : /************************************************************************/
80 : /* ==================================================================== */
81 : /* EnvisatDataset */
82 : /* ==================================================================== */
83 : /************************************************************************/
84 :
85 : /************************************************************************/
86 : /* EnvisatDataset() */
87 : /************************************************************************/
88 :
89 0 : EnvisatDataset::EnvisatDataset()
90 : {
91 0 : hEnvisatFile = NULL;
92 0 : fpImage = NULL;
93 0 : nGCPCount = 0;
94 0 : pasGCPList = NULL;
95 0 : papszTempMD = NULL;
96 0 : }
97 :
98 : /************************************************************************/
99 : /* ~EnvisatDataset() */
100 : /************************************************************************/
101 :
102 0 : EnvisatDataset::~EnvisatDataset()
103 :
104 : {
105 0 : FlushCache();
106 :
107 0 : if( hEnvisatFile != NULL )
108 0 : EnvisatFile_Close( hEnvisatFile );
109 :
110 0 : if( fpImage != NULL )
111 0 : VSIFClose( fpImage );
112 :
113 0 : if( nGCPCount > 0 )
114 : {
115 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
116 0 : CPLFree( pasGCPList );
117 : }
118 :
119 0 : CSLDestroy( papszTempMD );
120 0 : }
121 :
122 : /************************************************************************/
123 : /* GetGCPCount() */
124 : /************************************************************************/
125 :
126 0 : int EnvisatDataset::GetGCPCount()
127 :
128 : {
129 0 : return nGCPCount;
130 : }
131 :
132 : /************************************************************************/
133 : /* GetGCPProjection() */
134 : /************************************************************************/
135 :
136 0 : const char *EnvisatDataset::GetGCPProjection()
137 :
138 : {
139 0 : if( nGCPCount > 0 )
140 0 : return SRS_WKT_WGS84;
141 : else
142 0 : return "";
143 : }
144 :
145 : /************************************************************************/
146 : /* GetGCP() */
147 : /************************************************************************/
148 :
149 0 : const GDAL_GCP *EnvisatDataset::GetGCPs()
150 :
151 : {
152 0 : return pasGCPList;
153 : }
154 :
155 : /************************************************************************/
156 : /* ScanForGCPs_ASAR() */
157 : /************************************************************************/
158 :
159 0 : void EnvisatDataset::ScanForGCPs_ASAR()
160 :
161 : {
162 : int nDatasetIndex, nNumDSR, nDSRSize, iRecord;
163 :
164 : /* -------------------------------------------------------------------- */
165 : /* Do we have a meaningful geolocation grid? */
166 : /* -------------------------------------------------------------------- */
167 : nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
168 0 : "GEOLOCATION GRID ADS" );
169 0 : if( nDatasetIndex == -1 )
170 0 : return;
171 :
172 0 : if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex,
173 : NULL, NULL, NULL, NULL, NULL,
174 : &nNumDSR, &nDSRSize ) != SUCCESS )
175 0 : return;
176 :
177 0 : if( nNumDSR == 0 || nDSRSize != 521 )
178 0 : return;
179 :
180 : /* -------------------------------------------------------------------- */
181 : /* Collect the first GCP set from each record. */
182 : /* -------------------------------------------------------------------- */
183 : GByte abyRecord[521];
184 0 : int nRange=0, nSample, iGCP;
185 : GUInt32 unValue;
186 :
187 0 : nGCPCount = 0;
188 0 : pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),(nNumDSR+1) * 11);
189 :
190 0 : for( iRecord = 0; iRecord < nNumDSR; iRecord++ )
191 : {
192 0 : if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex,
193 : iRecord, abyRecord ) != SUCCESS )
194 0 : continue;
195 :
196 0 : memcpy( &unValue, abyRecord + 13, 4 );
197 0 : nRange = CPL_MSBWORD32( unValue );
198 :
199 0 : for( iGCP = 0; iGCP < 11; iGCP++ )
200 : {
201 : char szId[128];
202 :
203 0 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
204 :
205 0 : CPLFree( pasGCPList[nGCPCount].pszId );
206 :
207 0 : sprintf( szId, "%d", nGCPCount+1 );
208 0 : pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
209 :
210 0 : memcpy( &unValue, abyRecord + 25 + iGCP*4, 4 );
211 0 : nSample = CPL_MSBWORD32(unValue);
212 :
213 0 : memcpy( &unValue, abyRecord + 25 + 176 + iGCP*4, 4 );
214 0 : pasGCPList[nGCPCount].dfGCPX = ((int)CPL_MSBWORD32(unValue))*0.000001;
215 :
216 0 : memcpy( &unValue, abyRecord + 25 + 132 + iGCP*4, 4 );
217 0 : pasGCPList[nGCPCount].dfGCPY = ((int)CPL_MSBWORD32(unValue))*0.000001;
218 :
219 0 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
220 :
221 0 : pasGCPList[nGCPCount].dfGCPLine = nRange - 0.5;
222 0 : pasGCPList[nGCPCount].dfGCPPixel = nSample - 0.5;
223 :
224 0 : nGCPCount++;
225 : }
226 : }
227 :
228 : /* -------------------------------------------------------------------- */
229 : /* We also collect the bottom GCPs from the last granule. */
230 : /* -------------------------------------------------------------------- */
231 0 : memcpy( &unValue, abyRecord + 17, 4 );
232 0 : nRange = nRange + CPL_MSBWORD32( unValue ) - 1;
233 :
234 0 : for( iGCP = 0; iGCP < 11; iGCP++ )
235 : {
236 : char szId[128];
237 :
238 0 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
239 :
240 0 : CPLFree( pasGCPList[nGCPCount].pszId );
241 :
242 0 : sprintf( szId, "%d", nGCPCount+1 );
243 0 : pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
244 :
245 0 : memcpy( &unValue, abyRecord + 279 + iGCP*4, 4 );
246 0 : nSample = CPL_MSBWORD32(unValue);
247 :
248 0 : memcpy( &unValue, abyRecord + 279 + 176 + iGCP*4, 4 );
249 0 : pasGCPList[nGCPCount].dfGCPX = ((int)CPL_MSBWORD32(unValue))*0.000001;
250 :
251 0 : memcpy( &unValue, abyRecord + 279 + 132 + iGCP*4, 4 );
252 0 : pasGCPList[nGCPCount].dfGCPY = ((int)CPL_MSBWORD32(unValue))*0.000001;
253 :
254 0 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
255 :
256 0 : pasGCPList[nGCPCount].dfGCPLine = nRange - 0.5;
257 0 : pasGCPList[nGCPCount].dfGCPPixel = nSample - 0.5;
258 :
259 0 : nGCPCount++;
260 : }
261 : }
262 :
263 : /************************************************************************/
264 : /* ScanForGCPs_MERIS() */
265 : /************************************************************************/
266 :
267 0 : void EnvisatDataset::ScanForGCPs_MERIS()
268 :
269 : {
270 : int nDatasetIndex, nNumDSR, nDSRSize, iRecord;
271 :
272 : /* -------------------------------------------------------------------- */
273 : /* Do we have a meaningful geolocation grid? Seach for a */
274 : /* DS_TYPE=A and a name containing "geolocation" or "tie */
275 : /* points". */
276 : /* -------------------------------------------------------------------- */
277 : nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
278 0 : "Tie points ADS" );
279 0 : if( nDatasetIndex == -1 )
280 0 : return;
281 :
282 0 : if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex,
283 : NULL, NULL, NULL, NULL, NULL,
284 : &nNumDSR, &nDSRSize ) != SUCCESS )
285 0 : return;
286 :
287 0 : if( nNumDSR == 0 )
288 0 : return;
289 :
290 : /* -------------------------------------------------------------------- */
291 : /* Figure out the tiepoint space, and how many we have. */
292 : /* -------------------------------------------------------------------- */
293 : int nLinesPerTiePoint, nSamplesPerTiePoint;
294 0 : int nTPPerLine, nTPPerColumn = nNumDSR;
295 :
296 0 : if( nNumDSR == 0 )
297 0 : return;
298 :
299 : nLinesPerTiePoint =
300 : EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
301 0 : "LINES_PER_TIE_PT", 0 );
302 : nSamplesPerTiePoint =
303 : EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
304 0 : "SAMPLES_PER_TIE_PT", 0 );
305 :
306 0 : if( nLinesPerTiePoint == 0 || nSamplesPerTiePoint == 0 )
307 0 : return;
308 :
309 : nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1)
310 0 : / nSamplesPerTiePoint;
311 :
312 0 : if( (GetRasterXSize() + nSamplesPerTiePoint - 1)
313 : / nSamplesPerTiePoint != nTPPerColumn )
314 : {
315 : CPLDebug( "EnvisatDataset", "Got %d instead of %d nTPPerColumn.",
316 : (GetRasterXSize()+nSamplesPerTiePoint-1)/nSamplesPerTiePoint,
317 0 : nTPPerColumn );
318 0 : return;
319 : }
320 :
321 0 : if( 50*nTPPerLine + 13 != nDSRSize )
322 : {
323 : CPLDebug( "EnvisatDataset",
324 : "DSRSize=%d instead of expected %d for tiepoints ADS.",
325 0 : nDSRSize, 50*nTPPerLine + 13 );
326 0 : return;
327 : }
328 :
329 : /* -------------------------------------------------------------------- */
330 : /* Collect the first GCP set from each record. */
331 : /* -------------------------------------------------------------------- */
332 0 : GByte *pabyRecord = (GByte *) CPLMalloc(nDSRSize);
333 : int iGCP;
334 : GUInt32 unValue;
335 :
336 0 : nGCPCount = 0;
337 : pasGCPList = (GDAL_GCP *)
338 0 : CPLCalloc(sizeof(GDAL_GCP),nNumDSR * nTPPerLine);
339 :
340 0 : for( iRecord = 0; iRecord < nNumDSR; iRecord++ )
341 : {
342 0 : if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex,
343 : iRecord, pabyRecord ) != SUCCESS )
344 0 : continue;
345 :
346 0 : memcpy( &unValue, pabyRecord + 13, 4 );
347 :
348 0 : for( iGCP = 0; iGCP < nTPPerLine; iGCP++ )
349 : {
350 : char szId[128];
351 :
352 0 : GDALInitGCPs( 1, pasGCPList + nGCPCount );
353 :
354 0 : CPLFree( pasGCPList[nGCPCount].pszId );
355 :
356 0 : sprintf( szId, "%d", nGCPCount+1 );
357 0 : pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
358 :
359 0 : memcpy( &unValue, pabyRecord + 13 + nTPPerLine*4 + iGCP*4, 4 );
360 : pasGCPList[nGCPCount].dfGCPX =
361 0 : ((int)CPL_MSBWORD32(unValue))*0.000001;
362 :
363 0 : memcpy( &unValue, pabyRecord + 13 + iGCP*4, 4 );
364 : pasGCPList[nGCPCount].dfGCPY =
365 0 : ((int)CPL_MSBWORD32(unValue))*0.000001;
366 :
367 0 : pasGCPList[nGCPCount].dfGCPZ = 0.0;
368 :
369 0 : pasGCPList[nGCPCount].dfGCPLine = iRecord*nLinesPerTiePoint + 0.5;
370 0 : pasGCPList[nGCPCount].dfGCPPixel = iGCP*nSamplesPerTiePoint + 0.5;
371 :
372 0 : nGCPCount++;
373 : }
374 : }
375 0 : CPLFree( pabyRecord );
376 : }
377 :
378 : /************************************************************************/
379 : /* GetMetadata() */
380 : /************************************************************************/
381 :
382 0 : char **EnvisatDataset::GetMetadata( const char * pszDomain )
383 :
384 : {
385 0 : if( pszDomain == NULL || !EQUALN(pszDomain,"envisat-ds-",11) )
386 0 : return GDALDataset::GetMetadata( pszDomain );
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* Get the dataset name and record number. */
390 : /* -------------------------------------------------------------------- */
391 : char szDSName[128];
392 0 : int i, nRecord = -1;
393 :
394 0 : strncpy( szDSName, pszDomain+11, sizeof(szDSName) );
395 0 : for( i = 0; i < (int) sizeof(szDSName)-1; i++ )
396 : {
397 0 : if( szDSName[i] == '-' )
398 : {
399 0 : szDSName[i] = '\0';
400 0 : nRecord = atoi(szDSName+1);
401 0 : break;
402 : }
403 : }
404 :
405 0 : if( nRecord == -1 )
406 0 : return NULL;
407 :
408 : /* -------------------------------------------------------------------- */
409 : /* Get the dataset index and info. */
410 : /* -------------------------------------------------------------------- */
411 0 : int nDSIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile, szDSName );
412 : int nDSRSize, nNumDSR;
413 :
414 0 : if( nDSIndex == -1 )
415 0 : return NULL;
416 :
417 : EnvisatFile_GetDatasetInfo( hEnvisatFile, nDSIndex, NULL, NULL, NULL,
418 0 : NULL, NULL, &nNumDSR, &nDSRSize );
419 :
420 0 : if( nDSRSize == -1 || nRecord < 0 || nRecord >= nNumDSR )
421 0 : return NULL;
422 :
423 : /* -------------------------------------------------------------------- */
424 : /* Read the requested record. */
425 : /* -------------------------------------------------------------------- */
426 : char *pszRecord;
427 :
428 0 : pszRecord = (char *) CPLMalloc(nDSRSize+1);
429 :
430 0 : if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDSIndex, nRecord,
431 : pszRecord ) == FAILURE )
432 : {
433 0 : CPLFree( pszRecord );
434 0 : return NULL;
435 : }
436 :
437 : /* -------------------------------------------------------------------- */
438 : /* Massage the data into a safe textual format. For now we */
439 : /* just turn zero bytes into spaces. */
440 : /* -------------------------------------------------------------------- */
441 : char *pszEscapedRecord;
442 :
443 0 : CSLDestroy( papszTempMD );
444 :
445 : pszEscapedRecord = CPLEscapeString( pszRecord, nDSRSize,
446 0 : CPLES_BackslashQuotable );
447 0 : papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszEscapedRecord );
448 0 : CPLFree( pszEscapedRecord );
449 :
450 0 : for( i = 0; i < nDSRSize; i++ )
451 0 : if( pszRecord[i] == '\0' )
452 0 : pszRecord[i] = ' ';
453 :
454 0 : papszTempMD = CSLSetNameValue( papszTempMD, "RawRecord", pszRecord );
455 :
456 0 : CPLFree( pszRecord );
457 :
458 0 : return papszTempMD;
459 : }
460 :
461 : /************************************************************************/
462 : /* CollectDSDMetadata() */
463 : /* */
464 : /* Collect metadata based on any DSD entries with filenames */
465 : /* associated. */
466 : /************************************************************************/
467 :
468 0 : void EnvisatDataset::CollectDSDMetadata()
469 :
470 : {
471 : char *pszDSName, *pszFilename;
472 : int iDSD;
473 :
474 0 : for( iDSD = 0;
475 : EnvisatFile_GetDatasetInfo( hEnvisatFile, iDSD, &pszDSName, NULL,
476 : &pszFilename, NULL, NULL, NULL, NULL ) == SUCCESS;
477 : iDSD++ )
478 : {
479 0 : if( pszFilename == NULL
480 : || strlen(pszFilename) == 0
481 : || EQUALN(pszFilename,"NOT USED",8)
482 : || EQUALN(pszFilename," ",8))
483 0 : continue;
484 :
485 : char szKey[128], szTrimmedName[128];
486 : int i;
487 :
488 0 : strcpy( szKey, "DS_" );
489 0 : strcat( szKey, pszDSName );
490 :
491 : // strip trailing spaces.
492 0 : for( i = strlen(szKey)-1; i && szKey[i] == ' '; i-- )
493 0 : szKey[i] = '\0';
494 :
495 : // convert spaces into underscores.
496 0 : for( i = 0; szKey[i] != '\0'; i++ )
497 : {
498 0 : if( szKey[i] == ' ' )
499 0 : szKey[i] = '_';
500 : }
501 :
502 0 : strcat( szKey, "_NAME" );
503 :
504 0 : strcpy( szTrimmedName, pszFilename );
505 0 : for( i = strlen(szTrimmedName)-1; i && szTrimmedName[i] == ' '; i--)
506 0 : szTrimmedName[i] = '\0';
507 :
508 0 : SetMetadataItem( szKey, szTrimmedName );
509 : }
510 0 : }
511 :
512 : /************************************************************************/
513 : /* CollectMetadata() */
514 : /* */
515 : /* Collect metadata from the SPH or MPH header fields. */
516 : /************************************************************************/
517 :
518 0 : void EnvisatDataset::CollectMetadata( EnvisatFile_HeaderFlag eMPHOrSPH )
519 :
520 : {
521 : int iKey;
522 :
523 0 : for( iKey = 0; TRUE; iKey++ )
524 : {
525 : const char *pszValue, *pszKey;
526 : char szHeaderKey[128];
527 :
528 0 : pszKey = EnvisatFile_GetKeyByIndex(hEnvisatFile, eMPHOrSPH, iKey);
529 0 : if( pszKey == NULL )
530 0 : break;
531 :
532 : pszValue = EnvisatFile_GetKeyValueAsString( hEnvisatFile, eMPHOrSPH,
533 0 : pszKey, NULL );
534 :
535 0 : if( pszValue == NULL )
536 0 : continue;
537 :
538 : // skip some uninteresting structural information.
539 0 : if( EQUAL(pszKey,"TOT_SIZE")
540 : || EQUAL(pszKey,"SPH_SIZE")
541 : || EQUAL(pszKey,"NUM_DSD")
542 : || EQUAL(pszKey,"DSD_SIZE")
543 : || EQUAL(pszKey,"NUM_DATA_SETS") )
544 0 : continue;
545 :
546 0 : if( eMPHOrSPH == MPH )
547 0 : sprintf( szHeaderKey, "MPH_%s", pszKey );
548 : else
549 0 : sprintf( szHeaderKey, "SPH_%s", pszKey );
550 :
551 0 : SetMetadataItem( szHeaderKey, pszValue );
552 : }
553 0 : }
554 :
555 : /************************************************************************/
556 : /* Open() */
557 : /************************************************************************/
558 :
559 11013 : GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
560 :
561 : {
562 : EnvisatFile *hEnvisatFile;
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Check the header. */
566 : /* -------------------------------------------------------------------- */
567 11013 : if( poOpenInfo->nHeaderBytes < 8 || poOpenInfo->fp == NULL )
568 9800 : return NULL;
569 :
570 1213 : if( !EQUALN((const char *) poOpenInfo->pabyHeader, "PRODUCT=",8) )
571 1213 : return NULL;
572 :
573 : /* -------------------------------------------------------------------- */
574 : /* Try opening the dataset. */
575 : /* -------------------------------------------------------------------- */
576 : int ds_index;
577 :
578 0 : if( EnvisatFile_Open( &hEnvisatFile, poOpenInfo->pszFilename, "r" )
579 : == FAILURE )
580 0 : return NULL;
581 :
582 : /* -------------------------------------------------------------------- */
583 : /* Find a Mesurement type dataset to use as our reference */
584 : /* raster band. */
585 : /* -------------------------------------------------------------------- */
586 : int dsr_size, num_dsr, ds_offset, bNative;
587 : char *pszDSType;
588 :
589 0 : for( ds_index = 0; TRUE; ds_index++ )
590 : {
591 0 : if( EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
592 : NULL, &pszDSType, NULL,
593 : &ds_offset, NULL,
594 : &num_dsr, &dsr_size ) == FAILURE )
595 : {
596 : CPLError( CE_Failure, CPLE_AppDefined,
597 0 : "Unable to find \"MDS1\" measurement datatset in Envisat file." );
598 0 : EnvisatFile_Close( hEnvisatFile );
599 0 : return NULL;
600 : }
601 :
602 : /* Have we found what we are looking for? A Measurement ds. */
603 0 : if( EQUAL(pszDSType,"M") )
604 0 : break;
605 : }
606 :
607 : /* -------------------------------------------------------------------- */
608 : /* Confirm the requested access is supported. */
609 : /* -------------------------------------------------------------------- */
610 0 : if( poOpenInfo->eAccess == GA_Update )
611 : {
612 0 : EnvisatFile_Close( hEnvisatFile );
613 : CPLError( CE_Failure, CPLE_NotSupported,
614 : "The ENVISAT driver does not support update access to existing"
615 0 : " datasets.\n" );
616 0 : return NULL;
617 : }
618 : /* -------------------------------------------------------------------- */
619 : /* Create a corresponding GDALDataset. */
620 : /* -------------------------------------------------------------------- */
621 : EnvisatDataset *poDS;
622 :
623 0 : poDS = new EnvisatDataset();
624 :
625 0 : poDS->hEnvisatFile = hEnvisatFile;
626 :
627 : /* -------------------------------------------------------------------- */
628 : /* Setup image definition. */
629 : /* -------------------------------------------------------------------- */
630 : const char *pszDataType, *pszSampleType, *pszProduct;
631 : GDALDataType eDataType;
632 : int nPrefixBytes;
633 :
634 : EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
635 : NULL, NULL, NULL, &ds_offset, NULL,
636 0 : &num_dsr, &dsr_size );
637 :
638 : poDS->nRasterXSize = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
639 0 : "LINE_LENGTH", 0 );
640 0 : poDS->nRasterYSize = num_dsr;
641 0 : poDS->eAccess = GA_ReadOnly;
642 :
643 : pszProduct = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH,
644 0 : "PRODUCT", "" );
645 : pszDataType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH,
646 0 : "DATA_TYPE", "" );
647 : pszSampleType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH,
648 0 : "SAMPLE_TYPE", "" );
649 0 : if( EQUAL(pszDataType,"FLT32") && EQUALN(pszSampleType,"COMPLEX",7))
650 0 : eDataType = GDT_CFloat32;
651 0 : else if( EQUAL(pszDataType,"FLT32") )
652 0 : eDataType = GDT_Float32;
653 0 : else if( EQUAL(pszDataType,"UWORD") )
654 0 : eDataType = GDT_UInt16;
655 0 : else if( EQUAL(pszDataType,"SWORD") && EQUALN(pszSampleType,"COMPLEX",7) )
656 0 : eDataType = GDT_CInt16;
657 0 : else if( EQUAL(pszDataType,"SWORD") )
658 0 : eDataType = GDT_Int16;
659 0 : else if( EQUALN(pszProduct,"ATS_TOA_1",8) )
660 : {
661 : /* all 16bit data, no line length provided */
662 0 : eDataType = GDT_Int16;
663 0 : poDS->nRasterXSize = (dsr_size - 20) / 2;
664 : }
665 0 : else if( poDS->nRasterXSize == 0 )
666 : {
667 : CPLError( CE_Warning, CPLE_AppDefined,
668 : "Envisat product format not recognised. Assuming 8bit\n"
669 0 : "with no per-record prefix data. Results may be useless!" );
670 0 : eDataType = GDT_Byte;
671 0 : poDS->nRasterXSize = dsr_size;
672 : }
673 : else
674 : {
675 0 : if( dsr_size >= 2 * poDS->nRasterXSize )
676 0 : eDataType = GDT_UInt16;
677 : else
678 0 : eDataType = GDT_Byte;
679 : }
680 :
681 : #ifdef CPL_LSB
682 0 : bNative = FALSE;
683 : #else
684 : bNative = TRUE;
685 : #endif
686 :
687 : nPrefixBytes = dsr_size -
688 0 : ((GDALGetDataTypeSize(eDataType) / 8) * poDS->nRasterXSize);
689 :
690 : /* -------------------------------------------------------------------- */
691 : /* Fail out if we didn't get non-zero sizes. */
692 : /* -------------------------------------------------------------------- */
693 0 : if( poDS->nRasterXSize < 1 || poDS->nRasterYSize < 1 )
694 : {
695 : CPLError( CE_Failure, CPLE_AppDefined,
696 : "Unable to determine organization of dataset. It would\n"
697 : "appear this is an Envisat dataset, but an unsupported\n"
698 0 : "data product. Unable to utilize." );
699 0 : delete poDS;
700 0 : return NULL;
701 : }
702 :
703 : /* -------------------------------------------------------------------- */
704 : /* Assume ownership of the file handled from the GDALOpenInfo. */
705 : /* -------------------------------------------------------------------- */
706 0 : poDS->fpImage = poOpenInfo->fp;
707 0 : poOpenInfo->fp = NULL;
708 :
709 : /* -------------------------------------------------------------------- */
710 : /* Try to collect GCPs. */
711 : /* -------------------------------------------------------------------- */
712 :
713 : /* -------------------------------------------------------------------- */
714 : /* Scan for all datasets matching the reference dataset. */
715 : /* -------------------------------------------------------------------- */
716 0 : int num_dsr2, dsr_size2, iBand = 0;
717 : const char *pszDSName;
718 :
719 0 : for( ds_index = 0;
720 : EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
721 : (char **) &pszDSName, NULL, NULL,
722 : &ds_offset, NULL,
723 : &num_dsr2, &dsr_size2 ) == SUCCESS;
724 : ds_index++ )
725 : {
726 0 : if( EQUAL(pszDSType,"M")
727 : && num_dsr2 == num_dsr && dsr_size2 == dsr_size )
728 : {
729 : poDS->SetBand( iBand+1,
730 : new RawRasterBand( poDS, iBand+1, poDS->fpImage,
731 : ds_offset + nPrefixBytes,
732 : GDALGetDataTypeSize(eDataType) / 8,
733 : dsr_size,
734 0 : eDataType, bNative ) );
735 0 : iBand++;
736 :
737 0 : poDS->GetRasterBand(iBand)->SetDescription( pszDSName );
738 : }
739 : }
740 :
741 : /* -------------------------------------------------------------------- */
742 : /* Collect metadata. */
743 : /* -------------------------------------------------------------------- */
744 0 : poDS->CollectMetadata( MPH );
745 0 : poDS->CollectMetadata( SPH );
746 0 : poDS->CollectDSDMetadata();
747 :
748 0 : if( EQUALN(pszProduct,"MER",3) )
749 0 : poDS->ScanForGCPs_MERIS();
750 : else
751 0 : poDS->ScanForGCPs_ASAR();
752 :
753 : /* -------------------------------------------------------------------- */
754 : /* Initialize any PAM information. */
755 : /* -------------------------------------------------------------------- */
756 0 : poDS->SetDescription( poOpenInfo->pszFilename );
757 0 : poDS->TryLoadXML();
758 :
759 : /* -------------------------------------------------------------------- */
760 : /* Check for overviews. */
761 : /* -------------------------------------------------------------------- */
762 0 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
763 :
764 0 : return( poDS );
765 : }
766 :
767 : /************************************************************************/
768 : /* GDALRegister_Envisat() */
769 : /************************************************************************/
770 :
771 409 : void GDALRegister_Envisat()
772 :
773 : {
774 : GDALDriver *poDriver;
775 :
776 409 : if( GDALGetDriverByName( "ESAT" ) == NULL )
777 : {
778 392 : poDriver = new GDALDriver();
779 :
780 392 : poDriver->SetDescription( "ESAT" );
781 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
782 392 : "Envisat Image Format" );
783 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
784 392 : "frmt_various.html#Envisat" );
785 392 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "n1" );
786 :
787 392 : poDriver->pfnOpen = EnvisatDataset::Open;
788 :
789 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
790 : }
791 409 : }
792 :
|