Opened 16 years ago

Closed 16 years ago

#2243 closed defect (fixed)

Two differences between GDAL's AUX files and ESRI's AUX files.

Reported by: mrosen Owned by: warmerdam
Priority: high Milestone: 1.5.3
Component: GDAL_Raster Version: unspecified
Severity: normal Keywords: HFA
Cc: gaopeng

Description

While doing more work on an “ESRI Aux file writer” feature, we found that the “out of the box” behavior of GDAL’s HFA driver was inadequate for our purposes. Since I presume the intent of the “AUX” switch used by this driver is to write ESRI aux files, I submit this patch for your consideration (recognizing that it's an Imagine HFA driver, not an ESRI AUX driver).

We were working on 1.4.2 but also investigated 1.4esri and 1.5 … I think the behavior is the same on all branches.

The Problem.

While working on the ArcGIS / LT Express Server Plugin, we found that ArcGIS did not always read the CRS / Extent information correctly. Sometime yes, sometimes no. Almost always the second time we tried. This is true to varying degrees for both ArcGIS 9.1 and 9.2. However, we found that by staging an 9.2SP4-generated Aux file with the image pointer (“IRL file”) then all was well. Our solution was to write the AUX files ourselves using GDAL’s HFA driver and the AUX switch. I attach an exchange with Peng Gao that contains more information / examples. Unfortunately the currently implementation of the HFA driver did not get us what we needed. By comparing the 9.2SP4-generated files with those generated by GDAL, we found two differences we believe solve the problem

  1. ArcGIS likes the CRS information to be repeated for each layer. GDAL only writes it to the first layer (and only reads it from the first layer).
  1. ArcGIS seems not to understand the various projections that GDAL “Recognizes”. It requires a PE String instead (which is what GDAL writes if it can’t recognize the projection).

We need to point out that there are still differences between what 9.2sp4 writes and what this patch writes. However, our testing suggests that this may be adequate.

===================== LT’s patches to GDAL to Address this

--- xt_lib_gdal/src/gdal-1.4.2/frmts/hfa/hfadataset.cpp	2007/09/27 22:16:12	1.2
+++ xt_lib_gdal/src/gdal-1.4.2/frmts/hfa/hfadataset.cpp	2008/02/12 00:01:38	1.2.2.2
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfadataset.cpp,v 1.2 2007/09/27 22:16:12 mrosen Exp $
+ * $Id: hfadataset.cpp,v 1.2.2.2 2008/02/12 00:01:38 mrosen Exp $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -33,7 +33,7 @@
 #include "hfa_p.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hfadataset.cpp,v 1.2 2007/09/27 22:16:12 mrosen Exp $");
+CPL_CVSID("$Id: hfadataset.cpp,v 1.2.2.2 2008/02/12 00:01:38 mrosen Exp $");
 
 CPL_C_START
 void	GDALRegister_HFA(void);
@@ -270,6 +270,7 @@ class CPL_DLL HFADataset : public GDALPa
 
     CPLErr      ReadProjection();
     CPLErr      WriteProjection();
+    bool        bForceToPEString;
 
   protected:
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
@@ -1270,6 +1271,8 @@ HFADataset::HFADataset()
     pszProjection = CPLStrdup("");
     this->bMetadataDirty = FALSE;
     bIgnoreUTM = FALSE;
+    bForceToPEString = FALSE;
+
 }
 
 /************************************************************************/
@@ -1411,13 +1414,22 @@ CPLErr HFADataset::WriteProjection()
     if( bHaveSRS )
         pszProjName = oSRS.GetAttrValue( "PROJCS|PROJECTION" );
 
-    if( pszProjName == NULL )
+    if (bForceToPEString)
     {
-        if( bHaveSRS && oSRS.IsGeographic() )
-        {
-            sPro.proNumber = EPRJ_LATLONG;
-            sPro.proName = "Geographic (Lat/Lon)";
-        }
+      char *pszPEString = NULL;
+      oSRS.morphToESRI();
+      oSRS.exportToWkt( &pszPEString );
+      // need to transform this into ESRI format.
+      HFASetPEString( hHFA, pszPEString );
+      CPLFree( pszPEString );
+    }
+    else if( pszProjName == NULL )
+    {
+       if (bHaveSRS && oSRS.IsGeographic() )
+       {
+           sPro.proNumber = EPRJ_LATLONG;
+           sPro.proName = "Geographic (Lat/Lon)";
+       }
     }
 
     /* FIXME/NOTDEF/TODO: Add State Plane */
