1 : /******************************************************************************
2 : * $Id: ehdrdataset.cpp 18126 2009-11-28 14:11:43Z rouault $
3 : *
4 : * Project: ESRI .hdr Driver
5 : * Purpose: Implementation of EHdrDataset
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "rawdataset.h"
31 : #include "ogr_spatialref.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ehdrdataset.cpp 18126 2009-11-28 14:11:43Z rouault $");
35 :
36 : CPL_C_START
37 : void GDALRegister_EHdr(void);
38 : CPL_C_END
39 :
40 : /************************************************************************/
41 : /* ==================================================================== */
42 : /* EHdrDataset */
43 : /* ==================================================================== */
44 : /************************************************************************/
45 :
46 : class EHdrRasterBand;
47 :
48 : class EHdrDataset : public RawDataset
49 : {
50 : friend class EHdrRasterBand;
51 :
52 : FILE *fpImage; // image data file.
53 :
54 : int bGotTransform;
55 : double adfGeoTransform[6];
56 : char *pszProjection;
57 :
58 : int bHDRDirty;
59 : char **papszHDR;
60 :
61 : int bCLRDirty;
62 :
63 : CPLErr ReadSTX();
64 : CPLErr RewriteSTX();
65 : CPLErr RewriteHDR();
66 : void ResetKeyValue( const char *pszKey, const char *pszValue );
67 : const char *GetKeyValue( const char *pszKey, const char *pszDefault = "" );
68 : void RewriteColorTable( GDALColorTable * );
69 :
70 : public:
71 : EHdrDataset();
72 : ~EHdrDataset();
73 :
74 : virtual CPLErr GetGeoTransform( double * padfTransform );
75 : virtual CPLErr SetGeoTransform( double *padfTransform );
76 : virtual const char *GetProjectionRef(void);
77 : virtual CPLErr SetProjection( const char * );
78 :
79 : virtual char **GetFileList();
80 :
81 : static GDALDataset *Open( GDALOpenInfo * );
82 : static GDALDataset *Create( const char * pszFilename,
83 : int nXSize, int nYSize, int nBands,
84 : GDALDataType eType, char ** papszParmList );
85 : static GDALDataset *CreateCopy( const char * pszFilename,
86 : GDALDataset * poSrcDS,
87 : int bStrict, char ** papszOptions,
88 : GDALProgressFunc pfnProgress,
89 : void * pProgressData );
90 : static CPLString GetImageRepFilename(const char* pszFilename);
91 : };
92 :
93 : /************************************************************************/
94 : /* ==================================================================== */
95 : /* EHdrRasterBand */
96 : /* ==================================================================== */
97 : /************************************************************************/
98 :
99 : class EHdrRasterBand : public RawRasterBand
100 142 : {
101 : friend class EHdrDataset;
102 :
103 : int nBits;
104 : long nStartBit;
105 : int nPixelOffsetBits;
106 : int nLineOffsetBits;
107 :
108 : double dfMin;
109 : double dfMax;
110 : double dfMean;
111 : double dfStdDev;
112 :
113 : int minmaxmeanstddev;
114 :
115 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
116 : void *, int, int, GDALDataType,
117 : int, int );
118 :
119 : public:
120 : EHdrRasterBand( GDALDataset *poDS, int nBand, FILE * fpRaw,
121 : vsi_l_offset nImgOffset, int nPixelOffset,
122 : int nLineOffset,
123 : GDALDataType eDataType, int bNativeOrder,
124 : int nBits);
125 :
126 : virtual CPLErr IReadBlock( int, int, void * );
127 : virtual CPLErr IWriteBlock( int, int, void * );
128 :
129 : virtual double GetMinimum( int *pbSuccess = NULL );
130 : virtual double GetMaximum(int *pbSuccess = NULL );
131 : virtual CPLErr GetStatistics( int bApproxOK, int bForce,
132 : double *pdfMin, double *pdfMax,
133 : double *pdfMean, double *pdfStdDev );
134 : virtual CPLErr SetStatistics( double dfMin, double dfMax,
135 : double dfMean, double dfStdDev );
136 : virtual CPLErr SetColorTable( GDALColorTable *poNewCT );
137 :
138 : };
139 :
140 : /************************************************************************/
141 : /* EHdrRasterBand() */
142 : /************************************************************************/
143 :
144 71 : EHdrRasterBand::EHdrRasterBand( GDALDataset *poDS,
145 : int nBand, FILE * fpRaw,
146 : vsi_l_offset nImgOffset, int nPixelOffset,
147 : int nLineOffset,
148 : GDALDataType eDataType, int bNativeOrder,
149 : int nBits)
150 : : RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset, nLineOffset,
151 : eDataType, bNativeOrder, TRUE ),
152 : nBits(nBits),
153 : dfMin(0),
154 : dfMax(0),
155 71 : minmaxmeanstddev(0)
156 : {
157 71 : EHdrDataset* poEDS = (EHdrDataset*)poDS;
158 :
159 71 : if (nBits < 8)
160 : {
161 0 : nStartBit = atoi(poEDS->GetKeyValue("SKIPBYTES")) * 8;
162 0 : if (nBand >= 2)
163 : {
164 0 : long nRowBytes = atoi(poEDS->GetKeyValue("BANDROWBYTES"));
165 0 : if (nRowBytes == 0)
166 0 : nRowBytes = (nBits * poDS->GetRasterXSize() + 7) / 8;
167 :
168 0 : nStartBit += nRowBytes * (nBand-1) * 8;
169 : }
170 :
171 0 : nPixelOffsetBits = nBits;
172 0 : nLineOffsetBits = atoi(poEDS->GetKeyValue("TOTALROWBYTES")) * 8;
173 0 : if( nLineOffsetBits == 0 )
174 0 : nLineOffsetBits = nPixelOffsetBits * poDS->GetRasterXSize();
175 :
176 0 : nBlockXSize = poDS->GetRasterXSize();
177 0 : nBlockYSize = 1;
178 :
179 : SetMetadataItem( "NBITS",
180 : CPLString().Printf( "%d", nBits ),
181 0 : "IMAGE_STRUCTURE" );
182 : }
183 :
184 71 : if( eDataType == GDT_Byte
185 : && EQUAL(poEDS->GetKeyValue("PIXELTYPE",""),"SIGNEDINT") )
186 : SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
187 2 : "IMAGE_STRUCTURE" );
188 71 : }
189 :
190 : /************************************************************************/
191 : /* IReadBlock() */
192 : /************************************************************************/
193 :
194 240 : CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
195 : void * pImage )
196 :
197 : {
198 240 : if (nBits >= 8)
199 240 : return RawRasterBand::IReadBlock(nBlockXOff, nBlockYOff, pImage);
200 :
201 : vsi_l_offset nLineStart;
202 : unsigned int nLineBytes;
203 : int iBitOffset;
204 : GByte *pabyBuffer;
205 :
206 : /* -------------------------------------------------------------------- */
207 : /* Establish desired position. */
208 : /* -------------------------------------------------------------------- */
209 0 : nLineBytes = (nPixelOffsetBits*nBlockXSize + 7)/8;
210 0 : nLineStart = (nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) / 8;
211 : iBitOffset = (int)
212 0 : ((nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) % 8);
213 :
214 : /* -------------------------------------------------------------------- */
215 : /* Read data into buffer. */
216 : /* -------------------------------------------------------------------- */
217 0 : pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
218 :
219 0 : if( VSIFSeekL( GetFP(), nLineStart, SEEK_SET ) != 0
220 : || VSIFReadL( pabyBuffer, 1, nLineBytes, GetFP() ) != nLineBytes )
221 : {
222 : CPLError( CE_Failure, CPLE_FileIO,
223 : "Failed to read %u bytes at offset %lu.\n%s",
224 : nLineBytes, (unsigned long)nLineStart,
225 0 : VSIStrerror( errno ) );
226 0 : return CE_Failure;
227 : }
228 :
229 : /* -------------------------------------------------------------------- */
230 : /* Copy data, promoting to 8bit. */
231 : /* -------------------------------------------------------------------- */
232 0 : int iPixel = 0, iX;
233 :
234 0 : for( iX = 0; iX < nBlockXSize; iX++ )
235 : {
236 0 : int nOutWord = 0, iBit;
237 :
238 0 : for( iBit = 0; iBit < nBits; iBit++ )
239 : {
240 0 : if( pabyBuffer[iBitOffset>>3] & (0x80 >>(iBitOffset & 7)) )
241 0 : nOutWord |= (1 << (nBits - 1 - iBit));
242 0 : iBitOffset++;
243 : }
244 :
245 0 : iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
246 :
247 0 : ((GByte *) pImage)[iPixel++] = nOutWord;
248 : }
249 :
250 0 : CPLFree( pabyBuffer );
251 :
252 0 : return CE_None;
253 : }
254 :
255 : /************************************************************************/
256 : /* IWriteBlock() */
257 : /************************************************************************/
258 :
259 460 : CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
260 : void * pImage )
261 :
262 : {
263 460 : if (nBits >= 8)
264 460 : return RawRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
265 :
266 : vsi_l_offset nLineStart;
267 : unsigned int nLineBytes;
268 : int iBitOffset;
269 : GByte *pabyBuffer;
270 :
271 : /* -------------------------------------------------------------------- */
272 : /* Establish desired position. */
273 : /* -------------------------------------------------------------------- */
274 0 : nLineBytes = (nPixelOffsetBits*nBlockXSize + 7)/8;
275 0 : nLineStart = (nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) / 8;
276 : iBitOffset = (int)
277 0 : ((nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) % 8);
278 :
279 : /* -------------------------------------------------------------------- */
280 : /* Read data into buffer. */
281 : /* -------------------------------------------------------------------- */
282 0 : pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
283 :
284 0 : if( VSIFSeekL( GetFP(), nLineStart, SEEK_SET ) != 0 )
285 : {
286 : CPLError( CE_Failure, CPLE_FileIO,
287 : "Failed to read %u bytes at offset %lu.\n%s",
288 : nLineBytes, (unsigned long)nLineStart,
289 0 : VSIStrerror( errno ) );
290 0 : return CE_Failure;
291 : }
292 :
293 0 : VSIFReadL( pabyBuffer, 1, nLineBytes, GetFP() );
294 :
295 : /* -------------------------------------------------------------------- */
296 : /* Copy data, promoting to 8bit. */
297 : /* -------------------------------------------------------------------- */
298 0 : int iPixel = 0, iX;
299 :
300 0 : for( iX = 0; iX < nBlockXSize; iX++ )
301 : {
302 : int iBit;
303 0 : int nOutWord = ((GByte *) pImage)[iPixel++];
304 :
305 0 : for( iBit = 0; iBit < nBits; iBit++ )
306 : {
307 0 : if( nOutWord & (1 << (nBits - 1 - iBit)) )
308 0 : pabyBuffer[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
309 : else
310 0 : pabyBuffer[iBitOffset>>3] &= ~((0x80 >>(iBitOffset & 7)));
311 :
312 0 : iBitOffset++;
313 : }
314 :
315 0 : iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
316 : }
317 :
318 : /* -------------------------------------------------------------------- */
319 : /* Write the data back out. */
320 : /* -------------------------------------------------------------------- */
321 0 : if( VSIFSeekL( GetFP(), nLineStart, SEEK_SET ) != 0
322 : || VSIFWriteL( pabyBuffer, 1, nLineBytes, GetFP() ) != nLineBytes )
323 : {
324 : CPLError( CE_Failure, CPLE_FileIO,
325 : "Failed to write %u bytes at offset %lu.\n%s",
326 : nLineBytes, (unsigned long)nLineStart,
327 0 : VSIStrerror( errno ) );
328 0 : return CE_Failure;
329 : }
330 :
331 0 : CPLFree( pabyBuffer );
332 :
333 0 : return CE_None;
334 : }
335 :
336 : /************************************************************************/
337 : /* IRasterIO() */
338 : /************************************************************************/
339 :
340 452 : CPLErr EHdrRasterBand::IRasterIO( GDALRWFlag eRWFlag,
341 : int nXOff, int nYOff, int nXSize, int nYSize,
342 : void * pData, int nBufXSize, int nBufYSize,
343 : GDALDataType eBufType,
344 : int nPixelSpace, int nLineSpace )
345 :
346 : {
347 : // Defer to RawRasterBand
348 452 : if (nBits >= 8)
349 : return RawRasterBand::IRasterIO( eRWFlag,
350 : nXOff, nYOff, nXSize, nYSize,
351 : pData, nBufXSize, nBufYSize,
352 452 : eBufType, nPixelSpace, nLineSpace );
353 :
354 : // Force use of IReadBlock() and IWriteBlock()
355 : else
356 : return GDALRasterBand::IRasterIO( eRWFlag,
357 : nXOff, nYOff, nXSize, nYSize,
358 : pData, nBufXSize, nBufYSize,
359 0 : eBufType, nPixelSpace, nLineSpace );
360 : }
361 :
362 : /************************************************************************/
363 : /* OSR_GDS() */
364 : /************************************************************************/
365 :
366 0 : static const char*OSR_GDS( char* pszResult, int nResultLen,
367 : char **papszNV, const char * pszField,
368 : const char *pszDefaultValue )
369 :
370 : {
371 : int iLine;
372 :
373 0 : if( papszNV == NULL || papszNV[0] == NULL )
374 0 : return pszDefaultValue;
375 :
376 0 : for( iLine = 0;
377 0 : papszNV[iLine] != NULL &&
378 0 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
379 : iLine++ ) {}
380 :
381 0 : if( papszNV[iLine] == NULL )
382 0 : return pszDefaultValue;
383 : else
384 : {
385 : char **papszTokens;
386 :
387 0 : papszTokens = CSLTokenizeString(papszNV[iLine]);
388 :
389 0 : if( CSLCount(papszTokens) > 1 )
390 0 : strncpy( pszResult, papszTokens[1], nResultLen);
391 : else
392 0 : strncpy( pszResult, pszDefaultValue, nResultLen);
393 0 : pszResult[nResultLen-1] = '\0';
394 :
395 0 : CSLDestroy( papszTokens );
396 0 : return pszResult;
397 : }
398 : }
399 :
400 :
401 : /************************************************************************/
402 : /* ==================================================================== */
403 : /* EHdrDataset */
404 : /* ==================================================================== */
405 : /************************************************************************/
406 :
407 : /************************************************************************/
408 : /* EHdrDataset() */
409 : /************************************************************************/
410 :
411 45 : EHdrDataset::EHdrDataset()
412 : {
413 45 : fpImage = NULL;
414 45 : pszProjection = CPLStrdup("");
415 45 : bGotTransform = FALSE;
416 45 : adfGeoTransform[0] = 0.0;
417 45 : adfGeoTransform[1] = 1.0;
418 45 : adfGeoTransform[2] = 0.0;
419 45 : adfGeoTransform[3] = 0.0;
420 45 : adfGeoTransform[4] = 0.0;
421 45 : adfGeoTransform[5] = 1.0;
422 45 : papszHDR = NULL;
423 45 : bHDRDirty = FALSE;
424 45 : bCLRDirty = FALSE;
425 45 : }
426 :
427 : /************************************************************************/
428 : /* ~EHdrDataset() */
429 : /************************************************************************/
430 :
431 90 : EHdrDataset::~EHdrDataset()
432 :
433 : {
434 45 : FlushCache();
435 :
436 45 : if( nBands > 0 && GetAccess() == GA_Update )
437 : {
438 : int bNoDataSet;
439 : double dfNoData;
440 27 : RawRasterBand *poBand = (RawRasterBand *) GetRasterBand( 1 );
441 :
442 27 : dfNoData = poBand->GetNoDataValue(&bNoDataSet);
443 27 : if( bNoDataSet )
444 : {
445 : ResetKeyValue( "NODATA",
446 1 : CPLString().Printf( "%.8g", dfNoData ) );
447 : }
448 :
449 27 : if( bCLRDirty )
450 1 : RewriteColorTable( poBand->GetColorTable() );
451 :
452 27 : if( bHDRDirty )
453 16 : RewriteHDR();
454 : }
455 :
456 45 : if( fpImage != NULL )
457 45 : VSIFCloseL( fpImage );
458 :
459 45 : CPLFree( pszProjection );
460 45 : CSLDestroy( papszHDR );
461 90 : }
462 :
463 : /************************************************************************/
464 : /* GetKeyValue() */
465 : /************************************************************************/
466 :
467 38 : const char *EHdrDataset::GetKeyValue( const char *pszKey,
468 : const char *pszDefault )
469 :
470 : {
471 : int i;
472 :
473 342 : for( i = 0; papszHDR[i] != NULL; i++ )
474 : {
475 380 : if( EQUALN(pszKey,papszHDR[i],strlen(pszKey))
476 38 : && isspace((unsigned char)papszHDR[i][strlen(pszKey)]) )
477 : {
478 38 : const char *pszValue = papszHDR[i] + strlen(pszKey);
479 304 : while( isspace((unsigned char)*pszValue) )
480 228 : pszValue++;
481 :
482 38 : return pszValue;
483 : }
484 : }
485 :
486 0 : return pszDefault;
487 : }
488 :
489 : /************************************************************************/
490 : /* ResetKeyValue() */
491 : /* */
492 : /* Replace or add the keyword with the indicated value in the */
493 : /* papszHDR list. */
494 : /************************************************************************/
495 :
496 61 : void EHdrDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
497 :
498 : {
499 : int i;
500 : char szNewLine[82];
501 :
502 61 : if( strlen(pszValue) > 65 )
503 : {
504 : CPLAssert( strlen(pszValue) <= 65 );
505 0 : return;
506 : }
507 :
508 61 : sprintf( szNewLine, "%-15s%s", pszKey, pszValue );
509 :
510 700 : for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
511 : {
512 639 : if( EQUALN(papszHDR[i],szNewLine,strlen(pszKey)+1 ) )
513 : {
514 0 : if( strcmp(papszHDR[i],szNewLine) != 0 )
515 : {
516 0 : CPLFree( papszHDR[i] );
517 0 : papszHDR[i] = CPLStrdup( szNewLine );
518 0 : bHDRDirty = TRUE;
519 : }
520 0 : return;
521 : }
522 : }
523 :
524 61 : bHDRDirty = TRUE;
525 61 : papszHDR = CSLAddString( papszHDR, szNewLine );
526 : }
527 :
528 : /************************************************************************/
529 : /* RewriteColorTable() */
530 : /************************************************************************/
531 :
532 1 : void EHdrDataset::RewriteColorTable( GDALColorTable *poTable )
533 :
534 : {
535 1 : CPLString osCLRFilename = CPLResetExtension( GetDescription(), "clr" );
536 1 : if( poTable )
537 : {
538 1 : FILE *fp = VSIFOpenL( osCLRFilename, "wt" );
539 1 : if( fp != NULL )
540 : {
541 5 : for( int iColor = 0; iColor < poTable->GetColorEntryCount(); iColor++ )
542 : {
543 4 : CPLString oLine;
544 : GDALColorEntry sEntry;
545 :
546 4 : poTable->GetColorEntryAsRGB( iColor, &sEntry );
547 :
548 : // I wish we had a way to mark transparency.
549 : oLine.Printf( "%3d %3d %3d %3d\n",
550 4 : iColor, sEntry.c1, sEntry.c2, sEntry.c3 );
551 4 : VSIFWriteL( (void *) oLine.c_str(), 1, strlen(oLine), fp );
552 : }
553 1 : VSIFCloseL( fp );
554 : }
555 : else
556 : {
557 : CPLError( CE_Failure, CPLE_OpenFailed,
558 : "Unable to create color file %s.",
559 0 : osCLRFilename.c_str() );
560 : }
561 : }
562 : else
563 0 : VSIUnlink( osCLRFilename );
564 1 : }
565 :
566 : /************************************************************************/
567 : /* GetProjectionRef() */
568 : /************************************************************************/
569 :
570 15 : const char *EHdrDataset::GetProjectionRef()
571 :
572 : {
573 15 : if (pszProjection && strlen(pszProjection) > 0)
574 15 : return pszProjection;
575 :
576 0 : return GDALPamDataset::GetProjectionRef();
577 : }
578 :
579 : /************************************************************************/
580 : /* SetProjection() */
581 : /************************************************************************/
582 :
583 14 : CPLErr EHdrDataset::SetProjection( const char *pszSRS )
584 :
585 : {
586 : /* -------------------------------------------------------------------- */
587 : /* Reset coordinate system on the dataset. */
588 : /* -------------------------------------------------------------------- */
589 14 : CPLFree( pszProjection );
590 14 : pszProjection = CPLStrdup( pszSRS );
591 :
592 14 : if( strlen(pszSRS) == 0 )
593 0 : return CE_None;
594 :
595 : /* -------------------------------------------------------------------- */
596 : /* Convert to ESRI WKT. */
597 : /* -------------------------------------------------------------------- */
598 14 : OGRSpatialReference oSRS( pszSRS );
599 14 : char *pszESRI_SRS = NULL;
600 :
601 14 : oSRS.morphToESRI();
602 14 : oSRS.exportToWkt( &pszESRI_SRS );
603 :
604 : /* -------------------------------------------------------------------- */
605 : /* Write to .prj file. */
606 : /* -------------------------------------------------------------------- */
607 14 : CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
608 : FILE *fp;
609 :
610 14 : fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
611 14 : if( fp != NULL )
612 : {
613 14 : VSIFWriteL( pszESRI_SRS, 1, strlen(pszESRI_SRS), fp );
614 14 : VSIFWriteL( (void *) "\n", 1, 1, fp );
615 14 : VSIFCloseL( fp );
616 : }
617 :
618 14 : CPLFree( pszESRI_SRS );
619 :
620 14 : return CE_None;
621 : }
622 :
623 : /************************************************************************/
624 : /* GetGeoTransform() */
625 : /************************************************************************/
626 :
627 9 : CPLErr EHdrDataset::GetGeoTransform( double * padfTransform )
628 :
629 : {
630 9 : if( bGotTransform )
631 : {
632 9 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
633 9 : return CE_None;
634 : }
635 : else
636 : {
637 0 : return GDALPamDataset::GetGeoTransform( padfTransform );
638 : }
639 : }
640 :
641 : /************************************************************************/
642 : /* SetGeoTransform() */
643 : /************************************************************************/
644 :
645 15 : CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
646 :
647 : {
648 : /* -------------------------------------------------------------------- */
649 : /* We only support non-rotated images with info in the .HDR file. */
650 : /* -------------------------------------------------------------------- */
651 30 : if( padfGeoTransform[2] != 0.0
652 15 : || padfGeoTransform[4] != 0.0 )
653 : {
654 0 : return GDALPamDataset::SetGeoTransform( padfGeoTransform );
655 : }
656 :
657 : /* -------------------------------------------------------------------- */
658 : /* Record new geotransform. */
659 : /* -------------------------------------------------------------------- */
660 15 : bGotTransform = TRUE;
661 15 : memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
662 :
663 : /* -------------------------------------------------------------------- */
664 : /* Strip out all old geotransform keywords from HDR records. */
665 : /* -------------------------------------------------------------------- */
666 : int i;
667 150 : for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
668 : {
669 540 : if( EQUALN(papszHDR[i],"ul",2)
670 135 : || EQUALN(papszHDR[i]+1,"ll",2)
671 135 : || EQUALN(papszHDR[i],"cell",4)
672 135 : || EQUALN(papszHDR[i]+1,"dim",3) )
673 : {
674 0 : papszHDR = CSLRemoveStrings( papszHDR, i, 1, NULL );
675 : }
676 : }
677 :
678 : /* -------------------------------------------------------------------- */
679 : /* Set the transformation information. */
680 : /* -------------------------------------------------------------------- */
681 15 : CPLString oValue;
682 :
683 15 : oValue.Printf( "%.15g", adfGeoTransform[0] + adfGeoTransform[1] * 0.5 );
684 15 : ResetKeyValue( "ULXMAP", oValue );
685 :
686 15 : oValue.Printf( "%.15g", adfGeoTransform[3] + adfGeoTransform[5] * 0.5 );
687 15 : ResetKeyValue( "ULYMAP", oValue );
688 :
689 15 : oValue.Printf( "%.15g", adfGeoTransform[1] );
690 15 : ResetKeyValue( "XDIM", oValue );
691 :
692 15 : oValue.Printf( "%.15g", fabs(adfGeoTransform[5]) );
693 15 : ResetKeyValue( "YDIM", oValue );
694 :
695 15 : return CE_None;
696 : }
697 :
698 : /************************************************************************/
699 : /* RewriteHDR() */
700 : /************************************************************************/
701 :
702 16 : CPLErr EHdrDataset::RewriteHDR()
703 :
704 : {
705 16 : CPLString osPath = CPLGetPath( GetDescription() );
706 16 : CPLString osName = CPLGetBasename( GetDescription() );
707 16 : CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
708 :
709 : /* -------------------------------------------------------------------- */
710 : /* Write .hdr file. */
711 : /* -------------------------------------------------------------------- */
712 : FILE *fp;
713 : int i;
714 :
715 16 : fp = VSIFOpenL( osHDRFilename, "wt" );
716 :
717 16 : if( fp == NULL )
718 : {
719 : CPLError( CE_Failure, CPLE_OpenFailed,
720 : "Failed to rewrite .hdr file %s.",
721 0 : osHDRFilename.c_str() );
722 0 : return CE_Failure;
723 : }
724 :
725 221 : for( i = 0; papszHDR[i] != NULL; i++ )
726 : {
727 205 : VSIFWriteL( papszHDR[i], 1, strlen(papszHDR[i]), fp );
728 205 : VSIFWriteL( (void *) "\n", 1, 1, fp );
729 : }
730 :
731 16 : VSIFCloseL( fp );
732 :
733 16 : bHDRDirty = FALSE;
734 :
735 16 : return CE_None;
736 : }
737 :
738 : /************************************************************************/
739 : /* RewriteSTX() */
740 : /************************************************************************/
741 :
742 0 : CPLErr EHdrDataset::RewriteSTX()
743 : {
744 0 : CPLString osPath = CPLGetPath( GetDescription() );
745 0 : CPLString osName = CPLGetBasename( GetDescription() );
746 0 : CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
747 :
748 : /* -------------------------------------------------------------------- */
749 : /* Write .stx file. */
750 : /* -------------------------------------------------------------------- */
751 : FILE *fp;
752 0 : fp = VSIFOpenL( osSTXFilename, "wt" );
753 0 : if( fp == NULL )
754 : {
755 : CPLDebug( "EHDR", "Failed to rewrite .stx file %s.",
756 0 : osSTXFilename.c_str() );
757 0 : return CE_Failure;
758 : }
759 :
760 0 : for (int i = 0; i < nBands; ++i)
761 : {
762 0 : EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i];
763 0 : VSIFPrintfL( fp, "%d %.10f %.10f ", i+1, poBand->dfMin, poBand->dfMax );
764 0 : if ( poBand->minmaxmeanstddev & 0x4 )
765 0 : VSIFPrintfL( fp, "%.10f ", poBand->dfMean);
766 : else
767 0 : VSIFPrintfL( fp, "# ");
768 :
769 0 : if ( poBand->minmaxmeanstddev & 0x8 )
770 0 : VSIFPrintfL( fp, "%.10f\n", poBand->dfStdDev);
771 : else
772 0 : VSIFPrintfL( fp, "#\n");
773 : }
774 :
775 0 : VSIFCloseL( fp );
776 :
777 0 : return CE_None;
778 : }
779 :
780 : /************************************************************************/
781 : /* ReadSTX() */
782 : /************************************************************************/
783 :
784 45 : CPLErr EHdrDataset::ReadSTX()
785 : {
786 45 : CPLString osPath = CPLGetPath( GetDescription() );
787 45 : CPLString osName = CPLGetBasename( GetDescription() );
788 45 : CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
789 :
790 : /* -------------------------------------------------------------------- */
791 : /* Read .stx file. */
792 : /* -------------------------------------------------------------------- */
793 : FILE *fp;
794 45 : if ((fp = VSIFOpenL( osSTXFilename, "rt" )))
795 : {
796 : const char * pszLine;
797 0 : while( (pszLine = CPLReadLineL( fp )) )
798 : {
799 : char **papszTokens;
800 0 : papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
801 0 : int nTokens = CSLCount( papszTokens );
802 0 : if( nTokens >= 5 )
803 : {
804 0 : int i = atoi(papszTokens[0]);
805 0 : if (i > 0 && i <= nBands)
806 : {
807 0 : EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i-1];
808 0 : poBand->dfMin = atof(papszTokens[1]);
809 0 : poBand->dfMax = atof(papszTokens[2]);
810 0 : poBand->minmaxmeanstddev = 0x3;
811 : // reads optional mean and stddev
812 0 : if ( !EQUAL(papszTokens[3], "#") )
813 : {
814 0 : poBand->dfMean = atof(papszTokens[3]);
815 0 : poBand->minmaxmeanstddev |= 0x4;
816 : }
817 0 : if ( !EQUAL(papszTokens[4], "#") )
818 : {
819 0 : poBand->dfStdDev = atof(papszTokens[4]);
820 0 : poBand->minmaxmeanstddev |= 0x8;
821 : }
822 :
823 0 : if( nTokens >= 6 && !EQUAL(papszTokens[5], "#") )
824 0 : poBand->SetMetadataItem( "STRETCHMIN", papszTokens[5], "RENDERING_HINTS" );
825 :
826 0 : if( nTokens >= 7 && !EQUAL(papszTokens[6], "#") )
827 0 : poBand->SetMetadataItem( "STRETCHMAX", papszTokens[6], "RENDERING_HINTS" );
828 : }
829 : }
830 :
831 0 : CSLDestroy( papszTokens );
832 : }
833 :
834 0 : VSIFCloseL( fp );
835 : }
836 :
837 45 : return CE_None;
838 : }
839 :
840 :
841 : /************************************************************************/
842 : /* GetImageRepFilename() */
843 : /************************************************************************/
844 :
845 : /* -------------------------------------------------------------------- */
846 : /* Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep */
847 : /* if it's a GIS-GeoSPOT image */
848 : /* For the specification of SPDF (in French), */
849 : /* see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
850 : /* -------------------------------------------------------------------- */
851 :
852 39 : CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
853 : {
854 : VSIStatBufL sStatBuf;
855 :
856 39 : CPLString osPath = CPLGetPath( pszFilename );
857 39 : CPLString osName = CPLGetBasename( pszFilename );
858 : CPLString osREPFilename =
859 39 : CPLFormCIFilename( osPath, osName, "rep" );
860 39 : if( VSIStatL( (const char*)osREPFilename, &sStatBuf ) == 0 )
861 0 : return osREPFilename;
862 :
863 39 : if (EQUAL(CPLGetFilename(pszFilename), "imspatio.bil") ||
864 : EQUAL(CPLGetFilename(pszFilename), "haspatio.bil"))
865 : {
866 0 : CPLString pszImageRepFilename(CPLFormCIFilename( osPath, "image", "rep" ));
867 0 : if( VSIStatL( (const char*)pszImageRepFilename, &sStatBuf ) == 0 )
868 0 : return pszImageRepFilename;
869 :
870 : /* Try in the upper directories if not found in the BIL image directory */
871 0 : CPLString dirName(CPLGetDirname(osPath));
872 0 : if (CPLIsFilenameRelative((const char*)osPath))
873 : {
874 0 : char* cwd = CPLGetCurrentDir();
875 0 : if (cwd)
876 : {
877 0 : dirName = CPLFormFilename(cwd, (const char*)dirName, NULL);
878 0 : CPLFree(cwd);
879 : }
880 : }
881 0 : while (dirName[0] != 0 && EQUAL(dirName, ".") == FALSE && EQUAL(dirName, "/") == FALSE)
882 : {
883 0 : pszImageRepFilename = CPLFormCIFilename( (const char*)dirName, "image", "rep" );
884 0 : if( VSIStatL( (const char*)pszImageRepFilename, &sStatBuf ) == 0 )
885 0 : return pszImageRepFilename;
886 :
887 : /* Don't try to recurse above the 'image' subdirectory */
888 0 : if (EQUAL(dirName, "image"))
889 : {
890 0 : break;
891 : }
892 0 : dirName = CPLString(CPLGetDirname(dirName));
893 0 : }
894 : }
895 39 : return "";
896 : }
897 :
898 : /************************************************************************/
899 : /* GetFileList() */
900 : /************************************************************************/
901 :
902 7 : char **EHdrDataset::GetFileList()
903 :
904 : {
905 : VSIStatBufL sStatBuf;
906 7 : CPLString osPath = CPLGetPath( GetDescription() );
907 7 : CPLString osName = CPLGetBasename( GetDescription() );
908 7 : char **papszFileList = NULL;
909 :
910 : // Main data file, etc.
911 7 : papszFileList = GDALPamDataset::GetFileList();
912 :
913 : // Header file.
914 7 : CPLString osFilename = CPLFormCIFilename( osPath, osName, "hdr" );
915 7 : papszFileList = CSLAddString( papszFileList, osFilename );
916 :
917 : // Statistics file
918 7 : osFilename = CPLFormCIFilename( osPath, osName, "stx" );
919 7 : if( VSIStatL( osFilename, &sStatBuf ) == 0 )
920 0 : papszFileList = CSLAddString( papszFileList, osFilename );
921 :
922 : // color table file.
923 7 : osFilename = CPLFormCIFilename( osPath, osName, "clr" );
924 7 : if( VSIStatL( osFilename, &sStatBuf ) == 0 )
925 1 : papszFileList = CSLAddString( papszFileList, osFilename );
926 :
927 : // projections file.
928 7 : osFilename = CPLFormCIFilename( osPath, osName, "prj" );
929 7 : if( VSIStatL( osFilename, &sStatBuf ) == 0 )
930 4 : papszFileList = CSLAddString( papszFileList, osFilename );
931 :
932 7 : CPLString imageRepFilename = GetImageRepFilename( GetDescription() );
933 7 : if (imageRepFilename[0])
934 0 : papszFileList = CSLAddString( papszFileList, (const char*)imageRepFilename );
935 :
936 7 : return papszFileList;
937 : }
938 :
939 : /************************************************************************/
940 : /* Open() */
941 : /************************************************************************/
942 :
943 8672 : GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
944 :
945 : {
946 : int i, bSelectedHDR;
947 :
948 : /* -------------------------------------------------------------------- */
949 : /* We assume the user is pointing to the binary (ie. .bil) file. */
950 : /* -------------------------------------------------------------------- */
951 8672 : if( poOpenInfo->nHeaderBytes < 2 )
952 8292 : return NULL;
953 :
954 : /* -------------------------------------------------------------------- */
955 : /* Now we need to tear apart the filename to form a .HDR */
956 : /* filename. */
957 : /* -------------------------------------------------------------------- */
958 380 : CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
959 380 : CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
960 380 : CPLString osHDRFilename;
961 :
962 380 : if( poOpenInfo->papszSiblingFiles )
963 : {
964 : int iFile = CSLFindString(poOpenInfo->papszSiblingFiles,
965 348 : CPLFormFilename( NULL, osName, "hdr" ) );
966 348 : if( iFile < 0 ) // return if there is no corresponding .hdr file
967 281 : return NULL;
968 :
969 : osHDRFilename =
970 67 : CPLFormFilename( osPath, poOpenInfo->papszSiblingFiles[iFile],
971 134 : NULL );
972 : }
973 : else
974 : {
975 32 : osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
976 : }
977 :
978 99 : bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
979 :
980 : /* -------------------------------------------------------------------- */
981 : /* Do we have a .hdr file? */
982 : /* -------------------------------------------------------------------- */
983 : FILE *fp;
984 :
985 99 : fp = VSIFOpenL( osHDRFilename, "r" );
986 :
987 99 : if( fp == NULL )
988 : {
989 29 : return NULL;
990 : }
991 :
992 : /* -------------------------------------------------------------------- */
993 : /* Is this file an ESRI header file? Read a few lines of text */
994 : /* searching for something starting with nrows or ncols. */
995 : /* -------------------------------------------------------------------- */
996 : const char * pszLine;
997 70 : int nRows = -1, nCols = -1, nBands = 1;
998 70 : int nSkipBytes = 0;
999 70 : double dfULXMap=0.5, dfULYMap = 0.5, dfYLLCorner = -123.456;
1000 70 : int bCenter = TRUE;
1001 70 : double dfXDim = 1.0, dfYDim = 1.0, dfNoData = 0.0;
1002 70 : int nLineCount = 0, bNoDataSet = FALSE;
1003 70 : GDALDataType eDataType = GDT_Byte;
1004 70 : int nBits = -1;
1005 70 : char chByteOrder = 'M';
1006 70 : char chPixelType = 'N'; // not defined
1007 70 : char szLayout[10] = "BIL";
1008 70 : char **papszHDR = NULL;
1009 :
1010 795 : while( (pszLine = CPLReadLineL( fp )) )
1011 : {
1012 : char **papszTokens;
1013 :
1014 655 : nLineCount++;
1015 :
1016 655 : if( nLineCount > 50 || strlen(pszLine) > 1000 )
1017 0 : break;
1018 :
1019 655 : papszHDR = CSLAddString( papszHDR, pszLine );
1020 :
1021 655 : papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
1022 655 : if( CSLCount( papszTokens ) < 2 )
1023 : {
1024 44 : CSLDestroy( papszTokens );
1025 44 : continue;
1026 : }
1027 :
1028 611 : if( EQUAL(papszTokens[0],"ncols") )
1029 : {
1030 45 : nCols = atoi(papszTokens[1]);
1031 : }
1032 566 : else if( EQUAL(papszTokens[0],"nrows") )
1033 : {
1034 45 : nRows = atoi(papszTokens[1]);
1035 : }
1036 521 : else if( EQUAL(papszTokens[0],"skipbytes") )
1037 : {
1038 0 : nSkipBytes = atoi(papszTokens[1]);
1039 : }
1040 1549 : else if( EQUAL(papszTokens[0],"ulxmap")
1041 507 : || EQUAL(papszTokens[0],"xllcorner")
1042 507 : || EQUAL(papszTokens[0],"xllcenter") )
1043 : {
1044 14 : dfULXMap = atof(papszTokens[1]);
1045 14 : if( EQUAL(papszTokens[0],"xllcorner") )
1046 0 : bCenter = FALSE;
1047 : }
1048 507 : else if( EQUAL(papszTokens[0],"ulymap") )
1049 : {
1050 14 : dfULYMap = atof(papszTokens[1]);
1051 : }
1052 986 : else if( EQUAL(papszTokens[0],"yllcorner")
1053 493 : || EQUAL(papszTokens[0],"yllcenter") )
1054 : {
1055 0 : dfYLLCorner = atof(papszTokens[1]);
1056 0 : if( EQUAL(papszTokens[0],"yllcorner") )
1057 0 : bCenter = FALSE;
1058 : }
1059 493 : else if( EQUAL(papszTokens[0],"xdim") )
1060 : {
1061 14 : dfXDim = atof(papszTokens[1]);
1062 : }
1063 479 : else if( EQUAL(papszTokens[0],"ydim") )
1064 : {
1065 14 : dfYDim = atof(papszTokens[1]);
1066 : }
1067 465 : else if( EQUAL(papszTokens[0],"cellsize") )
1068 : {
1069 0 : dfXDim = dfYDim = atof(papszTokens[1]);
1070 : }
1071 465 : else if( EQUAL(papszTokens[0],"nbands") )
1072 : {
1073 45 : nBands = atoi(papszTokens[1]);
1074 : }
1075 420 : else if( EQUAL(papszTokens[0],"layout") )
1076 : {
1077 45 : strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
1078 45 : szLayout[sizeof(szLayout)-1] = '\0';
1079 : }
1080 752 : else if( EQUAL(papszTokens[0],"NODATA_value")
1081 375 : || EQUAL(papszTokens[0],"NODATA") )
1082 : {
1083 2 : dfNoData = atof(papszTokens[1]);
1084 2 : bNoDataSet = TRUE;
1085 : }
1086 373 : else if( EQUAL(papszTokens[0],"NBITS") )
1087 : {
1088 45 : nBits = atoi(papszTokens[1]);
1089 : }
1090 328 : else if( EQUAL(papszTokens[0],"PIXELTYPE") )
1091 : {
1092 45 : chPixelType = toupper(papszTokens[1][0]);
1093 : }
1094 283 : else if( EQUAL(papszTokens[0],"byteorder") )
1095 : {
1096 45 : chByteOrder = toupper(papszTokens[1][0]);
1097 : }
1098 :
1099 611 : CSLDestroy( papszTokens );
1100 : }
1101 :
1102 70 : VSIFCloseL( fp );
1103 :
1104 : /* -------------------------------------------------------------------- */
1105 : /* Did we get the required keywords? If not we return with */
1106 : /* this never having been considered to be a match. This isn't */
1107 : /* an error! */
1108 : /* -------------------------------------------------------------------- */
1109 70 : if( nRows == -1 || nCols == -1 )
1110 : {
1111 25 : CSLDestroy( papszHDR );
1112 25 : return NULL;
1113 : }
1114 :
1115 45 : if (!GDALCheckDatasetDimensions(nCols, nRows) ||
1116 : !GDALCheckBandCount(nBands, FALSE))
1117 : {
1118 0 : CSLDestroy( papszHDR );
1119 0 : return NULL;
1120 : }
1121 :
1122 : /* -------------------------------------------------------------------- */
1123 : /* Has the user selected the .hdr file to open? */
1124 : /* -------------------------------------------------------------------- */
1125 45 : if( bSelectedHDR )
1126 : {
1127 : CPLError( CE_Failure, CPLE_AppDefined,
1128 : "The selected file is an ESRI BIL header file, but to\n"
1129 : "open ESRI BIL datasets, the data file should be selected\n"
1130 : "instead of the .hdr file. Please try again selecting\n"
1131 : "the data file (often with the extension .bil) corresponding\n"
1132 : "to the header file: %s\n",
1133 0 : poOpenInfo->pszFilename );
1134 0 : CSLDestroy( papszHDR );
1135 0 : return NULL;
1136 : }
1137 :
1138 45 : if( nBits == -1 && chPixelType == 'N' )
1139 : {
1140 : VSIStatBufL sStatBuf;
1141 0 : if( VSIStatL( poOpenInfo->pszFilename, &sStatBuf ) == 0 )
1142 : {
1143 0 : size_t nBytes = sStatBuf.st_size/nCols/nRows/nBands;
1144 0 : if( nBytes > 0 && nBytes != 3 )
1145 0 : nBits = nBytes*8;
1146 :
1147 0 : if( nBytes == 4 )
1148 0 : chPixelType = 'F';
1149 : }
1150 : }
1151 :
1152 : /* -------------------------------------------------------------------- */
1153 : /* Create a corresponding GDALDataset. */
1154 : /* -------------------------------------------------------------------- */
1155 : EHdrDataset *poDS;
1156 :
1157 45 : poDS = new EHdrDataset();
1158 :
1159 : /* -------------------------------------------------------------------- */
1160 : /* Capture some information from the file that is of interest. */
1161 : /* -------------------------------------------------------------------- */
1162 45 : poDS->nRasterXSize = nCols;
1163 45 : poDS->nRasterYSize = nRows;
1164 45 : poDS->papszHDR = papszHDR;
1165 :
1166 : /* -------------------------------------------------------------------- */
1167 : /* Open target binary file. */
1168 : /* -------------------------------------------------------------------- */
1169 45 : if( poOpenInfo->eAccess == GA_ReadOnly )
1170 18 : poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
1171 : else
1172 27 : poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
1173 :
1174 45 : if( poDS->fpImage == NULL )
1175 : {
1176 : CPLError( CE_Failure, CPLE_OpenFailed,
1177 : "Failed to open %s with write permission.\n%s",
1178 0 : osName.c_str(), VSIStrerror( errno ) );
1179 0 : delete poDS;
1180 0 : return NULL;
1181 : }
1182 :
1183 45 : poDS->eAccess = poOpenInfo->eAccess;
1184 :
1185 45 : if( chPixelType == 'N' )
1186 : {
1187 0 : if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "FLT" ) )
1188 0 : chPixelType = 'F';
1189 : }
1190 :
1191 : /* -------------------------------------------------------------------- */
1192 : /* Figure out the data type. */
1193 : /* -------------------------------------------------------------------- */
1194 45 : if( nBits == 16 )
1195 : {
1196 7 : if ( chPixelType == 'S' )
1197 2 : eDataType = GDT_Int16;
1198 : else
1199 5 : eDataType = GDT_UInt16; // default
1200 : }
1201 38 : else if( nBits == 32 )
1202 : {
1203 20 : if( chPixelType == 'S' )
1204 5 : eDataType = GDT_Int32;
1205 15 : else if( chPixelType == 'F' )
1206 13 : eDataType = GDT_Float32;
1207 : else
1208 2 : eDataType = GDT_UInt32; // default
1209 : }
1210 18 : else if( nBits == 8 )
1211 : {
1212 18 : eDataType = GDT_Byte;
1213 18 : nBits = 8;
1214 : }
1215 0 : else if( nBits < 8 && nBits >= 1 )
1216 0 : eDataType = GDT_Byte;
1217 0 : else if( nBits == -1 )
1218 : {
1219 0 : if( chPixelType == 'F' )
1220 : {
1221 0 : eDataType = GDT_Float32;
1222 0 : nBits = 32;
1223 : }
1224 : else
1225 : {
1226 0 : eDataType = GDT_Byte;
1227 0 : nBits = 8;
1228 : }
1229 : }
1230 : else
1231 : {
1232 : CPLError( CE_Failure, CPLE_NotSupported,
1233 : "EHdr driver does not support %d NBITS value.",
1234 0 : nBits );
1235 0 : delete poDS;
1236 0 : return NULL;
1237 : }
1238 :
1239 : /* -------------------------------------------------------------------- */
1240 : /* Compute the line offset. */
1241 : /* -------------------------------------------------------------------- */
1242 45 : int nItemSize = GDALGetDataTypeSize(eDataType)/8;
1243 : int nPixelOffset, nLineOffset;
1244 : vsi_l_offset nBandOffset;
1245 :
1246 45 : if( EQUAL(szLayout,"BIP") )
1247 : {
1248 0 : nPixelOffset = nItemSize * nBands;
1249 0 : nLineOffset = nPixelOffset * nCols;
1250 0 : nBandOffset = (vsi_l_offset)nItemSize;
1251 : }
1252 45 : else if( EQUAL(szLayout,"BSQ") )
1253 : {
1254 0 : nPixelOffset = nItemSize;
1255 0 : nLineOffset = nPixelOffset * nCols;
1256 0 : nBandOffset = (vsi_l_offset)nLineOffset * nRows;
1257 : }
1258 : else /* assume BIL */
1259 : {
1260 45 : nPixelOffset = nItemSize;
1261 45 : nLineOffset = nItemSize * nBands * nCols;
1262 45 : nBandOffset = (vsi_l_offset)nItemSize * nCols;
1263 : }
1264 :
1265 45 : poDS->SetDescription( poOpenInfo->pszFilename );
1266 45 : poDS->PamInitialize();
1267 :
1268 : /* -------------------------------------------------------------------- */
1269 : /* Create band information objects. */
1270 : /* -------------------------------------------------------------------- */
1271 45 : poDS->nBands = nBands;
1272 116 : for( i = 0; i < poDS->nBands; i++ )
1273 : {
1274 : EHdrRasterBand *poBand;
1275 :
1276 : poBand =
1277 : new EHdrRasterBand( poDS, i+1, poDS->fpImage,
1278 : nSkipBytes + nBandOffset * i,
1279 : nPixelOffset, nLineOffset, eDataType,
1280 : #ifdef CPL_LSB
1281 : chByteOrder == 'I' || chByteOrder == 'L',
1282 : #else
1283 : chByteOrder == 'M',
1284 : #endif
1285 71 : nBits);
1286 :
1287 71 : if( bNoDataSet )
1288 2 : poBand->SetNoDataValue( dfNoData );
1289 :
1290 71 : poDS->SetBand( i+1, poBand );
1291 : }
1292 :
1293 : /* -------------------------------------------------------------------- */
1294 : /* If we didn't get bounds in the .hdr, look for a worldfile. */
1295 : /* -------------------------------------------------------------------- */
1296 45 : if( dfYLLCorner != -123.456 )
1297 : {
1298 0 : if( bCenter )
1299 0 : dfULYMap = dfYLLCorner + (nRows-1) * dfYDim;
1300 : else
1301 0 : dfULYMap = dfYLLCorner + nRows * dfYDim;
1302 : }
1303 :
1304 45 : if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
1305 : {
1306 14 : poDS->bGotTransform = TRUE;
1307 :
1308 14 : if( bCenter )
1309 : {
1310 14 : poDS->adfGeoTransform[0] = dfULXMap - dfXDim * 0.5;
1311 14 : poDS->adfGeoTransform[1] = dfXDim;
1312 14 : poDS->adfGeoTransform[2] = 0.0;
1313 14 : poDS->adfGeoTransform[3] = dfULYMap + dfYDim * 0.5;
1314 14 : poDS->adfGeoTransform[4] = 0.0;
1315 14 : poDS->adfGeoTransform[5] = - dfYDim;
1316 : }
1317 : else
1318 : {
1319 0 : poDS->adfGeoTransform[0] = dfULXMap;
1320 0 : poDS->adfGeoTransform[1] = dfXDim;
1321 0 : poDS->adfGeoTransform[2] = 0.0;
1322 0 : poDS->adfGeoTransform[3] = dfULYMap;
1323 0 : poDS->adfGeoTransform[4] = 0.0;
1324 0 : poDS->adfGeoTransform[5] = - dfYDim;
1325 : }
1326 : }
1327 :
1328 45 : if( !poDS->bGotTransform )
1329 : poDS->bGotTransform =
1330 : GDALReadWorldFile( poOpenInfo->pszFilename, 0,
1331 31 : poDS->adfGeoTransform );
1332 :
1333 45 : if( !poDS->bGotTransform )
1334 : poDS->bGotTransform =
1335 : GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
1336 31 : poDS->adfGeoTransform );
1337 :
1338 : /* -------------------------------------------------------------------- */
1339 : /* Check for a .prj file. */
1340 : /* -------------------------------------------------------------------- */
1341 45 : const char *pszPrjFilename = CPLFormCIFilename( osPath, osName, "prj" );
1342 :
1343 45 : fp = VSIFOpenL( pszPrjFilename, "r" );
1344 45 : if( fp != NULL )
1345 : {
1346 : char **papszLines;
1347 13 : OGRSpatialReference oSRS;
1348 :
1349 13 : VSIFCloseL( fp );
1350 :
1351 13 : papszLines = CSLLoad( pszPrjFilename );
1352 :
1353 13 : if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
1354 : {
1355 : // If geographic values are in seconds, we must transform.
1356 : // Is there a code for minutes too?
1357 : char szResult[80];
1358 13 : if( oSRS.IsGeographic()
1359 : && EQUAL(OSR_GDS( szResult, sizeof(szResult),
1360 : papszLines, "Units", ""), "DS") )
1361 : {
1362 0 : poDS->adfGeoTransform[0] /= 3600.0;
1363 0 : poDS->adfGeoTransform[1] /= 3600.0;
1364 0 : poDS->adfGeoTransform[2] /= 3600.0;
1365 0 : poDS->adfGeoTransform[3] /= 3600.0;
1366 0 : poDS->adfGeoTransform[4] /= 3600.0;
1367 0 : poDS->adfGeoTransform[5] /= 3600.0;
1368 : }
1369 :
1370 13 : CPLFree( poDS->pszProjection );
1371 13 : oSRS.exportToWkt( &(poDS->pszProjection) );
1372 : }
1373 :
1374 13 : CSLDestroy( papszLines );
1375 : }
1376 : else
1377 : {
1378 : /* -------------------------------------------------------------------- */
1379 : /* Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep */
1380 : /* if it's a GIS-GeoSPOT image */
1381 : /* For the specification of SPDF (in French), */
1382 : /* see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
1383 : /* -------------------------------------------------------------------- */
1384 32 : CPLString pszImageRepFilename = GetImageRepFilename(poOpenInfo->pszFilename );
1385 32 : if (pszImageRepFilename[0])
1386 : {
1387 0 : fp = VSIFOpenL( (const char*)pszImageRepFilename, "r" );
1388 : }
1389 32 : if (fp != NULL)
1390 : {
1391 : const char *pszLine;
1392 0 : int bUTM = FALSE;
1393 0 : int bWGS84 = FALSE;
1394 0 : int bNorth = FALSE;
1395 0 : int bSouth = FALSE;
1396 0 : int utmZone = 0;
1397 :
1398 0 : while( (pszLine = CPLReadLineL( fp )) )
1399 : {
1400 0 : if (strncmp(pszLine, "PROJ_ID", strlen("PROJ_ID")) == 0 &&
1401 : strstr(pszLine, "UTM"))
1402 : {
1403 0 : bUTM = TRUE;
1404 : }
1405 0 : else if (strncmp(pszLine, "PROJ_ZONE", strlen("PROJ_ZONE")) == 0)
1406 : {
1407 0 : const char* c = strchr(pszLine, '"');
1408 0 : if (c)
1409 : {
1410 0 : c++;
1411 0 : if (*c >= '0' && *c <= '9')
1412 : {
1413 0 : utmZone = atoi(c);
1414 0 : if (utmZone >= 1 && utmZone <= 60)
1415 : {
1416 0 : if (strstr(pszLine, "Nord") || strstr(pszLine, "NORD"))
1417 : {
1418 0 : bNorth = TRUE;
1419 : }
1420 0 : else if (strstr(pszLine, "Sud") || strstr(pszLine, "SUD"))
1421 : {
1422 0 : bSouth = TRUE;
1423 : }
1424 : }
1425 : }
1426 : }
1427 : }
1428 0 : else if (strncmp(pszLine, "PROJ_CODE", strlen("PROJ_CODE")) == 0 &&
1429 : strstr(pszLine, "FR-MINDEF"))
1430 : {
1431 0 : const char* c = strchr(pszLine, 'A');
1432 0 : if (c)
1433 : {
1434 0 : c++;
1435 0 : if (*c >= '0' && *c <= '9')
1436 : {
1437 0 : utmZone = atoi(c);
1438 0 : if (utmZone >= 1 && utmZone <= 60)
1439 : {
1440 0 : if (c[1] == 'N' ||
1441 0 : (c[1] != '\0' && c[2] == 'N'))
1442 : {
1443 0 : bNorth = TRUE;
1444 : }
1445 0 : else if (c[1] == 'S' ||
1446 0 : (c[1] != '\0' && c[2] == 'S'))
1447 : {
1448 0 : bSouth = TRUE;
1449 : }
1450 : }
1451 : }
1452 : }
1453 : }
1454 0 : else if (strncmp(pszLine, "HORIZ_DATUM", strlen("HORIZ_DATUM")) == 0 &&
1455 : (strstr(pszLine, "WGS 84") || strstr(pszLine, "WGS84")))
1456 : {
1457 0 : bWGS84 = TRUE;
1458 : }
1459 0 : else if (strncmp(pszLine, "MAP_NUMBER", strlen("MAP_NUMBER")) == 0)
1460 : {
1461 0 : const char* c = strchr(pszLine, '"');
1462 0 : if (c)
1463 : {
1464 0 : char* pszMapNumber = CPLStrdup(c+1);
1465 0 : char* c2 = strchr(pszMapNumber, '"');
1466 0 : if (c2) *c2 = 0;
1467 0 : poDS->SetMetadataItem("SPDF_MAP_NUMBER", pszMapNumber);
1468 0 : CPLFree(pszMapNumber);
1469 : }
1470 : }
1471 0 : else if (strncmp(pszLine, "PRODUCTION_DATE", strlen("PRODUCTION_DATE")) == 0)
1472 : {
1473 0 : const char* c = pszLine + strlen("PRODUCTION_DATE");
1474 0 : while(*c == ' ')
1475 0 : c++;
1476 0 : if (*c)
1477 : {
1478 0 : poDS->SetMetadataItem("SPDF_PRODUCTION_DATE", c );
1479 : }
1480 : }
1481 : }
1482 :
1483 0 : VSIFCloseL( fp );
1484 :
1485 0 : if (utmZone != 0 && bUTM && bWGS84 && (bNorth || bSouth))
1486 : {
1487 : char projCSStr[64];
1488 0 : OGRSpatialReference oSRS;
1489 :
1490 : sprintf(projCSStr, "WGS 84 / UTM zone %d%c",
1491 0 : utmZone, (bNorth) ? 'N' : 'S');
1492 0 : oSRS.SetProjCS(projCSStr);
1493 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
1494 0 : oSRS.SetUTM(utmZone, bNorth);
1495 0 : oSRS.SetAuthority("PROJCS", "EPSG", ((bNorth) ? 32600 : 32700) + utmZone);
1496 0 : oSRS.AutoIdentifyEPSG();
1497 :
1498 0 : CPLFree( poDS->pszProjection );
1499 0 : oSRS.exportToWkt( &(poDS->pszProjection) );
1500 : }
1501 : else
1502 : {
1503 0 : CPLError( CE_Warning, CPLE_NotSupported, "Cannot retrive projection from IMAGE.REP");
1504 : }
1505 32 : }
1506 : }
1507 :
1508 : /* -------------------------------------------------------------------- */
1509 : /* Check for a color table. */
1510 : /* -------------------------------------------------------------------- */
1511 45 : const char *pszCLRFilename = CPLFormCIFilename( osPath, osName, "clr" );
1512 :
1513 : /* Only read the .clr for byte, int16 or uint16 bands */
1514 45 : if (nItemSize <= 2)
1515 25 : fp = VSIFOpenL( pszCLRFilename, "r" );
1516 : else
1517 20 : fp = NULL;
1518 :
1519 45 : if( fp != NULL )
1520 : {
1521 2 : GDALColorTable oColorTable;
1522 2 : int bHasWarned = FALSE;
1523 :
1524 8 : while(TRUE)
1525 : {
1526 10 : const char *pszLine = CPLReadLineL(fp);
1527 10 : if ( !pszLine )
1528 : break;
1529 :
1530 8 : if( *pszLine == '#' || *pszLine == '!' )
1531 0 : continue;
1532 :
1533 : char **papszValues = CSLTokenizeString2(pszLine, "\t ",
1534 8 : CSLT_HONOURSTRINGS);
1535 : GDALColorEntry oEntry;
1536 :
1537 8 : if ( CSLCount(papszValues) >= 4 )
1538 : {
1539 8 : int nIndex = atoi( papszValues[0] ); // Index
1540 16 : if (nIndex >= 0 && nIndex < 65536)
1541 : {
1542 8 : oEntry.c1 = atoi( papszValues[1] ); // Red
1543 8 : oEntry.c2 = atoi( papszValues[2] ); // Green
1544 8 : oEntry.c3 = atoi( papszValues[3] ); // Blue
1545 8 : oEntry.c4 = 255;
1546 :
1547 8 : oColorTable.SetColorEntry( nIndex, &oEntry );
1548 : }
1549 : else
1550 : {
1551 : /* Negative values are valid. At least we can find use of */
1552 : /* them here : http://www.ngdc.noaa.gov/mgg/topo/elev/esri/clr/ */
1553 : /* but there's no way of representing them with GDAL color */
1554 : /* table model */
1555 0 : if (!bHasWarned)
1556 0 : CPLDebug("EHdr", "Ignoring color index : %d", nIndex);
1557 0 : bHasWarned = TRUE;
1558 : }
1559 : }
1560 :
1561 8 : CSLDestroy( papszValues );
1562 : }
1563 :
1564 2 : VSIFCloseL( fp );
1565 :
1566 4 : for( i = 1; i <= poDS->nBands; i++ )
1567 : {
1568 2 : GDALRasterBand *poBand = poDS->GetRasterBand( i );
1569 2 : poBand->SetColorTable( &oColorTable );
1570 2 : poBand->SetColorInterpretation( GCI_PaletteIndex );
1571 : }
1572 :
1573 2 : poDS->bCLRDirty = FALSE;
1574 : }
1575 :
1576 : /* -------------------------------------------------------------------- */
1577 : /* Read statistics (.STX) */
1578 : /* -------------------------------------------------------------------- */
1579 45 : poDS->ReadSTX();
1580 :
1581 : /* -------------------------------------------------------------------- */
1582 : /* Initialize any PAM information. */
1583 : /* -------------------------------------------------------------------- */
1584 45 : poDS->TryLoadXML();
1585 :
1586 : /* -------------------------------------------------------------------- */
1587 : /* Check for overviews. */
1588 : /* -------------------------------------------------------------------- */
1589 45 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1590 :
1591 45 : return( poDS );
1592 : }
1593 :
1594 : /************************************************************************/
1595 : /* Create() */
1596 : /************************************************************************/
1597 :
1598 38 : GDALDataset *EHdrDataset::Create( const char * pszFilename,
1599 : int nXSize, int nYSize, int nBands,
1600 : GDALDataType eType,
1601 : char **papszParmList )
1602 :
1603 : {
1604 : /* -------------------------------------------------------------------- */
1605 : /* Verify input options. */
1606 : /* -------------------------------------------------------------------- */
1607 38 : if (nBands <= 0)
1608 : {
1609 : CPLError( CE_Failure, CPLE_NotSupported,
1610 1 : "EHdr driver does not support %d bands.\n", nBands);
1611 1 : return NULL;
1612 : }
1613 :
1614 37 : if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
1615 : && eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_UInt32 )
1616 : {
1617 : CPLError( CE_Failure, CPLE_AppDefined,
1618 : "Attempt to create ESRI .hdr labelled dataset with an illegal\n"
1619 : "data type (%s).\n",
1620 10 : GDALGetDataTypeName(eType) );
1621 :
1622 10 : return NULL;
1623 : }
1624 :
1625 : /* -------------------------------------------------------------------- */
1626 : /* Try to create the file. */
1627 : /* -------------------------------------------------------------------- */
1628 : FILE *fp;
1629 :
1630 27 : fp = VSIFOpenL( pszFilename, "wb" );
1631 :
1632 27 : if( fp == NULL )
1633 : {
1634 : CPLError( CE_Failure, CPLE_OpenFailed,
1635 : "Attempt to create file `%s' failed.\n",
1636 0 : pszFilename );
1637 0 : return NULL;
1638 : }
1639 :
1640 : /* -------------------------------------------------------------------- */
1641 : /* Just write out a couple of bytes to establish the binary */
1642 : /* file, and then close it. */
1643 : /* -------------------------------------------------------------------- */
1644 27 : VSIFWriteL( (void *) "\0\0", 2, 1, fp );
1645 27 : VSIFCloseL( fp );
1646 :
1647 : /* -------------------------------------------------------------------- */
1648 : /* Create the hdr filename. */
1649 : /* -------------------------------------------------------------------- */
1650 : char *pszHdrFilename;
1651 :
1652 : pszHdrFilename =
1653 27 : CPLStrdup( CPLResetExtension( pszFilename, "hdr" ) );
1654 :
1655 : /* -------------------------------------------------------------------- */
1656 : /* Open the file. */
1657 : /* -------------------------------------------------------------------- */
1658 27 : fp = VSIFOpenL( pszHdrFilename, "wt" );
1659 27 : if( fp == NULL )
1660 : {
1661 : CPLError( CE_Failure, CPLE_OpenFailed,
1662 : "Attempt to create file `%s' failed.\n",
1663 0 : pszHdrFilename );
1664 0 : CPLFree( pszHdrFilename );
1665 0 : return NULL;
1666 : }
1667 :
1668 : /* -------------------------------------------------------------------- */
1669 : /* Decide how many bits the file should have. */
1670 : /* -------------------------------------------------------------------- */
1671 : int nRowBytes;
1672 27 : int nBits = GDALGetDataTypeSize(eType);
1673 :
1674 27 : if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
1675 0 : nBits = atoi(CSLFetchNameValue( papszParmList, "NBITS" ));
1676 :
1677 27 : nRowBytes = (nBits * nXSize + 7) / 8;
1678 :
1679 : /* -------------------------------------------------------------------- */
1680 : /* Check for signed byte. */
1681 : /* -------------------------------------------------------------------- */
1682 27 : const char *pszPixelType = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
1683 27 : if( pszPixelType == NULL )
1684 26 : pszPixelType = "";
1685 :
1686 : /* -------------------------------------------------------------------- */
1687 : /* Write out the raw definition for the dataset as a whole. */
1688 : /* -------------------------------------------------------------------- */
1689 27 : VSIFPrintfL( fp, "BYTEORDER I\n" );
1690 27 : VSIFPrintfL( fp, "LAYOUT BIL\n" );
1691 27 : VSIFPrintfL( fp, "NROWS %d\n", nYSize );
1692 27 : VSIFPrintfL( fp, "NCOLS %d\n", nXSize );
1693 27 : VSIFPrintfL( fp, "NBANDS %d\n", nBands );
1694 27 : VSIFPrintfL( fp, "NBITS %d\n", nBits );
1695 27 : VSIFPrintfL( fp, "BANDROWBYTES %d\n", nRowBytes );
1696 27 : VSIFPrintfL( fp, "TOTALROWBYTES %d\n", nRowBytes * nBands );
1697 :
1698 27 : if( eType == GDT_Float32 )
1699 4 : VSIFPrintfL( fp, "PIXELTYPE FLOAT\n");
1700 28 : else if( eType == GDT_Int16 || eType == GDT_Int32 )
1701 5 : VSIFPrintfL( fp, "PIXELTYPE SIGNEDINT\n");
1702 19 : else if( eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE") )
1703 1 : VSIFPrintfL( fp, "PIXELTYPE SIGNEDINT\n");
1704 : else
1705 17 : VSIFPrintfL( fp, "PIXELTYPE UNSIGNEDINT\n");
1706 :
1707 : /* -------------------------------------------------------------------- */
1708 : /* Cleanup */
1709 : /* -------------------------------------------------------------------- */
1710 27 : VSIFCloseL( fp );
1711 :
1712 27 : CPLFree( pszHdrFilename );
1713 :
1714 27 : return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
1715 : }
1716 :
1717 : /************************************************************************/
1718 : /* CreateCopy() */
1719 : /************************************************************************/
1720 :
1721 21 : GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename,
1722 : GDALDataset * poSrcDS,
1723 : int bStrict, char ** papszOptions,
1724 : GDALProgressFunc pfnProgress,
1725 : void * pProgressData )
1726 :
1727 : {
1728 21 : char **papszAdjustedOptions = CSLDuplicate( papszOptions );
1729 : GDALDataset *poOutDS;
1730 :
1731 21 : int nBands = poSrcDS->GetRasterCount();
1732 21 : if (nBands == 0)
1733 : {
1734 : CPLError( CE_Failure, CPLE_NotSupported,
1735 1 : "EHdr driver does not support source dataset with zero band.\n");
1736 1 : return NULL;
1737 : }
1738 :
1739 : /* -------------------------------------------------------------------- */
1740 : /* Ensure we pass on NBITS and PIXELTYPE structure information. */
1741 : /* -------------------------------------------------------------------- */
1742 40 : if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
1743 20 : "IMAGE_STRUCTURE" ) !=NULL
1744 : && CSLFetchNameValue( papszOptions, "NBITS" ) == NULL )
1745 : {
1746 : papszAdjustedOptions =
1747 : CSLSetNameValue( papszAdjustedOptions,
1748 : "NBITS",
1749 0 : poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS","IMAGE_STRUCTURE") );
1750 : }
1751 :
1752 40 : if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE",
1753 20 : "IMAGE_STRUCTURE" ) !=NULL
1754 : && CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL )
1755 : {
1756 : papszAdjustedOptions =
1757 : CSLSetNameValue( papszAdjustedOptions,
1758 : "PIXELTYPE",
1759 1 : poSrcDS->GetRasterBand(1)->GetMetadataItem("PIXELTYPE","IMAGE_STRUCTURE") );
1760 : }
1761 :
1762 : /* -------------------------------------------------------------------- */
1763 : /* Proceed with normal copying using the default createcopy */
1764 : /* operators. */
1765 : /* -------------------------------------------------------------------- */
1766 20 : GDALDriver *poDriver = (GDALDriver *) GDALGetDriverByName( "EHdr" );
1767 :
1768 : poOutDS = poDriver->DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
1769 : papszAdjustedOptions,
1770 20 : pfnProgress, pProgressData );
1771 20 : CSLDestroy( papszAdjustedOptions );
1772 :
1773 20 : return poOutDS;
1774 : }
1775 :
1776 : /************************************************************************/
1777 : /* GetMinimum() */
1778 : /************************************************************************/
1779 :
1780 0 : double EHdrRasterBand::GetMinimum( int *pbSuccess )
1781 : {
1782 0 : if( pbSuccess != NULL )
1783 0 : *pbSuccess = (minmaxmeanstddev & 0x1) != 0;
1784 :
1785 0 : if( minmaxmeanstddev & 0x1 )
1786 0 : return dfMin;
1787 :
1788 0 : return RawRasterBand::GetMinimum( pbSuccess );
1789 : }
1790 :
1791 : /************************************************************************/
1792 : /* GetMaximum() */
1793 : /************************************************************************/
1794 :
1795 0 : double EHdrRasterBand::GetMaximum( int *pbSuccess )
1796 : {
1797 0 : if( pbSuccess != NULL )
1798 0 : *pbSuccess = (minmaxmeanstddev & 0x2) != 0;
1799 :
1800 0 : if( minmaxmeanstddev & 0x2 )
1801 0 : return dfMax;
1802 :
1803 0 : return RawRasterBand::GetMaximum( pbSuccess );
1804 : }
1805 :
1806 : /************************************************************************/
1807 : /* GetStatistics() */
1808 : /************************************************************************/
1809 :
1810 0 : CPLErr EHdrRasterBand::GetStatistics( int bApproxOK, int bForce, double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
1811 : {
1812 0 : if( (minmaxmeanstddev & 0xf) == 0xf)
1813 : {
1814 0 : if ( pdfMin ) *pdfMin = dfMin;
1815 0 : if ( pdfMax ) *pdfMax = dfMax;
1816 0 : if ( pdfMean ) *pdfMean = dfMean;
1817 0 : if ( pdfStdDev ) *pdfStdDev = dfStdDev;
1818 0 : return CE_None;
1819 : }
1820 :
1821 : CPLErr eErr = RawRasterBand::GetStatistics( bApproxOK, bForce,
1822 : &dfMin, &dfMax,
1823 0 : &dfMean, &dfStdDev );
1824 :
1825 0 : if( eErr == CE_None )
1826 : {
1827 0 : EHdrDataset* poEDS = (EHdrDataset *) poDS;
1828 :
1829 0 : minmaxmeanstddev = 0xf;
1830 :
1831 0 : if( poEDS->RewriteSTX() != CE_None )
1832 0 : RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
1833 :
1834 0 : if( pdfMin )
1835 0 : *pdfMin = dfMin;
1836 0 : if( pdfMax )
1837 0 : *pdfMax = dfMax;
1838 0 : if( pdfMean )
1839 0 : *pdfMean = dfMean;
1840 0 : if( pdfStdDev )
1841 0 : *pdfStdDev = dfStdDev;
1842 : }
1843 :
1844 0 : return eErr;
1845 : }
1846 :
1847 : /************************************************************************/
1848 : /* SetStatistics() */
1849 : /************************************************************************/
1850 :
1851 0 : CPLErr EHdrRasterBand::SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev )
1852 : {
1853 : // avoid churn if nothing is changing.
1854 0 : if( dfMin == this->dfMin
1855 : && dfMax == this->dfMax
1856 : && dfMean == this->dfMean
1857 : && dfStdDev == this->dfStdDev )
1858 0 : return CE_None;
1859 :
1860 0 : this->dfMin = dfMin;
1861 0 : this->dfMax = dfMax;
1862 0 : this->dfMean = dfMean;
1863 0 : this->dfStdDev = dfStdDev;
1864 :
1865 : // marks stats valid
1866 0 : minmaxmeanstddev = 0xf;
1867 :
1868 0 : EHdrDataset* poEDS = (EHdrDataset *) poDS;
1869 :
1870 0 : if( poEDS->RewriteSTX() != CE_None )
1871 0 : return RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
1872 : else
1873 0 : return CE_None;
1874 : }
1875 :
1876 : /************************************************************************/
1877 : /* SetColorTable() */
1878 : /************************************************************************/
1879 :
1880 3 : CPLErr EHdrRasterBand::SetColorTable( GDALColorTable *poNewCT )
1881 : {
1882 3 : CPLErr err = RawRasterBand::SetColorTable( poNewCT );
1883 3 : if( err != CE_None )
1884 0 : return err;
1885 :
1886 3 : ((EHdrDataset*)poDS)->bCLRDirty = TRUE;
1887 :
1888 3 : return CE_None;
1889 : }
1890 :
1891 : /************************************************************************/
1892 : /* GDALRegister_EHdr() */
1893 : /************************************************************************/
1894 :
1895 338 : void GDALRegister_EHdr()
1896 :
1897 : {
1898 : GDALDriver *poDriver;
1899 :
1900 338 : if( GDALGetDriverByName( "EHdr" ) == NULL )
1901 : {
1902 336 : poDriver = new GDALDriver();
1903 :
1904 336 : poDriver->SetDescription( "EHdr" );
1905 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1906 336 : "ESRI .hdr Labelled" );
1907 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1908 336 : "frmt_various.html#EHdr" );
1909 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1910 336 : "Byte Int16 UInt16 Int32 UInt32 Float32" );
1911 :
1912 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1913 : "<CreationOptionList>"
1914 : " <Option name='NBITS' type='int' description='Special pixel bits (1-7)'/>"
1915 : " <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
1916 336 : "</CreationOptionList>" );
1917 :
1918 336 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1919 336 : poDriver->pfnOpen = EHdrDataset::Open;
1920 336 : poDriver->pfnCreate = EHdrDataset::Create;
1921 336 : poDriver->pfnCreateCopy = EHdrDataset::CreateCopy;
1922 :
1923 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
1924 : }
1925 338 : }
|