[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