[gdal-dev] ENVI driver patch

Wilson Waters "gdal-dev-list-mail" at alintech.com.au
Tue May 13 19:28:25 PDT 2014


Hi all,

I've been working with ENVI files lately and have come across a few 
issues. I'm hoping you can point out if I'm doing something wrong or if 
I should create a GDAL bug with the attached patch.

We found our ENVI .hdr files were being corrupted whenever opened in 
write mode with GDAL. No changes to the data or metadata are required to 
corrupt the file, simply opening the file in write mode was enough. I've 
attached example before and after .hdr files. These files have map info 
projection set to "Arbitrary" (we're not storing map data. It's long 
skinny images of underground drill core).

This is the process causing the corruption in ENVIDataset:
1) open envi file in read/write mode uses OPEN_EXISTING flag on .hdr
2) ENVIDataset::Open() doesn't understand "Arbitrary" projection so 
generates a "LOCAL_CS" projection string
3) close dataset causing ENVIDataset::FlushCache() to be called
4) FlushCache() re-writes hdr file as the bHeaderDirty was set in the 
Open() function. map info field is omitted for some reason?
5) FlushCache() overwrites the old hdr file without clearing first 
causing trailing data in the file

As far as I can tell there are four bugs in the ENVIDataset related to this
1) ENVIDataset::ProcessMapinfo() Doesn't understand the "Arbitrary" 
projection and defaults to LOCAL_CS - which is probably ok, but;
2) ENVIDataset::WriteProjectionInfo fails to write map info field when 
projection is LOCAL_CS
3) ENVIDataset::Open() causes bHeaderDirty to be set (should only happen 
when something external updates the image?)
4) ENVIDataset::FlushCache() should truncate existing file before 
overwriting

We're using GDAL 1.11 on windows, though I think the behaviour would be 
the same on any OS.

Any pointers on whether I'm doing the right thing and if I should submit 
a trac bug?

Cheers,
Wilson.
-------------- next part --------------
ENVI
description = {
C:\bad.bin}
samples = 58
lines   = 1967
bands   = 1
header offset = 0
file type = ENVI Standard
data type = 4
interleave = bsq
byte order = 0
band names = {
example band name}
5, -81.68, 0.0005, 0.0005, 0, North}

band names = {

example band name}

-------------- next part --------------
ENVI
description = {
C:\good.bin}
samples = 58
lines   = 1967
bands   = 1
header offset = 0
file type = ENVI Standard
data type = 4
interleave = bsq
byte order = 0
map info = {Arbitrary, 1, 1, -0.0145, -81.68, 0.0005, 0.0005, 0, North}
band names = {
example band name}
-------------- next part --------------
Index: envidataset.cpp
===================================================================
--- envidataset.cpp	(revision 1427)
+++ envidataset.cpp	(working copy)
@@ -370,6 +370,12 @@
 
     CPLLocaleC  oLocaleEnforcer;
 
+    //ww bugfix
+    // If opening an existing file in Update mode (i.e. "r+") we need to make
+    // sure any existing content is cleared, otherwise the file may contain 
+    // trailing content from the previous write.
+    VSIFTruncateL( fp, 0 );
+
     VSIFSeekL( fp, 0, SEEK_SET );
 /* -------------------------------------------------------------------- */
 /*      Rewrite out the header.                                           */
@@ -668,14 +674,14 @@
 /*      Minimal case - write out simple geotransform if we have a       */
 /*      non-default geotransform.                                       */
 /* -------------------------------------------------------------------- */
-    if( pszProjection == NULL || strlen(pszProjection) == 0 )
+    if( pszProjection == NULL || strlen(pszProjection) == 0 || (strlen(pszProjection) >= 8 && strncmp(pszProjection, "LOCAL_CS", 8) != 0 ) )
     {
         if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
             || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
             || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 )
         {
             const char* pszHemisphere = "North";
-            VSIFPrintfL( fp, "map info = {Unknown, %s, %d, %s}\n",
+            VSIFPrintfL( fp, "map info = {Arbitrary, %s, %d, %s}\n",
                          osLocation.c_str(), 0, pszHemisphere);
         }
         return;
@@ -2504,6 +2510,11 @@
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
+    //ww bug fix.
+    // SetMetadata() calls in Open() makes the header dirty.
+    // Don't re-write the header if nothing external has changed the metadata
+    poDS->bHeaderDirty = FALSE;
+
     return( poDS );
 }
 


More information about the gdal-dev mailing list