1 : /******************************************************************************
2 : * $Id: fastdataset.cpp 18415 2009-12-30 23:56:35Z warmerdam $
3 : *
4 : * Project: EOSAT FAST Format reader
5 : * Purpose: Reads Landsat FAST-L7A, IRS 1C/1D
6 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Andrey Kiselev <dron@ak4719.spb.edu>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_string.h"
31 : #include "cpl_conv.h"
32 : #include "ogr_spatialref.h"
33 : #include "rawdataset.h"
34 :
35 : CPL_CVSID("$Id: fastdataset.cpp 18415 2009-12-30 23:56:35Z warmerdam $");
36 :
37 : CPL_C_START
38 : void GDALRegister_FAST(void);
39 : CPL_C_END
40 :
41 : #define ADM_STD_HEADER_SIZE 4608 // XXX: Format specification says it
42 : #define ADM_HEADER_SIZE 5000 // should be 4608, but some vendors
43 : // ship broken large datasets.
44 : #define ADM_MIN_HEADER_SIZE 1536 // ...and sometimes it can be
45 : // even 1/3 of standard size
46 :
47 : #define ACQUISITION_DATE "ACQUISITION DATE"
48 : #define ACQUISITION_DATE_SIZE 8
49 :
50 : #define SATELLITE_NAME "SATELLITE"
51 : #define SATELLITE_NAME_SIZE 10
52 :
53 : #define SENSOR_NAME "SENSOR"
54 : #define SENSOR_NAME_SIZE 10
55 :
56 : #define BANDS_PRESENT "BANDS PRESENT"
57 : #define BANDS_PRESENT_SIZE 32
58 :
59 : #define FILENAME "FILENAME"
60 : #define FILENAME_SIZE 29
61 :
62 : #define PIXELS "PIXELS PER LINE"
63 : #define PIXELS_SIZE 5
64 :
65 : #define LINES1 "LINES PER BAND"
66 : #define LINES2 "LINES PER IMAGE"
67 : #define LINES_SIZE 5
68 :
69 : #define BITS_PER_PIXEL "OUTPUT BITS PER PIXEL"
70 : #define BITS_PER_PIXEL_SIZE 2
71 :
72 : #define PROJECTION_NAME "MAP PROJECTION"
73 : #define PROJECTION_NAME_SIZE 4
74 :
75 : #define ELLIPSOID_NAME "ELLIPSOID"
76 : #define ELLIPSOID_NAME_SIZE 18
77 :
78 : #define DATUM_NAME "DATUM"
79 : #define DATUM_NAME_SIZE 6
80 :
81 : #define ZONE_NUMBER "USGS MAP ZONE"
82 : #define ZONE_NUMBER_SIZE 6
83 :
84 : #define USGS_PARAMETERS "USGS PROJECTION PARAMETERS"
85 :
86 : #define CORNER_UPPER_LEFT "UL "
87 : #define CORNER_UPPER_RIGHT "UR "
88 : #define CORNER_LOWER_LEFT "LL "
89 : #define CORNER_LOWER_RIGHT "LR "
90 : #define CORNER_VALUE_SIZE 13
91 :
92 : #define VALUE_SIZE 24
93 :
94 : enum FASTSatellite // Satellites:
95 : {
96 : LANDSAT, // Landsat 7
97 : IRS // IRS 1C/1D
98 : };
99 :
100 : /************************************************************************/
101 : /* ==================================================================== */
102 : /* FASTDataset */
103 : /* ==================================================================== */
104 : /************************************************************************/
105 :
106 : class FASTDataset : public GDALPamDataset
107 : {
108 : friend class FASTRasterBand;
109 :
110 : double adfGeoTransform[6];
111 : char *pszProjection;
112 :
113 : FILE *fpHeader;
114 : CPLString apoChannelFilenames[7];
115 : FILE *fpChannels[7];
116 : const char *pszFilename;
117 : char *pszDirname;
118 : GDALDataType eDataType;
119 : FASTSatellite iSatellite;
120 :
121 : int OpenChannel( const char *pszFilename, int iBand );
122 :
123 : public:
124 : FASTDataset();
125 : ~FASTDataset();
126 :
127 : static GDALDataset *Open( GDALOpenInfo * );
128 :
129 : CPLErr GetGeoTransform( double * );
130 : const char *GetProjectionRef();
131 : FILE *FOpenChannel( const char *, int iBand, int iFASTBand );
132 : void TryEuromap_IRS_1C_1D_ChannelNameConvention();
133 :
134 : virtual char** GetFileList();
135 : };
136 :
137 : /************************************************************************/
138 : /* ==================================================================== */
139 : /* FASTRasterBand */
140 : /* ==================================================================== */
141 : /************************************************************************/
142 :
143 : class FASTRasterBand : public RawRasterBand
144 36 : {
145 : friend class FASTDataset;
146 :
147 : public:
148 :
149 : FASTRasterBand( FASTDataset *, int, FILE *, vsi_l_offset,
150 : int, int, GDALDataType, int );
151 : };
152 :
153 :
154 : /************************************************************************/
155 : /* FASTRasterBand() */
156 : /************************************************************************/
157 :
158 18 : FASTRasterBand::FASTRasterBand( FASTDataset *poDS, int nBand, FILE * fpRaw,
159 : vsi_l_offset nImgOffset, int nPixelOffset,
160 : int nLineOffset, GDALDataType eDataType,
161 : int bNativeOrder) :
162 : RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
163 18 : nLineOffset, eDataType, bNativeOrder, TRUE)
164 : {
165 :
166 18 : }
167 :
168 : /************************************************************************/
169 : /* ==================================================================== */
170 : /* FASTDataset */
171 : /* ==================================================================== */
172 : /************************************************************************/
173 :
174 : /************************************************************************/
175 : /* FASTDataset() */
176 : /************************************************************************/
177 :
178 7 : FASTDataset::FASTDataset()
179 :
180 : {
181 7 : fpHeader = NULL;
182 7 : pszDirname = NULL;
183 14 : pszProjection = CPLStrdup( "" );
184 7 : adfGeoTransform[0] = 0.0;
185 7 : adfGeoTransform[1] = 1.0;
186 7 : adfGeoTransform[2] = 0.0;
187 7 : adfGeoTransform[3] = 0.0;
188 7 : adfGeoTransform[4] = 0.0;
189 7 : adfGeoTransform[5] = 1.0;
190 7 : nBands = 0;
191 7 : }
192 :
193 : /************************************************************************/
194 : /* ~FASTDataset() */
195 : /************************************************************************/
196 :
197 14 : FASTDataset::~FASTDataset()
198 :
199 : {
200 : int i;
201 :
202 7 : FlushCache();
203 :
204 7 : if ( pszDirname )
205 7 : CPLFree( pszDirname );
206 7 : if ( pszProjection )
207 7 : CPLFree( pszProjection );
208 25 : for ( i = 0; i < nBands; i++ )
209 18 : if ( fpChannels[i] )
210 18 : VSIFCloseL( fpChannels[i] );
211 7 : if( fpHeader != NULL )
212 7 : VSIFClose( fpHeader );
213 14 : }
214 :
215 : /************************************************************************/
216 : /* GetGeoTransform() */
217 : /************************************************************************/
218 :
219 5 : CPLErr FASTDataset::GetGeoTransform( double * padfTransform )
220 :
221 : {
222 5 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
223 5 : return CE_None;
224 : }
225 :
226 : /************************************************************************/
227 : /* GetProjectionRef() */
228 : /************************************************************************/
229 :
230 4 : const char *FASTDataset::GetProjectionRef()
231 :
232 : {
233 4 : if( pszProjection )
234 4 : return pszProjection;
235 : else
236 0 : return "";
237 : }
238 :
239 : /************************************************************************/
240 : /* GetFileList() */
241 : /************************************************************************/
242 :
243 0 : char** FASTDataset::GetFileList()
244 : {
245 0 : char** papszFileList = GDALPamDataset::GetFileList();
246 : int i;
247 0 : for(i=0;i<6;i++)
248 : {
249 0 : if (apoChannelFilenames[i].size() > 0)
250 : papszFileList =
251 0 : CSLAddString(papszFileList, apoChannelFilenames[i].c_str());
252 : }
253 :
254 0 : return papszFileList;
255 : }
256 :
257 : /************************************************************************/
258 : /* OpenChannel() */
259 : /************************************************************************/
260 :
261 67 : int FASTDataset::OpenChannel( const char *pszFilename, int iBand )
262 : {
263 67 : fpChannels[iBand] = VSIFOpenL( pszFilename, "rb" );
264 67 : if (fpChannels[iBand])
265 18 : apoChannelFilenames[iBand] = pszFilename;
266 67 : return fpChannels[iBand] != NULL;
267 : }
268 :
269 : /************************************************************************/
270 : /* FOpenChannel() */
271 : /************************************************************************/
272 :
273 :
274 28 : FILE *FASTDataset::FOpenChannel( const char *pszBandname, int iBand, int iFASTBand )
275 : {
276 28 : const char *pszChannelFilename = NULL;
277 28 : char *pszPrefix = CPLStrdup( CPLGetBasename( pszFilename ) );
278 28 : char *pszSuffix = CPLStrdup( CPLGetExtension( pszFilename ) );
279 :
280 28 : fpChannels[iBand] = NULL;
281 :
282 28 : switch ( iSatellite )
283 : {
284 : case LANDSAT:
285 21 : if ( pszBandname && !EQUAL( pszBandname, "" ) )
286 : {
287 : pszChannelFilename =
288 4 : CPLFormCIFilename( pszDirname, pszBandname, NULL );
289 4 : if ( OpenChannel( pszChannelFilename, iBand ) )
290 4 : break;
291 : pszChannelFilename =
292 : CPLFormFilename( pszDirname,
293 : CPLSPrintf( "%s.b%02d", pszPrefix, iFASTBand ),
294 0 : NULL );
295 0 : OpenChannel( pszChannelFilename, iBand );
296 : }
297 17 : break;
298 : case IRS:
299 : default:
300 : pszChannelFilename = CPLFormFilename( pszDirname,
301 7 : CPLSPrintf( "%s.%d", pszPrefix, iFASTBand ), pszSuffix );
302 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
303 0 : break;
304 : pszChannelFilename = CPLFormFilename( pszDirname,
305 7 : CPLSPrintf( "IMAGERY%d", iFASTBand ), pszSuffix );
306 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
307 0 : break;
308 : pszChannelFilename = CPLFormFilename( pszDirname,
309 7 : CPLSPrintf( "imagery%d", iFASTBand ), pszSuffix );
310 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
311 0 : break;
312 : pszChannelFilename = CPLFormFilename( pszDirname,
313 7 : CPLSPrintf( "IMAGERY%d.DAT", iFASTBand ), NULL );
314 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
315 0 : break;
316 : pszChannelFilename = CPLFormFilename( pszDirname,
317 7 : CPLSPrintf( "imagery%d.dat", iFASTBand ), NULL );
318 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
319 0 : break;
320 : pszChannelFilename = CPLFormFilename( pszDirname,
321 7 : CPLSPrintf( "IMAGERY%d.dat", iFASTBand ), NULL );
322 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
323 0 : break;
324 : pszChannelFilename = CPLFormFilename( pszDirname,
325 7 : CPLSPrintf( "imagery%d.DAT", iFASTBand ), NULL );
326 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
327 0 : break;
328 : pszChannelFilename = CPLFormFilename( pszDirname,
329 7 : CPLSPrintf( "BAND%d", iFASTBand ), pszSuffix );
330 7 : if ( OpenChannel( pszChannelFilename, iBand ) )
331 7 : break;
332 : pszChannelFilename = CPLFormFilename( pszDirname,
333 0 : CPLSPrintf( "band%d", iFASTBand ), pszSuffix );
334 0 : if ( OpenChannel( pszChannelFilename, iBand ) )
335 0 : break;
336 : pszChannelFilename = CPLFormFilename( pszDirname,
337 0 : CPLSPrintf( "BAND%d.DAT", iFASTBand ), NULL );
338 0 : if ( OpenChannel( pszChannelFilename, iBand ) )
339 0 : break;
340 : pszChannelFilename = CPLFormFilename( pszDirname,
341 0 : CPLSPrintf( "band%d.dat", iFASTBand ), NULL );
342 0 : if ( OpenChannel( pszChannelFilename, iBand ) )
343 0 : break;
344 : pszChannelFilename = CPLFormFilename( pszDirname,
345 0 : CPLSPrintf( "BAND%d.dat", iFASTBand ), NULL );
346 0 : if ( OpenChannel( pszChannelFilename, iBand ) )
347 0 : break;
348 : pszChannelFilename = CPLFormFilename( pszDirname,
349 0 : CPLSPrintf( "band%d.DAT", iFASTBand ), NULL );
350 0 : OpenChannel( pszChannelFilename, iBand );
351 : break;
352 : }
353 :
354 28 : CPLDebug( "FAST", "Band %d filename=%s", iBand + 1, pszChannelFilename);
355 :
356 28 : CPLFree( pszPrefix );
357 28 : CPLFree( pszSuffix );
358 28 : return fpChannels[iBand];
359 : }
360 :
361 : /************************************************************************/
362 : /* TryEuromap_IRS_1C_1D_ChannelNameConvention() */
363 : /************************************************************************/
364 :
365 3 : void FASTDataset::TryEuromap_IRS_1C_1D_ChannelNameConvention()
366 : {
367 : /* Filename convention explained in http://www.euromap.de/download/em_names.pdf */
368 :
369 3 : char chLastLetterHeader = pszFilename[strlen(pszFilename)-1];
370 3 : if (EQUAL(GetMetadataItem("SENSOR"), "PAN"))
371 : {
372 : /* Converting upper-case to lower case */
373 1 : if (chLastLetterHeader >= 'A' && chLastLetterHeader <= 'M')
374 0 : chLastLetterHeader += 'a' - 'A';
375 :
376 2 : if (chLastLetterHeader >= 'a' && chLastLetterHeader <= 'j')
377 : {
378 1 : char chLastLetterData = chLastLetterHeader - 'a' + '0';
379 1 : char* pszChannelFilename = CPLStrdup(pszFilename);
380 1 : pszChannelFilename[strlen(pszChannelFilename)-1] = chLastLetterData;
381 1 : if (OpenChannel( pszChannelFilename, 0 ))
382 1 : nBands++;
383 : else
384 0 : CPLDebug("FAST", "Could not find %s", pszChannelFilename);
385 1 : CPLFree(pszChannelFilename);
386 : }
387 0 : else if (chLastLetterHeader >= 'k' && chLastLetterHeader <= 'm')
388 : {
389 0 : char chLastLetterData = chLastLetterHeader - 'k' + 'n';
390 0 : char* pszChannelFilename = CPLStrdup(pszFilename);
391 0 : pszChannelFilename[strlen(pszChannelFilename)-1] = chLastLetterData;
392 0 : if (OpenChannel( pszChannelFilename, 0 ))
393 0 : nBands++;
394 : else
395 : {
396 : /* Trying upper-case */
397 0 : pszChannelFilename[strlen(pszChannelFilename)-1] = chLastLetterData - 'a' + 'A';
398 0 : if (OpenChannel( pszChannelFilename, 0 ))
399 0 : nBands++;
400 : else
401 0 : CPLDebug("FAST", "Could not find %s", pszChannelFilename);
402 : }
403 0 : CPLFree(pszChannelFilename);
404 : }
405 : else
406 : {
407 0 : CPLDebug("FAST", "Unknown last letter (%c) for a IRS PAN Euromap FAST dataset", chLastLetterHeader);
408 : }
409 : }
410 2 : else if (EQUAL(GetMetadataItem("SENSOR"), "LISS3"))
411 : {
412 : const char apchLISSFilenames[7][5] = {
413 : { '0', '2', '3', '4', '5' },
414 : { '6', '7', '8', '9', 'a' },
415 : { 'b', 'c', 'd', 'e', 'f' },
416 : { 'g', 'h', 'i', 'j', 'k' },
417 : { 'l', 'm', 'n', 'o', 'p' },
418 : { 'q', 'r', 's', 't', 'u' },
419 1 : { 'v', 'w', 'x', 'y', 'z' } };
420 : int i;
421 5 : for (i = 0; i < 7 ; i++)
422 : {
423 15 : if (chLastLetterHeader == apchLISSFilenames[i][0] ||
424 6 : (apchLISSFilenames[i][0] >= 'a' && apchLISSFilenames[i][0] <= 'z' &&
425 2 : (apchLISSFilenames[i][0] - chLastLetterHeader == 0 ||
426 2 : apchLISSFilenames[i][0] - chLastLetterHeader == 32)))
427 : {
428 5 : for (int j = 0; j < 4; j ++)
429 : {
430 4 : char* pszChannelFilename = CPLStrdup(pszFilename);
431 4 : pszChannelFilename[strlen(pszChannelFilename)-1] = apchLISSFilenames[i][j+1];
432 4 : if (OpenChannel( pszChannelFilename, nBands ))
433 4 : nBands++;
434 0 : else if (apchLISSFilenames[i][j+1] >= 'a' && apchLISSFilenames[i][j+1] <= 'z')
435 : {
436 : /* Trying upper-case */
437 0 : pszChannelFilename[strlen(pszChannelFilename)-1] = apchLISSFilenames[i][j+1] - 'a' + 'A';
438 0 : if (OpenChannel( pszChannelFilename, nBands ))
439 0 : nBands++;
440 : else
441 : {
442 0 : CPLDebug("FAST", "Could not find %s", pszChannelFilename);
443 : }
444 : }
445 : else
446 : {
447 0 : CPLDebug("FAST", "Could not find %s", pszChannelFilename);
448 : }
449 4 : CPLFree(pszChannelFilename);
450 : }
451 1 : break;
452 : }
453 : }
454 1 : if (i == 7)
455 : {
456 0 : CPLDebug("FAST", "Unknown last letter (%c) for a IRS LISS3 Euromap FAST dataset", chLastLetterHeader);
457 : }
458 : }
459 1 : else if (EQUAL(GetMetadataItem("SENSOR"), "WIFS"))
460 : {
461 1 : if (chLastLetterHeader == '0')
462 : {
463 3 : for (int j = 0; j < 2; j ++)
464 : {
465 2 : char* pszChannelFilename = CPLStrdup(pszFilename);
466 2 : pszChannelFilename[strlen(pszChannelFilename)-1] = '1' + j;
467 2 : if (OpenChannel( pszChannelFilename, nBands ))
468 2 : nBands++;
469 : else
470 : {
471 0 : CPLDebug("FAST", "Could not find %s", pszChannelFilename);
472 : }
473 2 : CPLFree(pszChannelFilename);
474 : }
475 : }
476 : else
477 : {
478 0 : CPLDebug("FAST", "Unknown last letter (%c) for a IRS WIFS Euromap FAST dataset", chLastLetterHeader);
479 : }
480 : }
481 : else
482 : {
483 : CPLAssert(0);
484 : }
485 3 : }
486 :
487 : /************************************************************************/
488 : /* GetValue() */
489 : /************************************************************************/
490 :
491 71 : static char *GetValue( const char *pszString, const char *pszName,
492 : int iValueSize, int bNormalize )
493 : {
494 71 : char *pszTemp = strstr( (char *) pszString, pszName );
495 :
496 71 : if ( pszTemp )
497 : {
498 : // Skip the parameter name
499 63 : pszTemp += strlen( pszName );
500 : // Skip whitespaces and equal signs
501 187 : while ( *pszTemp == ' ' )
502 61 : pszTemp++;
503 189 : while ( *pszTemp == '=' )
504 63 : pszTemp++;
505 :
506 63 : pszTemp = CPLScanString( pszTemp, iValueSize, TRUE, bNormalize );
507 : }
508 :
509 71 : return pszTemp;
510 : }
511 :
512 : /************************************************************************/
513 : /* USGSMnemonicToCode() */
514 : /************************************************************************/
515 :
516 6 : static long USGSMnemonicToCode( const char* pszMnemonic )
517 : {
518 6 : if ( EQUAL(pszMnemonic, "UTM") )
519 1 : return 1L;
520 5 : else if ( EQUAL(pszMnemonic, "LCC") )
521 1 : return 4L;
522 4 : else if ( EQUAL(pszMnemonic, "PS") )
523 0 : return 6L;
524 4 : else if ( EQUAL(pszMnemonic, "PC") )
525 0 : return 7L;
526 4 : else if ( EQUAL(pszMnemonic, "TM") )
527 3 : return 9L;
528 1 : else if ( EQUAL(pszMnemonic, "OM") )
529 0 : return 20L;
530 1 : else if ( EQUAL(pszMnemonic, "SOM") )
531 1 : return 22L;
532 : else
533 0 : return 1L; // UTM by default
534 : }
535 :
536 : /************************************************************************/
537 : /* USGSEllipsoidToCode() */
538 : /************************************************************************/
539 :
540 7 : static long USGSEllipsoidToCode( const char* pszMnemonic )
541 : {
542 7 : if ( EQUAL(pszMnemonic, "CLARKE_1866") )
543 0 : return 0L;
544 7 : else if ( EQUAL(pszMnemonic, "CLARKE_1880") )
545 0 : return 1L;
546 7 : else if ( EQUAL(pszMnemonic, "BESSEL") )
547 0 : return 2L;
548 7 : else if ( EQUAL(pszMnemonic, "INTERNATL_1967") )
549 0 : return 3L;
550 7 : else if ( EQUAL(pszMnemonic, "INTERNATL_1909") )
551 2 : return 4L;
552 5 : else if ( EQUAL(pszMnemonic, "WGS72") || EQUAL(pszMnemonic, "WGS_72") )
553 0 : return 5L;
554 5 : else if ( EQUAL(pszMnemonic, "EVEREST") )
555 0 : return 6L;
556 5 : else if ( EQUAL(pszMnemonic, "WGS66") || EQUAL(pszMnemonic, "WGS_66") )
557 0 : return 7L;
558 5 : else if ( EQUAL(pszMnemonic, "GRS_80") )
559 0 : return 8L;
560 5 : else if ( EQUAL(pszMnemonic, "AIRY") )
561 0 : return 9L;
562 5 : else if ( EQUAL(pszMnemonic, "MODIFIED_EVEREST") )
563 0 : return 10L;
564 5 : else if ( EQUAL(pszMnemonic, "MODIFIED_AIRY") )
565 0 : return 11L;
566 5 : else if ( EQUAL(pszMnemonic, "WGS84") || EQUAL(pszMnemonic, "WGS_84") )
567 4 : return 12L;
568 1 : else if ( EQUAL(pszMnemonic, "SOUTHEAST_ASIA") )
569 0 : return 13L;
570 1 : else if ( EQUAL(pszMnemonic, "AUSTRALIAN_NATL") )
571 0 : return 14L;
572 1 : else if ( EQUAL(pszMnemonic, "KRASSOVSKY") )
573 0 : return 15L;
574 1 : else if ( EQUAL(pszMnemonic, "HOUGH") )
575 0 : return 16L;
576 1 : else if ( EQUAL(pszMnemonic, "MERCURY_1960") )
577 0 : return 17L;
578 1 : else if ( EQUAL(pszMnemonic, "MOD_MERC_1968") )
579 0 : return 18L;
580 1 : else if ( EQUAL(pszMnemonic, "6370997_M_SPHERE") )
581 0 : return 19L;
582 : else
583 1 : return 0L;
584 : }
585 :
586 : /************************************************************************/
587 : /* Open() */
588 : /************************************************************************/
589 :
590 8557 : GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
591 :
592 : {
593 : int i;
594 :
595 8557 : if( poOpenInfo->fp == NULL )
596 8276 : return NULL;
597 :
598 281 : if( !EQUALN((const char *) poOpenInfo->pabyHeader + 52,
599 : "ACQUISITION DATE =", 18)
600 : && !EQUALN((const char *) poOpenInfo->pabyHeader + 36,
601 : "ACQUISITION DATE =", 18) )
602 274 : return NULL;
603 :
604 : /* -------------------------------------------------------------------- */
605 : /* Create a corresponding GDALDataset. */
606 : /* -------------------------------------------------------------------- */
607 : FASTDataset *poDS;
608 :
609 7 : poDS = new FASTDataset();
610 :
611 7 : poDS->fpHeader = poOpenInfo->fp;
612 7 : poOpenInfo->fp = NULL;
613 7 : poDS->pszFilename = poOpenInfo->pszFilename;
614 7 : poDS->pszDirname = CPLStrdup( CPLGetDirname( poOpenInfo->pszFilename ) );
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Read the administrative record. */
618 : /* -------------------------------------------------------------------- */
619 : char *pszTemp;
620 7 : char *pszHeader = (char *) CPLMalloc( ADM_HEADER_SIZE + 1 );
621 : size_t nBytesRead;
622 :
623 7 : VSIFSeek( poDS->fpHeader, 0, SEEK_SET );
624 7 : nBytesRead = VSIFRead( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader );
625 7 : if ( nBytesRead < ADM_MIN_HEADER_SIZE )
626 : {
627 0 : CPLDebug( "FAST", "Header file too short. Reading failed" );
628 0 : CPLFree(pszHeader);
629 0 : delete poDS;
630 0 : return NULL;
631 : }
632 7 : pszHeader[nBytesRead] = '\0';
633 :
634 : // Read acquisition date
635 : pszTemp = GetValue( pszHeader, ACQUISITION_DATE,
636 7 : ACQUISITION_DATE_SIZE, TRUE );
637 7 : if (pszTemp == NULL)
638 : {
639 0 : CPLDebug( "FAST", "Cannot get ACQUISITION_DATE, using empty value." );
640 0 : pszTemp = CPLStrdup("");
641 : }
642 7 : poDS->SetMetadataItem( "ACQUISITION_DATE", pszTemp );
643 7 : CPLFree( pszTemp );
644 :
645 : // Read satellite name (will read the first one only)
646 7 : pszTemp = GetValue( pszHeader, SATELLITE_NAME, SATELLITE_NAME_SIZE, TRUE );
647 7 : if (pszTemp == NULL)
648 : {
649 0 : CPLDebug( "FAST", "Cannot get SATELLITE_NAME, using empty value." );
650 0 : pszTemp = CPLStrdup( "" );
651 : }
652 7 : poDS->SetMetadataItem( "SATELLITE", pszTemp );
653 7 : if ( EQUALN(pszTemp, "LANDSAT", 7) )
654 3 : poDS->iSatellite = LANDSAT;
655 4 : else if ( EQUALN(pszTemp, "IRS", 3) )
656 3 : poDS->iSatellite = IRS;
657 : else
658 1 : poDS->iSatellite = IRS;
659 7 : CPLFree( pszTemp );
660 :
661 : // Read sensor name (will read the first one only)
662 7 : pszTemp = GetValue( pszHeader, SENSOR_NAME, SENSOR_NAME_SIZE, TRUE );
663 7 : if (pszTemp == NULL)
664 : {
665 1 : CPLDebug( "FAST", "Cannot get SENSOR_NAME, using empty value." );
666 1 : pszTemp = CPLStrdup("");
667 : }
668 7 : poDS->SetMetadataItem( "SENSOR", pszTemp );
669 7 : CPLFree( pszTemp );
670 :
671 : // Read filenames
672 7 : pszTemp = pszHeader;
673 7 : poDS->nBands = 0;
674 :
675 7 : if (strstr( pszHeader, FILENAME ) == NULL)
676 : {
677 4 : if (strstr(pszHeader, "GENERATING AGENCY =EUROMAP"))
678 : {
679 : /* If we don't find the FILENAME field, let's try with the Euromap */
680 : /* PAN / LISS3 / WIFS IRS filename convention */
681 11 : if ((EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS 1C") ||
682 2 : EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS 1D")) &&
683 3 : (EQUAL(poDS->GetMetadataItem("SENSOR"), "PAN") ||
684 2 : EQUAL(poDS->GetMetadataItem("SENSOR"), "LISS3") ||
685 1 : EQUAL(poDS->GetMetadataItem("SENSOR"), "WIFS")))
686 : {
687 3 : poDS->TryEuromap_IRS_1C_1D_ChannelNameConvention();
688 : }
689 0 : else if (EQUAL(poDS->GetMetadataItem("SATELLITE"), "CARTOSAT-1") &&
690 0 : (EQUAL(poDS->GetMetadataItem("SENSOR"), "FORE") ||
691 0 : EQUAL(poDS->GetMetadataItem("SENSOR"), "AFT")))
692 : {
693 : /* See http://www.euromap.de/download/p5fast_20050301.pdf, appendix F */
694 0 : CPLString osSuffix = CPLGetExtension( poDS->pszFilename );
695 0 : const char *papszBasenames[] = { "BANDF", "bandf", "BANDA", "banda" };
696 0 : for ( i=0;i<4;i++)
697 : {
698 0 : CPLString osChannelFilename = CPLFormFilename( poDS->pszDirname, papszBasenames[i], osSuffix );
699 0 : if (poDS->OpenChannel( osChannelFilename, 0 ))
700 : {
701 0 : poDS->nBands = 1;
702 : break;
703 : }
704 0 : }
705 : }
706 0 : else if (EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS P6"))
707 : {
708 : /* If BANDS_PRESENT="2345", the file bands are "BAND2.DAT", "BAND3.DAT", etc. */
709 0 : pszTemp = GetValue( pszHeader, BANDS_PRESENT, BANDS_PRESENT_SIZE, TRUE );
710 0 : if (pszTemp)
711 : {
712 0 : for( i=0; pszTemp[i] != '\0'; i++)
713 : {
714 0 : if (pszTemp[i] >= '2' && pszTemp[i] <= '5')
715 : {
716 0 : if (poDS->FOpenChannel(poDS->pszFilename, poDS->nBands, pszTemp[i] - '0'))
717 0 : poDS->nBands++;
718 : }
719 : }
720 0 : CPLFree( pszTemp );
721 : }
722 : }
723 : }
724 : }
725 :
726 : /* If the previous lookup for band files didn't success, fallback to the */
727 : /* standard way of finding them, either by the FILENAME field, either with */
728 : /* the usual patterns like bandX.dat, etc... */
729 7 : if ( !poDS->nBands )
730 : {
731 32 : for ( i = 0; i < 7; i++ )
732 : {
733 28 : char *pszFilename = NULL ;
734 :
735 28 : if ( pszTemp )
736 22 : pszTemp = strstr( pszTemp, FILENAME );
737 28 : if ( pszTemp )
738 : {
739 : // Skip the parameter name
740 18 : pszTemp += strlen(FILENAME);
741 : // Skip whitespaces and equal signs
742 54 : while ( *pszTemp == ' ' )
743 18 : pszTemp++;
744 54 : while ( *pszTemp == '=' )
745 18 : pszTemp++;
746 18 : pszFilename = CPLScanString( pszTemp, FILENAME_SIZE, TRUE, FALSE );
747 : }
748 : else
749 10 : pszTemp = NULL;
750 28 : if ( poDS->FOpenChannel( pszFilename, poDS->nBands, poDS->nBands + 1 ) )
751 11 : poDS->nBands++;
752 28 : if ( pszFilename )
753 18 : CPLFree( pszFilename );
754 : }
755 : }
756 :
757 7 : if ( !poDS->nBands )
758 : {
759 : CPLError( CE_Failure, CPLE_NotSupported,
760 0 : "Failed to find and open band data files." );
761 0 : CPLFree(pszHeader);
762 0 : delete poDS;
763 0 : return NULL;
764 : }
765 :
766 : // Read number of pixels/lines and bit depth
767 7 : pszTemp = GetValue( pszHeader, PIXELS, PIXELS_SIZE, FALSE );
768 7 : if ( pszTemp )
769 : {
770 7 : poDS->nRasterXSize = atoi( pszTemp );
771 7 : CPLFree( pszTemp );
772 : }
773 : else
774 : {
775 0 : CPLDebug( "FAST", "Failed to find number of pixels in line." );
776 0 : CPLFree(pszHeader);
777 0 : delete poDS;
778 0 : return NULL;
779 : }
780 :
781 7 : pszTemp = GetValue( pszHeader, LINES1, LINES_SIZE, FALSE );
782 7 : if ( !pszTemp )
783 1 : pszTemp = GetValue( pszHeader, LINES2, LINES_SIZE, FALSE );
784 7 : if ( pszTemp )
785 : {
786 7 : poDS->nRasterYSize = atoi( pszTemp );
787 7 : CPLFree( pszTemp );
788 : }
789 : else
790 : {
791 0 : CPLDebug( "FAST", "Failed to find number of lines in raster." );
792 0 : CPLFree(pszHeader);
793 0 : delete poDS;
794 0 : return NULL;
795 : }
796 :
797 :
798 :
799 7 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
800 : {
801 0 : CPLFree(pszHeader);
802 0 : delete poDS;
803 0 : return NULL;
804 : }
805 :
806 7 : pszTemp = GetValue( pszHeader, BITS_PER_PIXEL, BITS_PER_PIXEL_SIZE, FALSE );
807 7 : if ( pszTemp )
808 : {
809 6 : switch( atoi(pszTemp) )
810 : {
811 : case 8:
812 : default:
813 6 : poDS->eDataType = GDT_Byte;
814 6 : break;
815 : case 10: /* For a strange reason, some Euromap products declare 10 bits output, but are 16 bits */
816 : case 16:
817 0 : poDS->eDataType = GDT_UInt16;
818 : break;
819 : }
820 6 : CPLFree( pszTemp );
821 : }
822 : else
823 1 : poDS->eDataType = GDT_Byte;
824 :
825 : /* -------------------------------------------------------------------- */
826 : /* Read radiometric record. */
827 : /* -------------------------------------------------------------------- */
828 : const char *pszFirst, *pszSecond;
829 :
830 : // Read gains and biases. This is a trick!
831 7 : pszTemp = strstr( pszHeader, "BIASES" );// It may be "BIASES AND GAINS"
832 : // or "GAINS AND BIASES"
833 7 : if ( pszTemp > strstr( pszHeader, "GAINS" ) )
834 : {
835 3 : pszFirst = "GAIN%d";
836 3 : pszSecond = "BIAS%d";
837 : }
838 : else
839 : {
840 4 : pszFirst = "BIAS%d";
841 4 : pszSecond = "GAIN%d";
842 : }
843 :
844 : // Now search for the first number occurance after that string
845 25 : for ( i = 1; i <= poDS->nBands; i++ )
846 : {
847 18 : char *pszValue = NULL;
848 18 : size_t nValueLen = VALUE_SIZE;
849 :
850 18 : pszTemp = strpbrk( pszTemp, "-.0123456789" );
851 18 : if ( pszTemp )
852 : {
853 18 : nValueLen = strspn( pszTemp, "+-.0123456789" );
854 18 : pszValue = CPLScanString( pszTemp, nValueLen, TRUE, TRUE );
855 18 : poDS->SetMetadataItem( CPLSPrintf(pszFirst, i ), pszValue );
856 18 : CPLFree( pszValue );
857 : }
858 18 : pszTemp += nValueLen;
859 18 : pszTemp = strpbrk( pszTemp, "-.0123456789" );
860 18 : if ( pszTemp )
861 : {
862 18 : nValueLen = strspn( pszTemp, "+-.0123456789" );
863 18 : pszValue = CPLScanString( pszTemp, nValueLen, TRUE, TRUE );
864 18 : poDS->SetMetadataItem( CPLSPrintf(pszSecond, i ), pszValue );
865 18 : CPLFree( pszValue );
866 : }
867 18 : pszTemp += nValueLen;
868 : }
869 :
870 : /* -------------------------------------------------------------------- */
871 : /* Read geometric record. */
872 : /* -------------------------------------------------------------------- */
873 7 : OGRSpatialReference oSRS;
874 : long iProjSys, iZone, iDatum;
875 : // Coordinates of pixel's centers
876 7 : double dfULX = 0.0, dfULY = 0.0;
877 7 : double dfURX = 0.0, dfURY = 0.0;
878 7 : double dfLLX = 0.0, dfLLY = 0.0;
879 7 : double dfLRX = 0.0, dfLRY = 0.0;
880 : double adfProjParms[15];
881 :
882 : // Read projection name
883 : pszTemp = GetValue( pszHeader, PROJECTION_NAME,
884 7 : PROJECTION_NAME_SIZE, FALSE );
885 13 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
886 6 : iProjSys = USGSMnemonicToCode( pszTemp );
887 : else
888 1 : iProjSys = 1L; // UTM by default
889 7 : CPLFree( pszTemp );
890 :
891 : // Read ellipsoid name
892 7 : pszTemp = GetValue( pszHeader, ELLIPSOID_NAME, ELLIPSOID_NAME_SIZE, FALSE );
893 14 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
894 7 : iDatum = USGSEllipsoidToCode( pszTemp );
895 : else
896 0 : iDatum = 0L; // Clarke, 1866 (NAD1927) by default
897 7 : CPLFree( pszTemp );
898 :
899 : // Read zone number
900 7 : pszTemp = GetValue( pszHeader, ZONE_NUMBER, ZONE_NUMBER_SIZE, FALSE );
901 11 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
902 4 : iZone = atoi( pszTemp );
903 : else
904 3 : iZone = 0L;
905 7 : CPLFree( pszTemp );
906 :
907 : // Read 15 USGS projection parameters
908 112 : for ( i = 0; i < 15; i++ )
909 105 : adfProjParms[i] = 0.0;
910 7 : pszTemp = strstr( pszHeader, USGS_PARAMETERS );
911 7 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
912 : {
913 7 : pszTemp += strlen( USGS_PARAMETERS );
914 112 : for ( i = 0; i < 15; i++ )
915 : {
916 105 : pszTemp = strpbrk( pszTemp, "-.0123456789" );
917 105 : if ( pszTemp )
918 105 : adfProjParms[i] = CPLScanDouble( pszTemp, VALUE_SIZE );
919 105 : pszTemp = strpbrk( pszTemp, " \t" );
920 : }
921 : }
922 :
923 : // Coordinates should follow the word "PROJECTION", otherwise we can
924 : // be confused by other occurences of the corner keywords.
925 7 : char *pszGeomRecord = strstr( pszHeader, "PROJECTION" );
926 : // Read corner coordinates
927 7 : pszTemp = strstr( pszGeomRecord, CORNER_UPPER_LEFT );
928 7 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
929 : {
930 7 : pszTemp += strlen( CORNER_UPPER_LEFT ) + 28;
931 7 : dfULX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
932 7 : pszTemp += CORNER_VALUE_SIZE + 1;
933 7 : dfULY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
934 : }
935 :
936 7 : pszTemp = strstr( pszGeomRecord, CORNER_UPPER_RIGHT );
937 7 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
938 : {
939 7 : pszTemp += strlen( CORNER_UPPER_RIGHT ) + 28;
940 7 : dfURX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
941 7 : pszTemp += CORNER_VALUE_SIZE + 1;
942 7 : dfURY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
943 : }
944 :
945 7 : pszTemp = strstr( pszGeomRecord, CORNER_LOWER_LEFT );
946 7 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
947 : {
948 7 : pszTemp += strlen( CORNER_LOWER_LEFT ) + 28;
949 7 : dfLLX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
950 7 : pszTemp += CORNER_VALUE_SIZE + 1;
951 7 : dfLLY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
952 : }
953 :
954 7 : pszTemp = strstr( pszGeomRecord, CORNER_LOWER_RIGHT );
955 7 : if ( pszTemp && !EQUAL( pszTemp, "" ) )
956 : {
957 7 : pszTemp += strlen( CORNER_LOWER_RIGHT ) + 28;
958 7 : dfLRX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
959 7 : pszTemp += CORNER_VALUE_SIZE + 1;
960 7 : dfLRY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
961 : }
962 :
963 7 : if ( dfULX != 0.0 && dfULY != 0.0
964 : && dfURX != 0.0 && dfURY != 0.0
965 : && dfLLX != 0.0 && dfLLY != 0.0
966 : && dfLRX != 0.0 && dfLRY != 0.0 )
967 : {
968 7 : int transform_ok=FALSE;
969 : GDAL_GCP *pasGCPList;
970 : int bAnglesInPackedDMSFormat;
971 :
972 : // Strip out zone number from the easting values, if either
973 7 : if ( dfULX >= 1000000.0 )
974 2 : dfULX -= (double)iZone * 1000000.0;
975 7 : if ( dfURX >= 1000000.0 )
976 2 : dfURX -= (double)iZone * 1000000.0;
977 7 : if ( dfLLX >= 1000000.0 )
978 2 : dfLLX -= (double)iZone * 1000000.0;
979 7 : if ( dfLRX >= 1000000.0 )
980 2 : dfLRX -= (double)iZone * 1000000.0;
981 :
982 : // In EOSAT FAST Rev C, the angles are in decimal degrees
983 : // otherwise they are in packed DMS format.
984 7 : if (strstr(pszHeader, "REV C") != NULL)
985 3 : bAnglesInPackedDMSFormat = FALSE;
986 : else
987 4 : bAnglesInPackedDMSFormat = TRUE;
988 :
989 : // Create projection definition
990 : OGRErr eErr =
991 7 : oSRS.importFromUSGS( iProjSys, iZone, adfProjParms, iDatum, bAnglesInPackedDMSFormat );
992 7 : if ( eErr != OGRERR_NONE )
993 0 : CPLDebug("FAST", "Import projection from USGS failed: %d", eErr);
994 7 : oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
995 :
996 : // Read datum name
997 7 : pszTemp = GetValue( pszHeader, DATUM_NAME, DATUM_NAME_SIZE, FALSE );
998 7 : if ( pszTemp )
999 : {
1000 6 : if ( EQUAL( pszTemp, "WGS84" ) )
1001 3 : oSRS.SetWellKnownGeogCS( "WGS84" );
1002 3 : else if ( EQUAL( pszTemp, "NAD27" ) )
1003 0 : oSRS.SetWellKnownGeogCS( "NAD27" );
1004 3 : else if ( EQUAL( pszTemp, "NAD83" ) )
1005 0 : oSRS.SetWellKnownGeogCS( "NAD83" );
1006 6 : CPLFree( pszTemp );
1007 : }
1008 : else
1009 : {
1010 : // Reasonable fallback
1011 1 : oSRS.SetWellKnownGeogCS( "WGS84" );
1012 : }
1013 :
1014 7 : if ( poDS->pszProjection )
1015 7 : CPLFree( poDS->pszProjection );
1016 7 : eErr = oSRS.exportToWkt( &poDS->pszProjection );
1017 7 : if ( eErr != OGRERR_NONE )
1018 0 : CPLDebug("FAST", "Export projection to WKT USGS failed: %d", eErr);
1019 :
1020 : // Generate GCPs
1021 7 : pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof( GDAL_GCP ), 4 );
1022 7 : GDALInitGCPs( 4, pasGCPList );
1023 7 : CPLFree(pasGCPList[0].pszId);
1024 7 : CPLFree(pasGCPList[1].pszId);
1025 7 : CPLFree(pasGCPList[2].pszId);
1026 7 : CPLFree(pasGCPList[3].pszId);
1027 :
1028 : /* Let's order the GCP in TL, TR, BR, BL order to benefit from the */
1029 : /* GDALGCPsToGeoTransform optimization */
1030 7 : pasGCPList[0].pszId = CPLStrdup("UPPER_LEFT");
1031 7 : pasGCPList[0].dfGCPX = dfULX;
1032 7 : pasGCPList[0].dfGCPY = dfULY;
1033 7 : pasGCPList[0].dfGCPZ = 0.0;
1034 7 : pasGCPList[0].dfGCPPixel = 0.5;
1035 7 : pasGCPList[0].dfGCPLine = 0.5;
1036 7 : pasGCPList[1].pszId = CPLStrdup("UPPER_RIGHT");
1037 7 : pasGCPList[1].dfGCPX = dfURX;
1038 7 : pasGCPList[1].dfGCPY = dfURY;
1039 7 : pasGCPList[1].dfGCPZ = 0.0;
1040 7 : pasGCPList[1].dfGCPPixel = poDS->nRasterXSize-0.5;
1041 7 : pasGCPList[1].dfGCPLine = 0.5;
1042 7 : pasGCPList[2].pszId = CPLStrdup("LOWER_RIGHT");
1043 7 : pasGCPList[2].dfGCPX = dfLRX;
1044 7 : pasGCPList[2].dfGCPY = dfLRY;
1045 7 : pasGCPList[2].dfGCPZ = 0.0;
1046 7 : pasGCPList[2].dfGCPPixel = poDS->nRasterXSize-0.5;
1047 7 : pasGCPList[2].dfGCPLine = poDS->nRasterYSize-0.5;
1048 7 : pasGCPList[3].pszId = CPLStrdup("LOWER_LEFT");
1049 7 : pasGCPList[3].dfGCPX = dfLLX;
1050 7 : pasGCPList[3].dfGCPY = dfLLY;
1051 7 : pasGCPList[3].dfGCPZ = 0.0;
1052 7 : pasGCPList[3].dfGCPPixel = 0.5;
1053 7 : pasGCPList[3].dfGCPLine = poDS->nRasterYSize-0.5;
1054 :
1055 : // Calculate transformation matrix, if accurate
1056 : transform_ok =
1057 7 : GDALGCPsToGeoTransform(4,pasGCPList,poDS->adfGeoTransform,0);
1058 7 : if (transform_ok == FALSE)
1059 : {
1060 :
1061 0 : poDS->adfGeoTransform[0] = 0.0;
1062 0 : poDS->adfGeoTransform[1] = 1.0;
1063 0 : poDS->adfGeoTransform[2] = 0.0;
1064 0 : poDS->adfGeoTransform[3] = 0.0;
1065 0 : poDS->adfGeoTransform[4] = 0.0;
1066 0 : poDS->adfGeoTransform[5] = 1.0;
1067 0 : if ( poDS->pszProjection )
1068 0 : CPLFree( poDS->pszProjection );
1069 0 : poDS->pszProjection = CPLStrdup("");
1070 : }
1071 :
1072 7 : GDALDeinitGCPs(4, pasGCPList);
1073 7 : CPLFree(pasGCPList);
1074 : }
1075 :
1076 : /* -------------------------------------------------------------------- */
1077 : /* Create band information objects. */
1078 : /* -------------------------------------------------------------------- */
1079 7 : int nPixelOffset = GDALGetDataTypeSize(poDS->eDataType) / 8;
1080 7 : int nLineOffset = poDS->nRasterXSize * nPixelOffset;
1081 :
1082 25 : for( i = 1; i <= poDS->nBands; i++ )
1083 : {
1084 : poDS->SetBand( i, new FASTRasterBand( poDS, i, poDS->fpChannels[i - 1],
1085 18 : 0, nPixelOffset, nLineOffset, poDS->eDataType, TRUE));
1086 : }
1087 :
1088 7 : CPLFree( pszHeader );
1089 :
1090 : /* -------------------------------------------------------------------- */
1091 : /* Initialize any PAM information. */
1092 : /* -------------------------------------------------------------------- */
1093 7 : poDS->SetDescription( poOpenInfo->pszFilename );
1094 7 : poDS->TryLoadXML();
1095 :
1096 : // opens overviews.
1097 7 : poDS->oOvManager.Initialize(poDS, poDS->pszFilename);
1098 :
1099 : /* -------------------------------------------------------------------- */
1100 : /* Confirm the requested access is supported. */
1101 : /* -------------------------------------------------------------------- */
1102 7 : if( poOpenInfo->eAccess == GA_Update )
1103 : {
1104 0 : delete poDS;
1105 : CPLError( CE_Failure, CPLE_NotSupported,
1106 : "The FAST driver does not support update access to existing"
1107 0 : " datasets.\n" );
1108 0 : return NULL;
1109 : }
1110 :
1111 7 : return( poDS );
1112 : }
1113 :
1114 : /************************************************************************/
1115 : /* GDALRegister_FAST() */
1116 : /************************************************************************/
1117 :
1118 338 : void GDALRegister_FAST()
1119 :
1120 : {
1121 : GDALDriver *poDriver;
1122 :
1123 338 : if( GDALGetDriverByName( "FAST" ) == NULL )
1124 : {
1125 336 : poDriver = new GDALDriver();
1126 :
1127 336 : poDriver->SetDescription( "FAST" );
1128 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1129 336 : "EOSAT FAST Format" );
1130 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1131 336 : "frmt_fast.html" );
1132 :
1133 336 : poDriver->pfnOpen = FASTDataset::Open;
1134 :
1135 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
1136 : }
1137 338 : }
1138 :
|