1 : /******************************************************************************
2 : * $Id: landataset.cpp 17117 2009-05-25 19:26:01Z warmerdam $
3 : *
4 : * Project: eCognition
5 : * Purpose: Implementation of Erdas .LAN / .GIS format.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Frank Warmerdam
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: landataset.cpp 17117 2009-05-25 19:26:01Z warmerdam $");
35 :
36 : CPL_C_START
37 : void GDALRegister_LAN(void);
38 : CPL_C_END
39 :
40 : /**
41 :
42 : Erdas Header format: "HEAD74"
43 :
44 : Offset Size Type Description
45 : ------ ---- ---- -----------
46 : 0 6 char magic cookie / version (ie. HEAD74).
47 : 6 2 Int16 Pixel type, 0=8bit, 1=4bit, 2=16bit
48 : 8 2 Int16 Number of Bands.
49 : 10 6 char Unknown.
50 : 16 4 Int32 Width
51 : 20 4 Int32 Height
52 : 24 4 Int32 X Start (offset in original file?)
53 : 28 4 Int32 Y Start (offset in original file?)
54 : 32 56 char Unknown.
55 : 88 2 Int16 0=LAT, 1=UTM, 2=StatePlane, 3- are projections?
56 : 90 2 Int16 Classes in coverage.
57 : 92 14 char Unknown.
58 : 106 2 Int16 Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
59 : 108 4 Float32 Pixel area.
60 : 112 4 Float32 Upper Left corner X (center of pixel?)
61 : 116 4 Float32 Upper Left corner Y (center of pixel?)
62 : 120 4 Float32 Width of a pixel.
63 : 124 4 Float32 Height of a pixel.
64 :
65 : Erdas Header format: "HEADER"
66 :
67 : Offset Size Type Description
68 : ------ ---- ---- -----------
69 : 0 6 char magic cookie / version (ie. HEAD74).
70 : 6 2 Int16 Pixel type, 0=8bit, 1=4bit, 2=16bit
71 : 8 2 Int16 Number of Bands.
72 : 10 6 char Unknown.
73 : 16 4 Float32 Width
74 : 20 4 Float32 Height
75 : 24 4 Int32 X Start (offset in original file?)
76 : 28 4 Int32 Y Start (offset in original file?)
77 : 32 56 char Unknown.
78 : 88 2 Int16 0=LAT, 1=UTM, 2=StatePlane, 3- are projections?
79 : 90 2 Int16 Classes in coverage.
80 : 92 14 char Unknown.
81 : 106 2 Int16 Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
82 : 108 4 Float32 Pixel area.
83 : 112 4 Float32 Upper Left corner X (center of pixel?)
84 : 116 4 Float32 Upper Left corner Y (center of pixel?)
85 : 120 4 Float32 Width of a pixel.
86 : 124 4 Float32 Height of a pixel.
87 :
88 : All binary fields are in the same byte order but it may be big endian or
89 : little endian depending on what platform the file was written on. Usually
90 : this can be checked against the number of bands though this test won't work
91 : if there are more than 255 bands.
92 :
93 : There is also some information on .STA and .TRL files at:
94 :
95 : http://www.pcigeomatics.com/cgi-bin/pcihlp/ERDASWR%7CTRAILER+FORMAT
96 :
97 : **/
98 :
99 : #define ERD_HEADER_SIZE 128
100 :
101 : /************************************************************************/
102 : /* ==================================================================== */
103 : /* LAN4BitRasterBand */
104 : /* ==================================================================== */
105 : /************************************************************************/
106 :
107 : class LANDataset;
108 :
109 : class LAN4BitRasterBand : public GDALPamRasterBand
110 : {
111 : GDALColorTable *poCT;
112 : GDALColorInterp eInterp;
113 :
114 : public:
115 : LAN4BitRasterBand( LANDataset *, int );
116 : ~LAN4BitRasterBand();
117 :
118 : virtual GDALColorTable *GetColorTable();
119 : virtual GDALColorInterp GetColorInterpretation();
120 : virtual CPLErr SetColorTable( GDALColorTable * );
121 : virtual CPLErr SetColorInterpretation( GDALColorInterp );
122 :
123 : virtual CPLErr IReadBlock( int, int, void * );
124 : };
125 :
126 : /************************************************************************/
127 : /* ==================================================================== */
128 : /* LANDataset */
129 : /* ==================================================================== */
130 : /************************************************************************/
131 :
132 : class LANDataset : public RawDataset
133 : {
134 : public:
135 : FILE *fpImage; // image data file.
136 :
137 : char pachHeader[ERD_HEADER_SIZE];
138 :
139 : char *pszProjection;
140 :
141 : double adfGeoTransform[6];
142 :
143 : CPLString osSTAFilename;
144 : void CheckForStatistics(void);
145 :
146 : virtual char **GetFileList();
147 :
148 : public:
149 : LANDataset();
150 : ~LANDataset();
151 :
152 : virtual CPLErr GetGeoTransform( double * padfTransform );
153 : virtual const char *GetProjectionRef();
154 :
155 : static GDALDataset *Open( GDALOpenInfo * );
156 : };
157 :
158 : /************************************************************************/
159 : /* ==================================================================== */
160 : /* LAN4BitRasterBand */
161 : /* ==================================================================== */
162 : /************************************************************************/
163 :
164 : /************************************************************************/
165 : /* LAN4BitRasterBand() */
166 : /************************************************************************/
167 :
168 1 : LAN4BitRasterBand::LAN4BitRasterBand( LANDataset *poDS, int nBandIn )
169 :
170 : {
171 1 : this->poDS = poDS;
172 1 : this->nBand = nBandIn;
173 1 : this->eDataType = GDT_Byte;
174 :
175 1 : nBlockXSize = poDS->GetRasterXSize();;
176 1 : nBlockYSize = 1;
177 :
178 1 : poCT = NULL;
179 1 : eInterp = GCI_Undefined;
180 1 : }
181 :
182 : /************************************************************************/
183 : /* ~LAN4BitRasterBand() */
184 : /************************************************************************/
185 :
186 2 : LAN4BitRasterBand::~LAN4BitRasterBand()
187 :
188 : {
189 1 : if( poCT )
190 0 : delete poCT;
191 2 : }
192 :
193 : /************************************************************************/
194 : /* IReadBlock() */
195 : /************************************************************************/
196 :
197 2 : CPLErr LAN4BitRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
198 : void * pImage )
199 :
200 : {
201 2 : LANDataset *poLAN_DS = (LANDataset *) poDS;
202 : CPLAssert( nBlockXOff == 0 );
203 :
204 : /* -------------------------------------------------------------------- */
205 : /* Seek to profile. */
206 : /* -------------------------------------------------------------------- */
207 : int nOffset;
208 :
209 : nOffset =
210 : ERD_HEADER_SIZE
211 : + (nBlockYOff * nRasterXSize * poLAN_DS->GetRasterCount()) / 2
212 2 : + ((nBand - 1) * nRasterXSize) / 2;
213 :
214 2 : if( VSIFSeekL( poLAN_DS->fpImage, nOffset, SEEK_SET ) != 0 )
215 : {
216 : CPLError( CE_Failure, CPLE_FileIO,
217 0 : "LAN Seek failed:%s", VSIStrerror( errno ) );
218 0 : return CE_Failure;
219 : }
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Read the profile. */
223 : /* -------------------------------------------------------------------- */
224 2 : if( VSIFReadL( pImage, 1, nRasterXSize/2, poLAN_DS->fpImage ) !=
225 : (size_t) nRasterXSize / 2 )
226 : {
227 : CPLError( CE_Failure, CPLE_FileIO,
228 0 : "LAN Read failed:%s", VSIStrerror( errno ) );
229 0 : return CE_Failure;
230 : }
231 :
232 : /* -------------------------------------------------------------------- */
233 : /* Convert 4bit to 8bit. */
234 : /* -------------------------------------------------------------------- */
235 : int i;
236 :
237 6 : for( i = nRasterXSize-1; i >= 0; i-- )
238 : {
239 4 : if( (i & 0x01) != 0 )
240 2 : ((GByte *) pImage)[i] = ((GByte *) pImage)[i/2] & 0x0f;
241 : else
242 2 : ((GByte *) pImage)[i] = (((GByte *) pImage)[i/2] & 0xf0)/16;
243 : }
244 :
245 2 : return CE_None;
246 : }
247 :
248 : /************************************************************************/
249 : /* SetColorTable() */
250 : /************************************************************************/
251 :
252 0 : CPLErr LAN4BitRasterBand::SetColorTable( GDALColorTable *poNewCT )
253 :
254 : {
255 0 : if( poCT )
256 0 : delete poCT;
257 0 : if( poNewCT == NULL )
258 0 : poCT = NULL;
259 : else
260 0 : poCT = poNewCT->Clone();
261 :
262 0 : return CE_None;
263 : }
264 :
265 : /************************************************************************/
266 : /* GetColorTable() */
267 : /************************************************************************/
268 :
269 0 : GDALColorTable *LAN4BitRasterBand::GetColorTable()
270 :
271 : {
272 0 : if( poCT != NULL )
273 0 : return poCT;
274 : else
275 0 : return GDALPamRasterBand::GetColorTable();
276 : }
277 :
278 : /************************************************************************/
279 : /* SetColorInterpretation() */
280 : /************************************************************************/
281 :
282 0 : CPLErr LAN4BitRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
283 :
284 : {
285 0 : eInterp = eNewInterp;
286 :
287 0 : return CE_None;
288 : }
289 :
290 : /************************************************************************/
291 : /* GetColorInterpretation() */
292 : /************************************************************************/
293 :
294 0 : GDALColorInterp LAN4BitRasterBand::GetColorInterpretation()
295 :
296 : {
297 0 : return eInterp;
298 : }
299 :
300 : /************************************************************************/
301 : /* ==================================================================== */
302 : /* LANDataset */
303 : /* ==================================================================== */
304 : /************************************************************************/
305 :
306 : /************************************************************************/
307 : /* LANDataset() */
308 : /************************************************************************/
309 :
310 2 : LANDataset::LANDataset()
311 : {
312 2 : fpImage = NULL;
313 2 : pszProjection = NULL;
314 2 : }
315 :
316 : /************************************************************************/
317 : /* ~LANDataset() */
318 : /************************************************************************/
319 :
320 4 : LANDataset::~LANDataset()
321 :
322 : {
323 2 : FlushCache();
324 :
325 2 : if( fpImage != NULL )
326 2 : VSIFCloseL( fpImage );
327 :
328 2 : CPLFree( pszProjection );
329 4 : }
330 :
331 : /************************************************************************/
332 : /* Open() */
333 : /************************************************************************/
334 :
335 8523 : GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
336 :
337 : {
338 : /* -------------------------------------------------------------------- */
339 : /* We assume the user is pointing to the header (.pcb) file. */
340 : /* Does this appear to be a pcb file? */
341 : /* -------------------------------------------------------------------- */
342 8523 : if( poOpenInfo->nHeaderBytes < ERD_HEADER_SIZE || poOpenInfo->fp == NULL )
343 8344 : return NULL;
344 :
345 179 : if( !EQUALN((const char *)poOpenInfo->pabyHeader,"HEADER",6)
346 : && !EQUALN((const char *)poOpenInfo->pabyHeader,"HEAD74",6) )
347 177 : return NULL;
348 :
349 : /* -------------------------------------------------------------------- */
350 : /* Create a corresponding GDALDataset. */
351 : /* -------------------------------------------------------------------- */
352 : LANDataset *poDS;
353 :
354 2 : poDS = new LANDataset();
355 :
356 2 : poDS->eAccess = poOpenInfo->eAccess;
357 :
358 : /* -------------------------------------------------------------------- */
359 : /* Adopt the openinfo file pointer for use with this file. */
360 : /* -------------------------------------------------------------------- */
361 2 : if( poOpenInfo->eAccess == GA_ReadOnly )
362 2 : poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
363 : else
364 0 : poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
365 2 : if( poDS->fpImage == NULL )
366 0 : return NULL;
367 :
368 : /* -------------------------------------------------------------------- */
369 : /* Do we need to byte swap the headers to local machine order? */
370 : /* -------------------------------------------------------------------- */
371 2 : int bBigEndian = poOpenInfo->pabyHeader[8] == 0;
372 : int bNeedSwap;
373 :
374 2 : memcpy( poDS->pachHeader, poOpenInfo->pabyHeader, ERD_HEADER_SIZE );
375 :
376 : #ifdef CPL_LSB
377 2 : bNeedSwap = bBigEndian;
378 : #else
379 : bNeedSwap = !bBigEndian;
380 : #endif
381 :
382 2 : if( bNeedSwap )
383 : {
384 0 : CPL_SWAP16PTR( poDS->pachHeader + 6 );
385 0 : CPL_SWAP16PTR( poDS->pachHeader + 8 );
386 :
387 0 : CPL_SWAP32PTR( poDS->pachHeader + 16 );
388 0 : CPL_SWAP32PTR( poDS->pachHeader + 20 );
389 0 : CPL_SWAP32PTR( poDS->pachHeader + 24 );
390 0 : CPL_SWAP32PTR( poDS->pachHeader + 28 );
391 :
392 0 : CPL_SWAP16PTR( poDS->pachHeader + 88 );
393 0 : CPL_SWAP16PTR( poDS->pachHeader + 90 );
394 :
395 0 : CPL_SWAP16PTR( poDS->pachHeader + 106 );
396 0 : CPL_SWAP32PTR( poDS->pachHeader + 108 );
397 0 : CPL_SWAP32PTR( poDS->pachHeader + 112 );
398 0 : CPL_SWAP32PTR( poDS->pachHeader + 116 );
399 0 : CPL_SWAP32PTR( poDS->pachHeader + 120 );
400 0 : CPL_SWAP32PTR( poDS->pachHeader + 124 );
401 : }
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* Capture some information from the file that is of interest. */
405 : /* -------------------------------------------------------------------- */
406 : int nBandCount, nPixelOffset;
407 : GDALDataType eDataType;
408 :
409 2 : if( EQUALN(poDS->pachHeader,"HEADER",7) )
410 : {
411 0 : poDS->nRasterXSize = (int) *((float *) (poDS->pachHeader + 16));
412 0 : poDS->nRasterYSize = (int) *((float *) (poDS->pachHeader + 20));
413 : }
414 : else
415 : {
416 2 : poDS->nRasterXSize = *((GInt32 *) (poDS->pachHeader + 16));
417 2 : poDS->nRasterYSize = *((GInt32 *) (poDS->pachHeader + 20));
418 : }
419 :
420 2 : if( *((GInt16 *) (poDS->pachHeader + 6)) == 0 )
421 : {
422 1 : eDataType = GDT_Byte;
423 1 : nPixelOffset = 1;
424 : }
425 1 : else if( *((GInt16 *) (poDS->pachHeader + 6)) == 1 ) /* 4bit! */
426 : {
427 1 : eDataType = GDT_Byte;
428 1 : nPixelOffset = -1;
429 : }
430 0 : else if( *((GInt16 *) (poDS->pachHeader + 6)) == 2 )
431 : {
432 0 : nPixelOffset = 2;
433 0 : eDataType = GDT_Int16;
434 : }
435 : else
436 : {
437 : CPLError( CE_Failure, CPLE_AppDefined,
438 : "Unsupported pixel type (%d).",
439 0 : *((GInt16 *) (poDS->pachHeader + 6)) );
440 :
441 0 : delete poDS;
442 0 : return NULL;
443 : }
444 :
445 2 : nBandCount = *((GInt16 *) (poDS->pachHeader + 8));
446 :
447 2 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
448 : !GDALCheckBandCount(nBandCount, FALSE))
449 : {
450 0 : delete poDS;
451 0 : return NULL;
452 : }
453 :
454 : /* -------------------------------------------------------------------- */
455 : /* Create band information object. */
456 : /* -------------------------------------------------------------------- */
457 4 : for( int iBand = 1; iBand <= nBandCount; iBand++ )
458 : {
459 2 : if( nPixelOffset == -1 ) /* 4 bit case */
460 : poDS->SetBand( iBand,
461 1 : new LAN4BitRasterBand( poDS, iBand ) );
462 : else
463 : poDS->SetBand(
464 : iBand,
465 : new RawRasterBand( poDS, iBand, poDS->fpImage,
466 : ERD_HEADER_SIZE + (iBand-1)
467 : * nPixelOffset * poDS->nRasterXSize,
468 : nPixelOffset,
469 : poDS->nRasterXSize*nPixelOffset*nBandCount,
470 1 : eDataType, !bNeedSwap, TRUE ));
471 : }
472 :
473 : /* -------------------------------------------------------------------- */
474 : /* Initialize any PAM information. */
475 : /* -------------------------------------------------------------------- */
476 2 : poDS->SetDescription( poOpenInfo->pszFilename );
477 2 : poDS->CheckForStatistics();
478 2 : poDS->TryLoadXML();
479 :
480 : /* -------------------------------------------------------------------- */
481 : /* Check for overviews. */
482 : /* -------------------------------------------------------------------- */
483 2 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
484 :
485 : /* -------------------------------------------------------------------- */
486 : /* Try to interprete georeferencing. */
487 : /* -------------------------------------------------------------------- */
488 2 : poDS->adfGeoTransform[0] = *((float *) (poDS->pachHeader + 112));
489 2 : poDS->adfGeoTransform[1] = *((float *) (poDS->pachHeader + 120));
490 2 : poDS->adfGeoTransform[2] = 0.0;
491 2 : poDS->adfGeoTransform[3] = *((float *) (poDS->pachHeader + 116));
492 2 : poDS->adfGeoTransform[4] = 0.0;
493 2 : poDS->adfGeoTransform[5] = - *((float *) (poDS->pachHeader + 124));
494 :
495 : // adjust for center of pixel vs. top left corner of pixel.
496 2 : poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
497 2 : poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5;
498 :
499 : /* -------------------------------------------------------------------- */
500 : /* If we didn't get any georeferencing, try for a worldfile. */
501 : /* -------------------------------------------------------------------- */
502 4 : if( poDS->adfGeoTransform[1] == 0.0
503 2 : || poDS->adfGeoTransform[5] == 0.0 )
504 : {
505 0 : if( !GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
506 : poDS->adfGeoTransform ) )
507 : GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
508 0 : poDS->adfGeoTransform );
509 : }
510 :
511 : /* -------------------------------------------------------------------- */
512 : /* Try to come up with something for the coordinate system. */
513 : /* -------------------------------------------------------------------- */
514 2 : int nCoordSys = *((GInt16 *) (poDS->pachHeader + 88));
515 :
516 2 : if( nCoordSys == 0 )
517 : {
518 2 : poDS->pszProjection = CPLStrdup(SRS_WKT_WGS84);
519 :
520 : }
521 0 : else if( nCoordSys == 1 )
522 : {
523 : poDS->pszProjection =
524 0 : CPLStrdup("LOCAL_CS[\"UTM - Zone Unknown\",UNIT[\"Meter\",1]]");
525 : }
526 0 : else if( nCoordSys == 2 )
527 : {
528 0 : poDS->pszProjection = CPLStrdup("LOCAL_CS[\"State Plane - Zone Unknown\",UNIT[\"US survey foot\",0.3048006096012192]]");
529 : }
530 : else
531 : {
532 : poDS->pszProjection =
533 0 : CPLStrdup("LOCAL_CS[\"Unknown\",UNIT[\"Meter\",1]]");
534 : }
535 :
536 : /* -------------------------------------------------------------------- */
537 : /* Check for a trailer file with a colormap in it. */
538 : /* -------------------------------------------------------------------- */
539 2 : char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
540 2 : char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
541 : const char *pszTRLFilename =
542 2 : CPLFormCIFilename( pszPath, pszBasename, "trl" );
543 : FILE *fpTRL;
544 :
545 2 : fpTRL = VSIFOpenL( pszTRLFilename, "rb" );
546 2 : if( fpTRL != NULL )
547 : {
548 : char szTRLData[896];
549 : int iColor;
550 : GDALColorTable *poCT;
551 :
552 0 : VSIFReadL( szTRLData, 1, 896, fpTRL );
553 0 : VSIFCloseL( fpTRL );
554 :
555 0 : poCT = new GDALColorTable();
556 0 : for( iColor = 0; iColor < 256; iColor++ )
557 : {
558 : GDALColorEntry sEntry;
559 :
560 0 : sEntry.c2 = ((GByte *) szTRLData)[iColor+128];
561 0 : sEntry.c1 = ((GByte *) szTRLData)[iColor+128+256];
562 0 : sEntry.c3 = ((GByte *) szTRLData)[iColor+128+512];
563 0 : sEntry.c4 = 255;
564 0 : poCT->SetColorEntry( iColor, &sEntry );
565 :
566 : // only 16 colors in 4bit files.
567 0 : if( nPixelOffset == -1 && iColor == 15 )
568 0 : break;
569 : }
570 :
571 0 : poDS->GetRasterBand(1)->SetColorTable( poCT );
572 0 : poDS->GetRasterBand(1)->SetColorInterpretation( GCI_PaletteIndex );
573 :
574 0 : delete poCT;
575 : }
576 :
577 2 : CPLFree( pszPath );
578 2 : CPLFree( pszBasename );
579 :
580 2 : return( poDS );
581 : }
582 :
583 : /************************************************************************/
584 : /* GetGeoTransform() */
585 : /************************************************************************/
586 :
587 0 : CPLErr LANDataset::GetGeoTransform( double * padfTransform )
588 :
589 : {
590 0 : if( adfGeoTransform[1] != 0.0 && adfGeoTransform[5] != 0.0 )
591 : {
592 0 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
593 0 : return CE_None;
594 : }
595 : else
596 0 : return GDALPamDataset::GetGeoTransform( padfTransform );
597 : }
598 :
599 : /************************************************************************/
600 : /* GetProjectionRef() */
601 : /* */
602 : /* Use PAM coordinate system if available in preference to the */
603 : /* generally poor value derived from the file itself. */
604 : /************************************************************************/
605 :
606 0 : const char *LANDataset::GetProjectionRef()
607 :
608 : {
609 0 : const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
610 :
611 0 : if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
612 0 : return pszProjection;
613 : else
614 0 : return pszPamPrj;
615 : }
616 :
617 : /************************************************************************/
618 : /* GetFileList() */
619 : /************************************************************************/
620 :
621 0 : char **LANDataset::GetFileList()
622 :
623 : {
624 0 : char **papszFileList = NULL;
625 :
626 : // Main data file, etc.
627 0 : papszFileList = GDALPamDataset::GetFileList();
628 :
629 0 : if( strlen(osSTAFilename) > 0 )
630 0 : papszFileList = CSLAddString( papszFileList, osSTAFilename );
631 :
632 0 : return papszFileList;
633 : }
634 :
635 : /************************************************************************/
636 : /* CheckForStatistics() */
637 : /************************************************************************/
638 :
639 2 : void LANDataset::CheckForStatistics()
640 :
641 : {
642 : /* -------------------------------------------------------------------- */
643 : /* Do we have a statistics file? */
644 : /* -------------------------------------------------------------------- */
645 2 : osSTAFilename = CPLResetExtension(GetDescription(),"sta");
646 :
647 2 : FILE *fpSTA = VSIFOpenL( osSTAFilename, "r" );
648 :
649 : #ifndef WIN32
650 2 : if( fpSTA == NULL )
651 : {
652 2 : osSTAFilename = CPLResetExtension(GetDescription(),"STA");
653 2 : fpSTA = VSIFOpenL( osSTAFilename, "r" );
654 : }
655 : #endif
656 :
657 2 : if( fpSTA == NULL )
658 : {
659 2 : osSTAFilename = "";
660 2 : return;
661 : }
662 :
663 : /* -------------------------------------------------------------------- */
664 : /* Read it one band at a time. */
665 : /* -------------------------------------------------------------------- */
666 : GByte abyBandInfo[1152];
667 : int iBand;
668 :
669 0 : for( iBand = 0; iBand < nBands; iBand++ )
670 : {
671 0 : if( VSIFReadL( abyBandInfo, 1152, 1, fpSTA ) != 1 )
672 0 : break;
673 :
674 0 : int nBandNumber = abyBandInfo[7];
675 0 : GDALRasterBand *poBand = GetRasterBand(nBandNumber);
676 0 : if( poBand == NULL )
677 0 : break;
678 :
679 : float fMean, fStdDev;
680 : GInt16 nMin, nMax;
681 :
682 0 : if( poBand->GetRasterDataType() != GDT_Byte )
683 : {
684 0 : memcpy( &nMin, abyBandInfo + 28, 2 );
685 0 : memcpy( &nMax, abyBandInfo + 30, 2 );
686 : CPL_LSBPTR16( &nMin );
687 : CPL_LSBPTR16( &nMax );
688 : }
689 : else
690 : {
691 0 : nMin = abyBandInfo[9];
692 0 : nMax = abyBandInfo[8];
693 : }
694 :
695 0 : memcpy( &fMean, abyBandInfo + 12, 4 );
696 0 : memcpy( &fStdDev, abyBandInfo + 24, 4 );
697 : CPL_LSBPTR32( &fMean );
698 : CPL_LSBPTR32( &fStdDev );
699 :
700 0 : poBand->SetStatistics( nMin, nMax, fMean, fStdDev );
701 : }
702 :
703 0 : VSIFCloseL( fpSTA );
704 : }
705 :
706 : /************************************************************************/
707 : /* GDALRegister_LAN() */
708 : /************************************************************************/
709 :
710 338 : void GDALRegister_LAN()
711 :
712 : {
713 : GDALDriver *poDriver;
714 :
715 338 : if( GDALGetDriverByName( "LAN" ) == NULL )
716 : {
717 336 : poDriver = new GDALDriver();
718 :
719 336 : poDriver->SetDescription( "LAN" );
720 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
721 336 : "Erdas .LAN/.GIS" );
722 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
723 336 : "frmt_various.html#LAN" );
724 :
725 336 : poDriver->pfnOpen = LANDataset::Open;
726 :
727 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
728 : }
729 338 : }
730 :
|