@@ -2539,6 +2551,8 @@ GDALDataset *HFADataset::Create( const c
     {
         poDS->bIgnoreUTM = CSLFetchBoolean( papszParmList, "IGNOREUTM",
                                             FALSE );
+        poDS->bForceToPEString = CSLFetchBoolean( papszParmList, "FORCETOPESTRING",
+                                            FALSE );
     }
 
     return poDS;



--- xt_lib_gdal/src/gdal-1.4.2/frmts/hfa/hfaopen.cpp	2007/08/06 21:55:18	1.1.1.1
+++ xt_lib_gdal/src/gdal-1.4.2/frmts/hfa/hfaopen.cpp	2008/02/07 20:32:56	1.1.1.1.6.1
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaopen.cpp,v 1.1.1.1 2007/08/06 21:55:18 mrosen Exp $
+ * $Id: hfaopen.cpp,v 1.1.1.1.6.1 2008/02/07 20:32:56 mrosen Exp $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Supporting functions for HFA (.img) ... main (C callable) API
@@ -41,7 +41,7 @@
 //#include "gdal_alg.h"
 #include <limits.h>
 
-CPL_CVSID("$Id: hfaopen.cpp,v 1.1.1.1 2007/08/06 21:55:18 mrosen Exp $");
+CPL_CVSID("$Id: hfaopen.cpp,v 1.1.1.1.6.1 2008/02/07 20:32:56 mrosen Exp $");
 
 
 static char *apszAuxMetadataItems[] = {
@@ -1126,10 +1126,15 @@ CPLErr HFASetPEString( HFAHandle hHFA, c
 /* -------------------------------------------------------------------- */
     if( hHFA->nBands == 0 )
         return CE_None;
+/* -------------------------------------------------------------------- */
+/*      Loop over bands, setting information on each one.               */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
+    {
 
     HFAEntry *poProX;
 
-    poProX = hHFA->papoBand[0]->poNode->GetNamedChild( "ProjectionX" );
+    poProX = hHFA->papoBand[iBand]->poNode->GetNamedChild( "ProjectionX" );
     if( poProX != NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1142,7 +1147,7 @@ CPLErr HFASetPEString( HFAHandle hHFA, c
 /*      Create the node.                                                */
 /* -------------------------------------------------------------------- */
     poProX = new HFAEntry( hHFA, "ProjectionX","Eprj_MapProjection842",
-                           hHFA->papoBand[0]->poNode );
+                           hHFA->papoBand[iBand]->poNode );
     if( poProX == NULL )
         return CE_Failure;
 
@@ -1212,7 +1217,7 @@ CPLErr HFASetPEString( HFAHandle hHFA, c
     memcpy( pabyData, pszPEString, strlen(pszPEString)+1 );
     
     poProX->SetStringField( "title.string", "PE" );
-
+    }
     return CE_None;
 }

Attachments (1)

RE How to write ESRI Aux files from GDAL 15698.msg (98.5 KB ) - added by mrosen 16 years ago.
email & attachment

Download all attachments as: .zip

Change History (4)

by mrosen, 16 years ago

email & attachment

comment:1 by warmerdam, 16 years ago

Cc: gaopeng added
Component: defaultGDAL_Raster
Keywords: HFA added
Milestone: 1.5.3
Priority: normalhigh
Status: newassigned

Bump priority - I plan to address for 1.5.3.

comment:2 by warmerdam, 16 years ago

I'm unable to read the .msg file with Outlook or anything else I've tried. I'm going to pursue issue (1) (writing the coordinate system info for each layer), but I'd like some confirmation on the other issue of always writing a PE string. I'm concerned this may interfere with Imagine interoperability.

comment:3 by warmerdam, 16 years ago

Resolution: fixed
Status: assignedclosed

On reflection, the FORCETOPESTRING stuff only has an effect when explicitly requested, so I have decided it is safe to apply.

I have manually applied the patch in trunk (r15341) and 1.5 branch (r15342).

I have not added a test suite item as it is tricky examining how the internals of the .aux file are getting set.

I'm concerned that FORCETOPESTRING is still left as a sort of poorly understood creation option hack. I'd appreciate understanding better when it is appropriate and whether we ought to be writing more coordinate systems as PE strings by default.

Note: See TracTickets for help on using tickets.