LCOV - code coverage report
Current view: directory - frmts/adrg - adrgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1217 1042 85.6 %
Date: 2010-01-09 Functions: 42 42 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: adrgdataset.cpp 18407 2009-12-28 16:15:36Z rouault $
       3                 :  *
       4                 :  * Purpose:  ADRG reader
       5                 :  * Author:   Even Rouault, even.rouault at mines-paris.org
       6                 :  *
       7                 :  ******************************************************************************
       8                 :  * Copyright (c) 2007, Even Rouault
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  ****************************************************************************/
      28                 : 
      29                 : #include "gdal_pam.h"
      30                 : #include "ogr_spatialref.h"
      31                 : #include "cpl_string.h"
      32                 : #include "iso8211.h"
      33                 : 
      34                 : CPL_CVSID("$Id: adrgdataset.cpp 18407 2009-12-28 16:15:36Z rouault $");
      35                 : 
      36                 : #define N_ELEMENTS(x)  (sizeof(x)/sizeof(x[0]))
      37                 : 
      38                 : class ADRGDataset : public GDALPamDataset
      39                 : {
      40                 :     friend class ADRGRasterBand;
      41                 :     
      42                 :     CPLString    osGENFileName;
      43                 :     CPLString    osIMGFileName;
      44                 : 
      45                 :     FILE*        fdIMG;
      46                 :     int*         TILEINDEX;
      47                 :     int          offsetInIMG;
      48                 :     int          NFC;
      49                 :     int          NFL;
      50                 :     double       LSO;
      51                 :     double       PSO;
      52                 :     int          ARV;
      53                 :     int          BRV;
      54                 : 
      55                 :     char**       papszSubDatasets;
      56                 :     
      57                 :     ADRGDataset* poOverviewDS;
      58                 :     
      59                 :     /* For creation */
      60                 :     int          bCreation;
      61                 :     FILE*        fdGEN;
      62                 :     FILE*        fdTHF;
      63                 :     int          bGeoTransformValid;
      64                 :     double       adfGeoTransform[6];
      65                 :     int          nNextAvailableBlock;
      66                 :     CPLString    osBaseFileName;
      67                 :     
      68                 :     static char** GetGENListFromTHF(const char* pszFileName);
      69                 :     static char** GetIMGListFromGEN(const char* pszFileName, int* pnRecordIndex = NULL);
      70                 :     static ADRGDataset* OpenDataset(const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record = NULL);
      71                 :     static DDFRecord*  FindRecordInGENForIMG(DDFModule& module,
      72                 :                                              const char* pszGENFileName, const char* pszIMGFileName);
      73                 : 
      74                 :   public:
      75                 :                  ADRGDataset();
      76                 :     virtual     ~ADRGDataset();
      77                 :     
      78                 :     virtual const char *GetProjectionRef(void);
      79                 :     virtual CPLErr GetGeoTransform( double * padfGeoTransform );
      80                 :     virtual CPLErr SetGeoTransform( double * padfGeoTransform );
      81                 : 
      82                 :     virtual char      **GetMetadata( const char * pszDomain = "" );
      83                 :     
      84                 :     virtual char      **GetFileList();
      85                 : 
      86                 :     void                AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
      87                 : 
      88                 :     static GDALDataset *Open( GDALOpenInfo * );
      89                 :     static GDALDataset *Create(const char* pszFilename, int nXSize, int nYSize,
      90                 :                                int nBands, GDALDataType eType, char **papszOptions);
      91                 :     
      92                 :     static double GetLongitudeFromString(const char* str);
      93                 :     static double GetLatitudeFromString(const char* str);
      94                 :     
      95                 :     void WriteGENFile();
      96                 :     void WriteTHFFile();
      97                 : };
      98                 : 
      99                 : /************************************************************************/
     100                 : /* ==================================================================== */
     101                 : /*                            ADRGRasterBand                             */
     102                 : /* ==================================================================== */
     103                 : /************************************************************************/
     104                 : 
     105                 : class ADRGRasterBand : public GDALPamRasterBand
     106              78 : {
     107                 :     friend class ADRGDataset;
     108                 : 
     109                 :   public:
     110                 :                             ADRGRasterBand( ADRGDataset *, int );
     111                 : 
     112                 :     virtual GDALColorInterp GetColorInterpretation();
     113                 :     virtual CPLErr          IReadBlock( int, int, void * );
     114                 :     virtual CPLErr          IWriteBlock( int, int, void * );
     115                 : 
     116                 :     virtual double          GetNoDataValue( int *pbSuccess = NULL );
     117                 : 
     118                 : //    virtual int             GetOverviewCount();
     119                 : //    virtual GDALRasterBand* GetOverview(int i);
     120                 : };
     121                 : 
     122                 : 
     123                 : /************************************************************************/
     124                 : /*                           ADRGRasterBand()                            */
     125                 : /************************************************************************/
     126                 : 
     127              39 : ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDS, int nBand )
     128                 : 
     129                 : {
     130              39 :     this->poDS = poDS;
     131              39 :     this->nBand = nBand;
     132                 :     
     133              39 :     eDataType = GDT_Byte;
     134                 : 
     135              39 :     nBlockXSize = 128;
     136              39 :     nBlockYSize = 128;
     137              39 : }
     138                 : 
     139                 : #if 0
     140                 : 
     141                 : /* We have a problem with the overview. Its geo bounding box doesn't match */
     142                 : /* exactly the one of the main image. We should handle the shift between */
     143                 : /* the two top level corners... */
     144                 : 
     145                 : /************************************************************************/
     146                 : /*                          GetOverviewCount()                          */
     147                 : /************************************************************************/
     148                 : 
     149                 : int ADRGRasterBand::GetOverviewCount()
     150                 : 
     151                 : {
     152                 :     ADRGDataset* poDS = (ADRGDataset*)this->poDS;
     153                 :     if( poDS->poOverviewDS )
     154                 :         return 1;
     155                 :     else
     156                 :         return GDALRasterBand::GetOverviewCount();
     157                 : }
     158                 : 
     159                 : /************************************************************************/
     160                 : /*                            GetOverview()                             */
     161                 : /************************************************************************/
     162                 : 
     163                 : GDALRasterBand *ADRGRasterBand::GetOverview( int i )
     164                 : 
     165                 : {
     166                 :     ADRGDataset* poDS = (ADRGDataset*)this->poDS;
     167                 :     if( poDS->poOverviewDS )
     168                 :     {
     169                 :         if( i < 0 || i >= 1 )
     170                 :             return NULL;
     171                 :         else
     172                 :             return poDS->poOverviewDS->GetRasterBand(nBand);
     173                 :     }
     174                 :     else
     175                 :         return GDALRasterBand::GetOverview( i );
     176                 : }
     177                 : #endif
     178                 : 
     179                 : /************************************************************************/
     180                 : /*                            GetNoDataValue()                          */
     181                 : /************************************************************************/
     182                 : 
     183              27 : double  ADRGRasterBand::GetNoDataValue( int *pbSuccess )
     184                 : {
     185              27 :     if (pbSuccess)
     186              18 :         *pbSuccess = TRUE;
     187                 : 
     188              27 :     return 0;
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                       GetColorInterpretation()                       */
     193                 : /************************************************************************/
     194                 : 
     195              27 : GDALColorInterp ADRGRasterBand::GetColorInterpretation()
     196                 : 
     197                 : {
     198              27 :     if( nBand == 1 )
     199               9 :         return GCI_RedBand;
     200                 : 
     201              18 :     else if( nBand == 2 )
     202               9 :         return GCI_GreenBand;
     203                 : 
     204                 :     else 
     205               9 :         return GCI_BlueBand;
     206                 : }
     207                 : 
     208                 : /************************************************************************/
     209                 : /*                             IReadBlock()                             */
     210                 : /************************************************************************/
     211                 : 
     212              14 : CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     213                 :                                   void * pImage )
     214                 : 
     215                 : {
     216              14 :     ADRGDataset* poDS = (ADRGDataset*)this->poDS;
     217                 :     int offset;
     218              14 :     int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
     219              14 :     if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
     220                 :     {
     221                 :         CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
     222               0 :                  nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
     223               0 :         return CE_Failure;
     224                 :     }
     225              14 :     CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
     226                 : 
     227              14 :     if (poDS->TILEINDEX)
     228                 :     {
     229              14 :         if (poDS->TILEINDEX[nBlock] == 0)
     230                 :         {
     231               0 :             memset(pImage, 0, 128 * 128);
     232               0 :             return CE_None;
     233                 :         }
     234              14 :         offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
     235                 :     }
     236                 :     else
     237               0 :         offset = poDS->offsetInIMG + nBlock * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
     238                 :     
     239              14 :     if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
     240                 :     {
     241               0 :         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
     242               0 :         return CE_Failure;
     243                 :     }
     244              14 :     if (VSIFReadL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
     245                 :     {
     246               0 :         CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
     247               0 :         return CE_Failure;
     248                 :     }
     249                 :     
     250              14 :     return CE_None;
     251                 : }
     252                 : 
     253                 : /************************************************************************/
     254                 : /*                            IWriteBlock()                             */
     255                 : /************************************************************************/
     256                 : 
     257               9 : CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     258                 :                                   void * pImage )
     259                 : 
     260                 : {
     261               9 :     ADRGDataset* poDS = (ADRGDataset*)this->poDS;
     262                 :     int offset;
     263               9 :     int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
     264               9 :     if (poDS->eAccess != GA_Update)
     265                 :     {
     266               0 :         return CE_Failure;
     267                 :     }
     268               9 :     if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
     269                 :     {
     270                 :         CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
     271               0 :                  nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
     272               0 :         return CE_Failure;
     273                 :     }
     274               9 :     CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
     275                 :     
     276               9 :     if (poDS->TILEINDEX[nBlock] == 0)
     277                 :     {
     278                 :         unsigned int i;
     279               3 :         int* pi = (int*)pImage;
     280               3 :         for(i=0;i<128*128 / sizeof(int);i++)
     281                 :         {
     282               3 :             if (pi[i])
     283               3 :                 break;
     284                 :         }
     285               3 :         if (i == 128*128 / sizeof(int))
     286                 :         {
     287               0 :             return CE_None;
     288                 :         }
     289                 : 
     290               3 :         poDS->TILEINDEX[nBlock] = poDS->nNextAvailableBlock ++;
     291                 :     }
     292                 : 
     293               9 :     offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
     294                 : 
     295               9 :     if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
     296                 :     {
     297               0 :         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
     298               0 :         return CE_Failure;
     299                 :     }
     300               9 :     if (VSIFWriteL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
     301                 :     {
     302               0 :         CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
     303               0 :         return CE_Failure;
     304                 :     }
     305                 : 
     306               9 :     return CE_None;
     307                 : }
     308                 : 
     309             204 : static unsigned int WriteSubFieldStr(FILE* fd, const char* pszStr, unsigned int size)
     310                 : {
     311             204 :     char* str = (char*)CPLMalloc(size+1);
     312             204 :     memset(str, ' ', size);
     313             204 :     if (strlen(pszStr) > size)
     314                 :     {
     315               0 :         CPLError(CE_Failure, CPLE_AppDefined, "strlen(pszStr) > size");
     316               0 :         CPLFree(str);
     317               0 :         return size;
     318                 :     }
     319             204 :     strcpy(str, pszStr);
     320             204 :     str[strlen(pszStr)] = ' ';
     321             204 :     VSIFWriteL(str, 1, size, fd);
     322             204 :     CPLFree(str);
     323             204 :     return size;
     324                 : }
     325                 : 
     326             625 : static unsigned int WriteSubFieldInt(FILE* fd, int val, unsigned int size)
     327                 : {
     328             625 :     char* str = (char*)CPLMalloc(size+1);
     329                 :     char formatStr[32];
     330             625 :     sprintf( formatStr, "%%0%dd", size);
     331             625 :     sprintf( str, formatStr, val);
     332             625 :     VSIFWriteL(str, 1, size, fd);
     333             625 :     CPLFree(str);
     334             625 :     return size;
     335                 : }
     336                 : 
     337             212 : static unsigned int WriteFieldTerminator(FILE* fd)
     338                 : {
     339             212 :     char fieldTerminator = 30;
     340             212 :     VSIFWriteL(&fieldTerminator, 1, 1, fd);
     341             212 :     return 1;
     342                 : }
     343                 : 
     344             126 : static unsigned int WriteUnitTerminator(FILE* fd)
     345                 : {
     346             126 :     char fieldTerminator = 31;
     347             126 :     VSIFWriteL(&fieldTerminator, 1, 1, fd);
     348             126 :     return 1;
     349                 : }
     350                 : 
     351              29 : static unsigned int WriteLongitude(FILE* fd, double val)
     352                 : {
     353                 :     char str[11+1];
     354              29 :     char sign = (val >= 0) ? '+' : '-';
     355              29 :     if (val < 0) val = -val;
     356              29 :     int ddd = (int)val;
     357              29 :     int mm = (int)((val - ddd) * 60);
     358              29 :     double ssdotss = ((val - ddd) * 60 - mm) * 60;
     359              29 :     sprintf(str, "%c%03d%02d%02.2f", sign, ddd, mm, ssdotss);
     360              29 :     VSIFWriteL(str, 1, 11, fd);
     361              29 :     return 11;
     362                 : }
     363                 : 
     364              29 : static unsigned int WriteLatitude(FILE* fd, double val)
     365                 : {
     366                 :     char str[10+1];
     367              29 :     char sign = (val >= 0) ? '+' : '-';
     368              29 :     if (val < 0) val = -val;
     369              29 :     int dd = (int)val;
     370              29 :     int mm = (int)((val - dd) * 60);
     371              29 :     double ssdotss = ((val - dd) * 60 - mm) * 60;
     372              29 :     sprintf(str, "%c%02d%02d%02.2f", sign, dd, mm, ssdotss);
     373              29 :     VSIFWriteL(str, 1, 10, fd);
     374              29 :     return 10;
     375                 : }
     376                 : 
     377              25 : static int BeginLeader(FILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
     378                 :                        int nFields)
     379                 : {
     380              25 :     int pos = (int)VSIFTellL(fd);
     381              25 :     VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * (vsi_l_offset)nFields + 1, SEEK_CUR);
     382              25 :     return pos;
     383                 : }
     384                 : 
     385              25 : static void FinishWriteLeader(FILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
     386                 :                              int nFields, int* sizeOfFields, const char** nameOfFields)
     387                 : {
     388              25 :     int endPos = (int)VSIFTellL(fd);
     389              25 :     VSIFSeekL(fd, beginPos, SEEK_SET);
     390                 :     
     391              25 :     int nLeaderSize = 24;
     392                 :     char szLeader[24+1];
     393              25 :     memset(szLeader, ' ', nLeaderSize);
     394                 :     
     395                 :     int i;
     396              25 :     int nDataSize = 0;
     397              25 :     int nFieldOffset = 0;
     398             131 :     for(i=0;i<nFields;i++)
     399             106 :         nDataSize += sizeOfFields[i];
     400              25 :     nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
     401              25 :     nDataSize += nFieldOffset;
     402                 :     
     403              25 :     sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
     404              25 :     szLeader[5] = ' ';
     405              25 :     szLeader[6] = 'D';
     406                 :     
     407              25 :     sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
     408              25 :     szLeader[17] = ' ';
     409                 : 
     410              25 :     szLeader[20] = (char) ('0' + sizeFieldLength);
     411              25 :     szLeader[21] = (char) ('0' + sizeFieldPos);
     412              25 :     szLeader[22] = '0';
     413              25 :     szLeader[23] = (char) ('0' + sizeFieldTag);
     414                 : 
     415              25 :     VSIFWriteL(szLeader, 1, nLeaderSize, fd);
     416                 :     
     417              25 :     int acc = 0;
     418             131 :     for(i=0;i<nFields;i++)
     419                 :     {
     420             106 :         VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
     421             106 :         WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
     422             106 :         WriteSubFieldInt(fd, acc, sizeFieldPos);
     423             106 :         acc += sizeOfFields[i];
     424                 :     }
     425              25 :     WriteFieldTerminator(fd);
     426                 :     
     427              25 :     VSIFSeekL(fd, endPos, SEEK_SET);
     428              25 : }
     429                 : 
     430                 : 
     431               9 : static int BeginHeader(FILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
     432                 :                        int nFields)
     433                 : {
     434               9 :     int pos = (int)VSIFTellL(fd);
     435               9 :     VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1, SEEK_CUR);
     436               9 :     return pos;
     437                 : }
     438                 : 
     439               9 : static void FinishWriteHeader(FILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
     440                 :                              int nFields, int* sizeOfFields, const char** nameOfFields)
     441                 : {
     442               9 :     int endPos = (int)VSIFTellL(fd);
     443               9 :     VSIFSeekL(fd, beginPos, SEEK_SET);
     444                 :     
     445               9 :     int nLeaderSize = 24;
     446                 :     char szLeader[24+1];
     447               9 :     memset(szLeader, ' ', nLeaderSize);
     448                 :     
     449                 :     int i;
     450               9 :     int nDataSize = 0;
     451               9 :     int nFieldOffset = 0;
     452              81 :     for(i=0;i<nFields;i++)
     453              72 :         nDataSize += sizeOfFields[i];
     454               9 :     nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
     455               9 :     nDataSize += nFieldOffset;
     456                 :     
     457               9 :     sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
     458               9 :     szLeader[5] = '2';
     459               9 :     szLeader[6] = 'L';
     460                 :     
     461               9 :     szLeader[10] = '0';
     462               9 :     szLeader[11] = '6';
     463               9 :     sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
     464               9 :     szLeader[17] = ' ';
     465                 : 
     466               9 :     szLeader[20] = (char) ('0' + sizeFieldLength);
     467               9 :     szLeader[21] = (char) ('0' + sizeFieldPos);
     468               9 :     szLeader[22] = '0';
     469               9 :     szLeader[23] = (char) ('0' + sizeFieldTag);
     470                 : 
     471               9 :     VSIFWriteL(szLeader, 1, nLeaderSize, fd);
     472                 :     
     473               9 :     int acc = 0;
     474              81 :     for(i=0;i<nFields;i++)
     475                 :     {
     476              72 :         VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
     477              72 :         WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
     478              72 :         WriteSubFieldInt(fd, acc, sizeFieldPos);
     479              72 :         acc += sizeOfFields[i];
     480                 :     }
     481               9 :     WriteFieldTerminator(fd);
     482                 :     
     483               9 :     VSIFSeekL(fd, endPos, SEEK_SET);
     484               9 : }
     485                 : 
     486              72 : static int WriteFieldDecl(FILE* fd, char _data_struct_code , char _data_type_code, const char* _fieldName,
     487                 :                            const char* _arrayDescr, const char* _formatControls)
     488                 : {
     489              72 :     VSIFWriteL(&_data_struct_code, 1, 1, fd);
     490              72 :     VSIFWriteL(&_data_type_code, 1, 1, fd);
     491              72 :     if (_data_struct_code == ' ')
     492                 :     {
     493               9 :         VSIFWriteL("    ", 1 , 4, fd);
     494                 :     }
     495                 :     else
     496                 :     {
     497              63 :         VSIFWriteL("00;&", 1 , 4, fd);
     498                 :     }
     499              72 :     int len = 6;
     500              72 :     VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd);
     501              72 :     len += strlen(_fieldName);
     502              72 :     if (_arrayDescr[0])
     503                 :     {
     504              63 :         len += WriteUnitTerminator(fd);
     505              63 :         VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd);
     506              63 :         len += strlen(_arrayDescr);
     507                 : 
     508              63 :         len += WriteUnitTerminator(fd);
     509              63 :         VSIFWriteL(_formatControls, 1, strlen(_formatControls), fd);
     510              63 :         len += strlen(_formatControls);
     511                 :     }
     512              72 :     len += WriteFieldTerminator(fd);
     513              72 :     return len;
     514                 : }
     515                 : 
     516                 : 
     517                 : /************************************************************************/
     518                 : /*                          ADRGDataset()                               */
     519                 : /************************************************************************/
     520                 : 
     521              14 : ADRGDataset::ADRGDataset()
     522                 : {
     523              14 :     bCreation = FALSE;
     524              14 :     poOverviewDS = NULL;
     525              14 :     fdIMG = NULL;
     526              14 :     fdGEN = NULL;
     527              14 :     fdTHF = NULL;
     528              14 :     TILEINDEX = NULL;
     529              14 :     papszSubDatasets = NULL;
     530              14 : }
     531                 : 
     532                 : /************************************************************************/
     533                 : /*                          ~ADRGDataset()                              */
     534                 : /************************************************************************/
     535                 : 
     536              28 : ADRGDataset::~ADRGDataset()
     537                 : {
     538              14 :     if (poOverviewDS)
     539                 :     {
     540               0 :         delete poOverviewDS;
     541                 :     }
     542                 :     
     543              14 :     CSLDestroy(papszSubDatasets);
     544                 :     
     545              14 :     if (bCreation)
     546                 :     {
     547               3 :         GDALPamDataset::FlushCache();
     548                 :         
     549                 :         /* Write header and padding of image */
     550               3 :         VSIFSeekL(fdIMG, 0, SEEK_SET);
     551                 :         {
     552               3 :             FILE* fd = fdIMG;
     553               3 :             int nFields = 0;
     554               3 :             int sizeOfFields[] = { 0, 0, 0, 0 };
     555               3 :             const char* nameOfFields[] = { "000", "001", "PAD", "SCN" };
     556               3 :             int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
     557                 :     
     558               3 :             sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GEO_DATA_FILE", "", ""); /* 000 */
     559                 :             sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
     560                 :                                                     "RTY!RID",
     561               3 :                                                     "(A(3),A(2))");
     562                 :             sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "PADDING_FIELD", /* PAD */
     563                 :                                                     "PAD",
     564               3 :                                                     "(A)");
     565                 :             sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '0', "PIXEL_FIELD", /* SCN */
     566                 :                                                     "*PIX",
     567               3 :                                                     "(A(1))");
     568                 :     
     569               3 :             FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
     570                 :             
     571                 :             /* Write IMAGE_RECORD */
     572                 :             {
     573               3 :                 int nFields = 0;
     574               3 :                 int sizeOfFields[] = {0, 0, 0};
     575               3 :                 const char* nameOfFields[] = { "001", "PAD", "SCN" };
     576               3 :                 int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
     577                 :         
     578                 :                 /* Field 001 */
     579               3 :                 sizeOfFields[nFields] += WriteSubFieldStr(fd, "IMG", 3); /* RTY */
     580               3 :                 sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
     581               3 :                 sizeOfFields[nFields] += WriteFieldTerminator(fd);
     582               3 :                 nFields++;
     583                 :         
     584                 :                 /* Field PAD */
     585               3 :                 int endPos = (int)VSIFTellL(fd);
     586               3 :                 char* pad = (char*)CPLMalloc(2047 - endPos);
     587               3 :                 memset(pad, ' ', 2047 - endPos);
     588               3 :                 VSIFWriteL(pad, 1, 2047 - endPos, fd);
     589               3 :                 CPLFree(pad);
     590               3 :                 WriteFieldTerminator(fd);
     591               3 :                 sizeOfFields[nFields] += 2047 - endPos + 1;
     592               3 :                 nFields++;
     593                 :                 
     594                 :                 /* Field SCN */
     595               3 :                 sizeOfFields[nFields] = (nNextAvailableBlock - 1) * 128 * 128 * 3;
     596               3 :                 nFields++;
     597                 :         
     598               3 :                 FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
     599                 :             }
     600                 :         }
     601                 : 
     602                 :         /* Write terminal field terminator */
     603               3 :         int offset = offsetInIMG + (nNextAvailableBlock - 1) * 128 * 128 * 3;
     604               3 :         VSIFSeekL(fdIMG, offset, SEEK_SET);
     605               3 :         WriteFieldTerminator(fdIMG);
     606                 :         
     607               3 :         WriteGENFile();
     608               3 :         WriteTHFFile();
     609                 :     }
     610                 : 
     611              14 :     if (fdIMG)
     612                 :     {
     613              13 :         VSIFCloseL(fdIMG);
     614                 :     }
     615                 :     
     616              14 :     if (fdGEN)
     617                 :     {
     618               3 :         VSIFCloseL(fdGEN);
     619                 :     }
     620              14 :     if (fdTHF)
     621                 :     {
     622               3 :         VSIFCloseL(fdTHF);
     623                 :     }
     624                 : 
     625              14 :     if (TILEINDEX)
     626                 :     {
     627              13 :         delete [] TILEINDEX;
     628                 :     }
     629              28 : }
     630                 : 
     631                 : /************************************************************************/
     632                 : /*                            GetFileList()                             */
     633                 : /************************************************************************/
     634                 : 
     635               2 : char ** ADRGDataset::GetFileList()
     636                 : {
     637               2 :     char** papszFileList = GDALPamDataset::GetFileList();
     638                 :     
     639               2 :     if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
     640                 :     {
     641               2 :         CPLString osMainFilename = GetDescription();
     642                 :         int bMainFileReal;
     643                 :         VSIStatBufL  sStat;
     644                 : 
     645               2 :         bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
     646               2 :         if (bMainFileReal)
     647                 :         {
     648               2 :             CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
     649               2 :             CPLString osShortGENFileName = CPLGetFilename(osGENFileName);
     650               2 :             if ( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
     651               0 :                 papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
     652                 :         }
     653                 :         else
     654               0 :             papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
     655                 :         
     656               2 :         papszFileList = CSLAddString(papszFileList, osIMGFileName.c_str());
     657                 :     }
     658                 :     
     659               2 :     return papszFileList;
     660                 : }
     661                 : 
     662                 : /************************************************************************/
     663                 : /*                           AddSubDataset()                            */
     664                 : /************************************************************************/
     665                 : 
     666               2 : void ADRGDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName )
     667                 : {
     668                 :     char  szName[80];
     669               2 :     int   nCount = CSLCount(papszSubDatasets ) / 2;
     670                 :     
     671               2 :     CPLString osSubDatasetName;
     672               2 :     osSubDatasetName = "ADRG:";
     673               2 :     osSubDatasetName += pszGENFileName;
     674               2 :     osSubDatasetName += ",";
     675               2 :     osSubDatasetName += pszIMGFileName;
     676                 : 
     677               2 :     sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
     678                 :     papszSubDatasets = 
     679               2 :         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
     680                 : 
     681               2 :     sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
     682                 :     papszSubDatasets = 
     683               2 :         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
     684               2 : }
     685                 : 
     686                 : /************************************************************************/
     687                 : /*                            GetMetadata()                             */
     688                 : /************************************************************************/
     689                 : 
     690              10 : char **ADRGDataset::GetMetadata( const char *pszDomain )
     691                 : 
     692                 : {
     693              10 :     if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
     694               0 :         return papszSubDatasets;
     695                 : 
     696              10 :     return GDALPamDataset::GetMetadata( pszDomain );
     697                 : }
     698                 : 
     699                 : /************************************************************************/
     700                 : /*                        GetProjectionRef()                            */
     701                 : /************************************************************************/
     702                 : 
     703               9 : const char* ADRGDataset::GetProjectionRef()
     704                 : {
     705               9 :     return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
     706                 : }
     707                 : 
     708                 : /************************************************************************/
     709                 : /*                        GetGeoTransform()                             */
     710                 : /************************************************************************/
     711                 : 
     712               3 : CPLErr ADRGDataset::GetGeoTransform( double * padfGeoTransform)
     713                 : {
     714               3 :     if (papszSubDatasets != NULL)
     715               0 :         return CE_Failure;
     716                 : 
     717               3 :     padfGeoTransform[0] = LSO;
     718               3 :     padfGeoTransform[1] = 360. / ARV;
     719               3 :     padfGeoTransform[2] = 0.0;
     720               3 :     padfGeoTransform[3] = PSO;
     721               3 :     padfGeoTransform[4] = 0.0;
     722               3 :     padfGeoTransform[5] = - 360. / BRV;
     723                 : 
     724               3 :     return CE_None;
     725                 : }
     726                 : 
     727                 : /************************************************************************/
     728                 : /*                          SetGeoTransform()                           */
     729                 : /************************************************************************/
     730                 : 
     731               3 : CPLErr ADRGDataset::SetGeoTransform( double * padfGeoTransform )
     732                 : 
     733                 : {
     734               3 :     memcpy( adfGeoTransform, padfGeoTransform, sizeof(double)*6 );
     735               3 :     bGeoTransformValid = TRUE;
     736               3 :     return CE_None;
     737                 : }
     738                 : 
     739                 : /************************************************************************/
     740                 : /*                     GetLongitudeFromString()                         */
     741                 : /************************************************************************/
     742                 : 
     743              10 : double ADRGDataset::GetLongitudeFromString(const char* str)
     744                 : {
     745              10 :     char ddd[3+1] = { 0 };
     746              10 :     char mm[2+1] = { 0 };
     747              10 :     char ssdotss[5+1] = { 0 };
     748              10 :     int sign = (str[0] == '+') ? 1 : - 1;
     749              10 :     str++;
     750              10 :     strncpy(ddd, str, 3);
     751              10 :     str+=3;
     752              10 :     strncpy(mm, str, 2);
     753              10 :     str+=2;
     754              10 :     strncpy(ssdotss, str, 5);
     755              10 :     return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
     756                 : }
     757                 : 
     758                 : /************************************************************************/
     759                 : /*                      GetLatitudeFromString()                         */
     760                 : /************************************************************************/
     761                 : 
     762              10 : double ADRGDataset::GetLatitudeFromString(const char* str)
     763                 : {
     764              10 :     char ddd[2+1] = { 0 };
     765              10 :     char mm[2+1] = { 0 };
     766              10 :     char ssdotss[5+1] = { 0 };
     767              10 :     int sign = (str[0] == '+') ? 1 : - 1;
     768              10 :     str++;
     769              10 :     strncpy(ddd, str, 2);
     770              10 :     str+=2;
     771              10 :     strncpy(mm, str, 2);
     772              10 :     str+=2;
     773              10 :     strncpy(ssdotss, str, 5);
     774              10 :     return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
     775                 : }
     776                 : 
     777                 : /************************************************************************/
     778                 : /*                      FindRecordInGENForIMG()                         */
     779                 : /************************************************************************/
     780                 : 
     781               2 : DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
     782                 :                                               const char* pszGENFileName,
     783                 :                                               const char* pszIMGFileName)
     784                 : {
     785                 :     /* Finds the GEN file corresponding to the IMG file */
     786               2 :     if (!module.Open(pszGENFileName, TRUE))
     787               0 :         return NULL;
     788                 :         
     789                 :         
     790               2 :     CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
     791                 :         
     792                 :     DDFField* field;
     793                 :     DDFFieldDefn *fieldDefn;
     794                 :     DDFSubfieldDefn* subfieldDefn;
     795                 :     
     796                 :     /* Now finds the record */
     797               5 :     while (TRUE)
     798                 :     {
     799               7 :         CPLPushErrorHandler( CPLQuietErrorHandler );
     800               7 :         DDFRecord* record = module.ReadRecord();
     801               7 :         CPLPopErrorHandler();
     802               7 :         CPLErrorReset();
     803               7 :         if (record == NULL)
     804               0 :           return NULL;
     805                 : 
     806               7 :         if (record->GetFieldCount() >= 5)
     807                 :         {
     808               5 :             field = record->GetField(0);
     809               5 :             fieldDefn = field->GetFieldDefn();
     810               5 :             if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
     811                 :                 fieldDefn->GetSubfieldCount() == 2))
     812                 :             {
     813               0 :                 continue;
     814                 :             }
     815                 : 
     816               5 :             subfieldDefn = fieldDefn->GetSubfield(0);
     817              10 :             if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
     818               5 :                   (subfieldDefn->GetFormat())[0] == 'A'))
     819                 :             {
     820               0 :                 continue;
     821                 :             }
     822                 :             
     823               5 :             const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
     824                 :             
     825                 :             /* Ignore overviews */
     826               5 :             if ( strcmp(RTY, "OVV") == 0 )
     827               2 :                 continue;
     828                 :             
     829               3 :             if ( strcmp(RTY, "GIN") != 0 )
     830               0 :                 continue;
     831                 : 
     832               3 :             field = record->GetField(3);
     833               3 :             fieldDefn = field->GetFieldDefn();
     834                 :             
     835               3 :             if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
     836                 :                     fieldDefn->GetSubfieldCount() == 15))
     837                 :             {
     838               0 :                 continue;
     839                 :             }
     840                 :      
     841               3 :             subfieldDefn = fieldDefn->GetSubfield(13);
     842               6 :             if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
     843               3 :                     (subfieldDefn->GetFormat())[0] == 'A'))
     844                 :             {
     845               0 :                 continue;
     846                 :             } 
     847                 :             
     848               3 :             CPLString osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
     849                 :             {
     850               3 :                 char* c = (char*) strchr(osBAD.c_str(), ' ');
     851               3 :                 if (c)
     852               0 :                     *c = 0;
     853                 :             }
     854                 :             
     855               3 :             if (EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()))
     856                 :             {
     857               2 :                 return record;
     858               0 :             }
     859                 :         }
     860               0 :     }
     861                 : }
     862                 : 
     863                 : /************************************************************************/
     864                 : /*                           OpenDataset()                              */
     865                 : /************************************************************************/
     866                 : 
     867              10 : ADRGDataset* ADRGDataset::OpenDataset(
     868                 :         const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
     869                 : {
     870              10 :     DDFModule module;
     871                 :     
     872              10 :     int SCA = 0;
     873              10 :     int ZNA = 0;
     874                 :     double PSP;
     875                 :     int ARV;
     876                 :     int BRV;
     877                 :     double LSO;
     878                 :     double PSO;
     879                 :     int NFL;
     880                 :     int NFC;
     881              10 :     CPLString osBAD;
     882                 :     int TIF;
     883              10 :     int* TILEINDEX = NULL;
     884                 :     int i;
     885                 :     
     886                 :     DDFField* field;
     887                 :     DDFFieldDefn *fieldDefn;
     888                 :     DDFSubfieldDefn* subfieldDefn;
     889                 :     
     890              10 :     if (record == NULL)
     891                 :     {
     892               2 :         record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
     893               2 :         if (record == NULL)
     894               0 :             return NULL;
     895                 :     }
     896                 : 
     897              10 :     field = record->GetField(1);
     898              10 :     fieldDefn = field->GetFieldDefn();
     899                 : 
     900              10 :     if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
     901                 :           fieldDefn->GetSubfieldCount() == 2))
     902                 :     {
     903               0 :         return NULL;
     904                 :     }
     905                 :     
     906              10 :     subfieldDefn = fieldDefn->GetSubfield(0);
     907              20 :     if (!(strcmp(subfieldDefn->GetName(), "PRT") == 0 &&
     908              10 :          (subfieldDefn->GetFormat())[0] == 'A' &&
     909                 :          strcmp(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 4, NULL), "ADRG") == 0))
     910                 :     {
     911               0 :        return NULL;
     912                 :     }
     913                 :     
     914              10 :     subfieldDefn = fieldDefn->GetSubfield(1);
     915              20 :     if (!(strcmp(subfieldDefn->GetName(), "NAM") == 0 &&
     916              10 :           (subfieldDefn->GetFormat())[0] == 'A'))
     917                 :     {
     918               0 :         return NULL;
     919                 :     }
     920                 : 
     921              10 :     CPLString osNAM = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 8, NULL);
     922                 :     
     923              10 :     field = record->GetField(2);
     924              10 :     fieldDefn = field->GetFieldDefn();
     925                 :     
     926              10 :     int isGIN = TRUE;
     927                 :     
     928              10 :     if (isGIN)
     929                 :     {
     930              10 :         if (!(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
     931                 :                 fieldDefn->GetSubfieldCount() == 21))
     932                 :         {
     933               0 :             return NULL;
     934                 :         }
     935                 :         
     936              10 :         subfieldDefn = fieldDefn->GetSubfield(0);
     937              20 :         if (!(strcmp(subfieldDefn->GetName(), "STR") == 0 &&
     938              10 :                 (subfieldDefn->GetFormat())[0] == 'I' &&
     939                 :                 subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 1, NULL) == 3))
     940                 :         {
     941               0 :             return NULL;
     942                 :         }
     943                 :         
     944              10 :         subfieldDefn = fieldDefn->GetSubfield(12);
     945              20 :         if (!(strcmp(subfieldDefn->GetName(), "SCA") == 0 &&
     946              10 :                 (subfieldDefn->GetFormat())[0] == 'I'))
     947                 :         {
     948               0 :             return NULL;
     949                 :         }
     950                 :         
     951              10 :         SCA = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 9, NULL);
     952              10 :         CPLDebug("ADRG", "SCA=%d", SCA);
     953                 :         
     954              10 :         subfieldDefn = fieldDefn->GetSubfield(13);
     955              20 :         if (!(strcmp(subfieldDefn->GetName(), "ZNA") == 0 &&
     956              10 :                 (subfieldDefn->GetFormat())[0] == 'I'))
     957                 :         {
     958               0 :             return NULL;
     959                 :         }
     960                 :         
     961              10 :         ZNA = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 2, NULL);
     962              10 :         CPLDebug("ADRG", "ZNA=%d", ZNA);
     963                 :         
     964              10 :         subfieldDefn = fieldDefn->GetSubfield(14);
     965              20 :         if (!(strcmp(subfieldDefn->GetName(), "PSP") == 0 &&
     966              10 :                 (subfieldDefn->GetFormat())[0] == 'R'))
     967                 :         {
     968               0 :             return NULL;
     969                 :         }
     970                 :         
     971              10 :         PSP = subfieldDefn->ExtractFloatData(field->GetSubfieldData(subfieldDefn), 5, NULL);
     972              10 :         CPLDebug("ADRG", "PSP=%f", PSP);
     973                 :         
     974              10 :         subfieldDefn = fieldDefn->GetSubfield(16);
     975              20 :         if (!(strcmp(subfieldDefn->GetName(), "ARV") == 0 &&
     976              10 :                 (subfieldDefn->GetFormat())[0] == 'I'))
     977                 :         {
     978               0 :             return NULL;
     979                 :         }
     980                 :         
     981              10 :         ARV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
     982              10 :         CPLDebug("ADRG", "ARV=%d", ARV);
     983                 :         
     984              10 :         subfieldDefn = fieldDefn->GetSubfield(17);
     985              20 :         if (!(strcmp(subfieldDefn->GetName(), "BRV") == 0 &&
     986              10 :                 (subfieldDefn->GetFormat())[0] == 'I'))
     987                 :         {
     988               0 :             return NULL;
     989                 :         }
     990                 :         
     991              10 :         BRV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
     992              10 :         CPLDebug("ADRG", "BRV=%d", BRV);
     993                 :         
     994                 :         
     995              10 :         subfieldDefn = fieldDefn->GetSubfield(18);
     996              20 :         if (!(strcmp(subfieldDefn->GetName(), "LSO") == 0 &&
     997              10 :                 (subfieldDefn->GetFormat())[0] == 'A'))
     998                 :         {
     999               0 :             return NULL;
    1000                 :         }
    1001                 :         
    1002              10 :         LSO = GetLongitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 11, NULL));
    1003              10 :         CPLDebug("ADRG", "LSO=%f", LSO);
    1004                 :         
    1005              10 :         subfieldDefn = fieldDefn->GetSubfield(19);
    1006              20 :         if (!(strcmp(subfieldDefn->GetName(), "PSO") == 0 &&
    1007              10 :                 (subfieldDefn->GetFormat())[0] == 'A'))
    1008                 :         {
    1009               0 :             return NULL;
    1010                 :         }
    1011                 :         
    1012              10 :         PSO = GetLatitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 10, NULL));
    1013              10 :         CPLDebug("ADRG", "PSO=%f", PSO);
    1014                 :     }
    1015                 :     else
    1016                 :     {
    1017               0 :         if (!(strcmp(fieldDefn->GetName(), "OVI") == 0 &&
    1018                 :                 fieldDefn->GetSubfieldCount() == 5))
    1019                 :         {
    1020               0 :             return NULL;
    1021                 :         }
    1022                 :         
    1023               0 :         subfieldDefn = fieldDefn->GetSubfield(0);
    1024               0 :         if (!(strcmp(subfieldDefn->GetName(), "STR") == 0 &&
    1025               0 :                 (subfieldDefn->GetFormat())[0] == 'I' &&
    1026                 :                 subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 1, NULL) == 3))
    1027                 :         {
    1028               0 :             return NULL;
    1029                 :         }
    1030                 :         
    1031               0 :         subfieldDefn = fieldDefn->GetSubfield(1);
    1032               0 :         if (!(strcmp(subfieldDefn->GetName(), "ARV") == 0 &&
    1033               0 :                 (subfieldDefn->GetFormat())[0] == 'I'))
    1034                 :         {
    1035               0 :             return NULL;
    1036                 :         }
    1037                 :         
    1038               0 :         ARV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
    1039               0 :         CPLDebug("ADRG", "ARV=%d", ARV);
    1040                 :         
    1041               0 :         subfieldDefn = fieldDefn->GetSubfield(2);
    1042               0 :         if (!(strcmp(subfieldDefn->GetName(), "BRV") == 0 &&
    1043               0 :                 (subfieldDefn->GetFormat())[0] == 'I'))
    1044                 :         {
    1045               0 :             return NULL;
    1046                 :         }
    1047                 :         
    1048               0 :         BRV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
    1049               0 :         CPLDebug("ADRG", "BRV=%d", BRV);
    1050                 :         
    1051                 :         
    1052               0 :         subfieldDefn = fieldDefn->GetSubfield(3);
    1053               0 :         if (!(strcmp(subfieldDefn->GetName(), "LSO") == 0 &&
    1054               0 :                 (subfieldDefn->GetFormat())[0] == 'A'))
    1055                 :         {
    1056               0 :             return NULL;
    1057                 :         }
    1058                 :         
    1059               0 :         LSO = GetLongitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 11, NULL));
    1060               0 :         CPLDebug("ADRG", "LSO=%f", LSO);
    1061                 :         
    1062               0 :         subfieldDefn = fieldDefn->GetSubfield(4);
    1063               0 :         if (!(strcmp(subfieldDefn->GetName(), "PSO") == 0 &&
    1064               0 :                 (subfieldDefn->GetFormat())[0] == 'A'))
    1065                 :         {
    1066               0 :             return NULL;
    1067                 :         }
    1068                 :         
    1069               0 :         PSO = GetLatitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 10, NULL));
    1070               0 :         CPLDebug("ADRG", "PSO=%f", PSO);
    1071                 :     }
    1072                 :     
    1073              10 :     field = record->GetField(3);
    1074              10 :     fieldDefn = field->GetFieldDefn();
    1075                 :     
    1076              10 :     if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
    1077                 :             fieldDefn->GetSubfieldCount() == 15))
    1078                 :     {
    1079               0 :         return NULL;
    1080                 :     }
    1081                 :     
    1082              10 :     subfieldDefn = fieldDefn->GetSubfield(4);
    1083              20 :     if (!(strcmp(subfieldDefn->GetName(), "NFL") == 0 &&
    1084              10 :             (subfieldDefn->GetFormat())[0] == 'I'))
    1085                 :     {
    1086               0 :         return NULL;
    1087                 :     }
    1088                 :     
    1089              10 :     NFL = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 3, NULL);
    1090              10 :     CPLDebug("ADRG", "NFL=%d", NFL);
    1091                 :     
    1092              10 :     subfieldDefn = fieldDefn->GetSubfield(5);
    1093              20 :     if (!(strcmp(subfieldDefn->GetName(), "NFC") == 0 &&
    1094              10 :             (subfieldDefn->GetFormat())[0] == 'I'))
    1095                 :     {
    1096               0 :         return NULL;
    1097                 :     }
    1098                 :     
    1099              10 :     NFC = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 3, NULL);
    1100              10 :     CPLDebug("ADRG", "NFC=%d", NFC);
    1101                 :     
    1102              10 :     subfieldDefn = fieldDefn->GetSubfield(6);
    1103              20 :     if (!(strcmp(subfieldDefn->GetName(), "PNC") == 0 &&
    1104              10 :             (subfieldDefn->GetFormat())[0] == 'I'))
    1105                 :     {
    1106               0 :         return NULL;
    1107                 :     }
    1108                 :     
    1109              10 :     int PNC = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 6, NULL);
    1110              10 :     CPLDebug("ADRG", "PNC=%d", PNC);
    1111              10 :     if (PNC != 128)
    1112                 :     {
    1113               0 :         return NULL;
    1114                 :     }
    1115                 :     
    1116              10 :     subfieldDefn = fieldDefn->GetSubfield(7);
    1117              20 :     if (!(strcmp(subfieldDefn->GetName(), "PNL") == 0 &&
    1118              10 :             (subfieldDefn->GetFormat())[0] == 'I'))
    1119                 :     {
    1120               0 :         return NULL;
    1121                 :     }
    1122                 :     
    1123              10 :     int PNL = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 6, NULL);
    1124              10 :     CPLDebug("ADRG", "PNL=%d", PNL);
    1125              10 :     if (PNL != 128)
    1126                 :     {
    1127               0 :         return NULL;
    1128                 :     }
    1129                 :     
    1130              10 :     subfieldDefn = fieldDefn->GetSubfield(13);
    1131              20 :     if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
    1132              10 :             (subfieldDefn->GetFormat())[0] == 'A'))
    1133                 :     {
    1134               0 :         return NULL;
    1135                 :     }
    1136                 :     
    1137              10 :     osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
    1138                 :     {
    1139              10 :         char* c = (char*) strchr(osBAD.c_str(), ' ');
    1140              10 :         if (c)
    1141               0 :             *c = 0;
    1142                 :     }
    1143              10 :     CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
    1144                 :     
    1145              10 :     subfieldDefn = fieldDefn->GetSubfield(14);
    1146              20 :     if (!(strcmp(subfieldDefn->GetName(), "TIF") == 0 &&
    1147              10 :             (subfieldDefn->GetFormat())[0] == 'A'))
    1148                 :     {
    1149               0 :         return NULL;
    1150                 :     }
    1151                 :     
    1152              10 :     TIF = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 1, NULL)[0] == 'Y';
    1153              10 :     CPLDebug("ADRG", "TIF=%d", TIF);
    1154                 :     
    1155              10 :     if (TIF)
    1156                 :     {
    1157              10 :         if (record->GetFieldCount() != 6)
    1158                 :         {
    1159               0 :             return NULL;
    1160                 :         }
    1161                 :         
    1162              10 :         field = record->GetField(5);
    1163              10 :         fieldDefn = field->GetFieldDefn();
    1164                 :     
    1165              10 :         if (!(strcmp(fieldDefn->GetName(), "TIM") == 0))
    1166                 :         {
    1167               0 :             return NULL;
    1168                 :         }
    1169                 :         
    1170              10 :         if (field->GetDataSize() != 5 * NFL * NFC + 1)
    1171                 :         {
    1172               0 :             return NULL;
    1173                 :         }
    1174                 :     
    1175              10 :         TILEINDEX = new int [NFL * NFC];
    1176              10 :         const char* ptr = field->GetData();
    1177              10 :         char offset[5+1]={0};
    1178              20 :         for(i=0;i<NFL*NFC;i++)
    1179                 :         {
    1180              10 :             strncpy(offset, ptr, 5);
    1181              10 :             ptr += 5;
    1182              10 :             TILEINDEX[i] = atoi(offset);
    1183                 :             //CPLDebug("ADRG", "TSI[%d]=%d", i, TILEINDEX[i]);
    1184                 :         }
    1185                 :     }
    1186                 : 
    1187              10 :     FILE* fdIMG = VSIFOpenL(pszIMGFileName, "rb");
    1188              10 :     if (fdIMG == NULL)
    1189                 :     {
    1190               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s\n", pszIMGFileName);
    1191               0 :         return NULL;
    1192                 :     }
    1193                 :     
    1194              10 :     if (ZNA == 9 || ZNA == 18)
    1195                 :     {
    1196               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by ADRG driver");
    1197               0 :         VSIFCloseL(fdIMG);
    1198               0 :         return NULL;
    1199                 :     }
    1200                 :     
    1201                 :     /* Skip ISO8211 header of IMG file */
    1202              10 :     int offsetInIMG = 0;
    1203                 :     char c;
    1204                 :     char recordName[3];
    1205              10 :     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
    1206                 :     {
    1207               0 :         VSIFCloseL(fdIMG);
    1208               0 :         return NULL;
    1209                 :     }
    1210            2590 :     while (!VSIFEofL(fdIMG))
    1211                 :     {
    1212            2580 :         if (c == 30)
    1213                 :         {
    1214              60 :             if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
    1215                 :             {
    1216               0 :                 VSIFCloseL(fdIMG);
    1217               0 :                 return NULL;
    1218                 :             }
    1219              60 :             offsetInIMG += 3;
    1220              60 :             if (strncmp(recordName,"IMG",3) == 0)
    1221                 :             {
    1222              10 :                 offsetInIMG += 4;
    1223              10 :                 if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
    1224                 :                 {
    1225               0 :                     VSIFCloseL(fdIMG);
    1226               0 :                     return NULL;
    1227                 :                 }
    1228              10 :                 if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
    1229                 :                 {
    1230               0 :                     VSIFCloseL(fdIMG);
    1231               0 :                     return NULL;
    1232                 :                 }
    1233           17700 :                 while(c ==' ')
    1234                 :                 {
    1235           17680 :                     offsetInIMG ++;
    1236           17680 :                     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
    1237                 :                     {
    1238               0 :                         VSIFCloseL(fdIMG);
    1239               0 :                         return NULL;
    1240                 :                     }
    1241                 :                 }
    1242              10 :                 offsetInIMG ++;
    1243              10 :                 break;
    1244                 :             }
    1245                 :         }
    1246                 : 
    1247            2570 :         offsetInIMG ++;
    1248            2570 :         if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
    1249                 :         {
    1250               0 :             VSIFCloseL(fdIMG);
    1251               0 :             return NULL;
    1252                 :         }
    1253                 :     }
    1254                 :     
    1255              10 :     if (VSIFEofL(fdIMG))
    1256                 :     {
    1257               0 :         VSIFCloseL(fdIMG);
    1258               0 :         return NULL;
    1259                 :     }
    1260                 :     
    1261              10 :     CPLDebug("ADRG", "Img offset data = %d", offsetInIMG);
    1262                 :     
    1263              10 :     ADRGDataset* poDS = new ADRGDataset();
    1264                 :     
    1265              20 :     poDS->osGENFileName = pszGENFileName;
    1266              10 :     poDS->osIMGFileName = pszIMGFileName;
    1267              10 :     poDS->NFC = NFC;
    1268              10 :     poDS->NFL = NFL;
    1269              10 :     poDS->nRasterXSize = NFC * 128;
    1270              10 :     poDS->nRasterYSize = NFL * 128;
    1271              10 :     poDS->LSO = LSO;
    1272              10 :     poDS->PSO = PSO;
    1273              10 :     poDS->ARV = ARV;
    1274              10 :     poDS->BRV = BRV;
    1275              10 :     poDS->TILEINDEX = TILEINDEX;
    1276              10 :     poDS->fdIMG = fdIMG;
    1277              10 :     poDS->offsetInIMG = offsetInIMG;
    1278              10 :     poDS->poOverviewDS = NULL;
    1279                 :     
    1280              10 :     if (isGIN)
    1281                 :     {
    1282                 :         char pszValue[32];
    1283              10 :         sprintf(pszValue, "%d", SCA);
    1284              10 :         poDS->SetMetadataItem( "ADRG_SCA", pszValue );
    1285                 :     }
    1286                 :     
    1287              10 :     poDS->SetMetadataItem( "ADRG_NAM", osNAM.c_str() );
    1288                 :     
    1289              10 :     poDS->nBands = 3;
    1290              40 :     for( i = 0; i < poDS->nBands; i++ )
    1291              30 :         poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
    1292                 : 
    1293              10 :     return poDS;
    1294                 : }
    1295                 : 
    1296                 : /************************************************************************/
    1297                 : /*                          GetGENListFromTHF()                         */
    1298                 : /************************************************************************/
    1299                 : 
    1300               2 : char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
    1301                 : {
    1302               2 :     DDFModule module;
    1303                 :     DDFRecord * record;
    1304                 :     DDFField* field;
    1305                 :     DDFFieldDefn *fieldDefn;
    1306                 :     DDFSubfieldDefn* subfieldDefn;
    1307                 :     int i;
    1308               2 :     int nFilenames = 0;
    1309               2 :     char** papszFileNames = NULL;
    1310                 : 
    1311               2 :     if (!module.Open(pszFileName, TRUE))
    1312               0 :         return papszFileNames;
    1313                 : 
    1314               8 :     while (TRUE)
    1315                 :     {
    1316              10 :         CPLPushErrorHandler( CPLQuietErrorHandler );
    1317              10 :         record = module.ReadRecord();
    1318              10 :         CPLPopErrorHandler();
    1319              10 :         CPLErrorReset();
    1320              10 :         if (record == NULL)
    1321                 :           break;
    1322                 : 
    1323               8 :         if (record->GetFieldCount() >= 2)
    1324                 :         {
    1325               8 :             field = record->GetField(0);
    1326               8 :             fieldDefn = field->GetFieldDefn();
    1327               8 :             if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
    1328                 :                 fieldDefn->GetSubfieldCount() == 2))
    1329                 :             {
    1330               0 :                 continue;
    1331                 :             }
    1332                 : 
    1333               8 :             subfieldDefn = fieldDefn->GetSubfield(0);
    1334              16 :             if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
    1335               8 :                   (subfieldDefn->GetFormat())[0] == 'A'))
    1336                 :             {
    1337               0 :                 continue;
    1338                 :             }
    1339                 :             
    1340               8 :             const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
    1341               8 :             if (! ( strcmp(RTY, "TFN") == 0 ))
    1342                 :             {
    1343               6 :                 continue;
    1344                 :             }
    1345                 :             
    1346               2 :             for (i = 1; i < record->GetFieldCount() ; i++)
    1347                 :             {
    1348               9 :                 field = record->GetField(i);
    1349               9 :                 fieldDefn = field->GetFieldDefn();
    1350                 :                 
    1351               9 :                 if (!(strcmp(fieldDefn->GetName(), "VFF") == 0 &&
    1352                 :                       fieldDefn->GetSubfieldCount() == 1))
    1353                 :                 {
    1354               0 :                     continue;
    1355                 :                 }
    1356                 :             
    1357               9 :                 subfieldDefn = fieldDefn->GetSubfield(0);
    1358              18 :                 if (!(strcmp(subfieldDefn->GetName(), "VFF") == 0 &&
    1359               9 :                     (subfieldDefn->GetFormat())[0] == 'A'))
    1360                 :                 {
    1361               0 :                     continue;
    1362                 :                 }
    1363                 :                 
    1364               9 :                 CPLString osSubFileName(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 300, NULL));
    1365               9 :                 char* c = (char*) strchr(osSubFileName.c_str(), ' ');
    1366               9 :                 if (c)
    1367               9 :                     *c = 0;
    1368               9 :                 if (EQUAL(CPLGetExtension(osSubFileName.c_str()), "GEN"))
    1369                 :                 {
    1370               2 :                     CPLDebug("ADRG", "Found GEN file in THF : %s", osSubFileName.c_str());
    1371               2 :                     CPLString osGENFileName(CPLGetDirname(pszFileName));
    1372               2 :                     char** tokens = CSLTokenizeString2( osSubFileName.c_str(), "/\"", 0);
    1373               2 :                     char** ptr = tokens;
    1374               2 :                     if (ptr == NULL)
    1375               0 :                         continue;
    1376               6 :                     while(*ptr)
    1377                 :                     {
    1378               2 :                         char** papszDirContent = VSIReadDir(osGENFileName.c_str());
    1379               2 :                         char** ptrDir = papszDirContent;
    1380               2 :                         if (ptrDir)
    1381                 :                         {
    1382              17 :                             while(*ptrDir)
    1383                 :                             {
    1384              15 :                                 if (EQUAL(*ptrDir, *ptr))
    1385                 :                                 {
    1386               2 :                                     osGENFileName = CPLFormFilename(osGENFileName.c_str(), *ptrDir, NULL);
    1387               2 :                                     CPLDebug("ADRG", "Building GEN full file name : %s", osGENFileName.c_str());
    1388               2 :                                     break;
    1389                 :                                 }
    1390              13 :                                 ptrDir ++;
    1391                 :                             }
    1392                 :                         }
    1393               2 :                         if (ptrDir == NULL)
    1394               0 :                             break;
    1395               2 :                         CSLDestroy(papszDirContent);
    1396               2 :                         ptr++;
    1397                 :                     }
    1398               2 :                     int isNameValid = *ptr == NULL;
    1399               2 :                     CSLDestroy(tokens);
    1400               2 :                     if (isNameValid)
    1401                 :                     {
    1402               2 :                         papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
    1403               2 :                         papszFileNames[nFilenames] = CPLStrdup(osGENFileName.c_str());
    1404               2 :                         papszFileNames[nFilenames + 1] = NULL;
    1405               2 :                         nFilenames ++;
    1406               0 :                     }
    1407                 :                 }
    1408                 :             }
    1409                 :         }
    1410                 :     }
    1411               2 :     return papszFileNames;
    1412                 : }
    1413                 : 
    1414                 : /************************************************************************/
    1415                 : /*                          GetIMGListFromGEN()                         */
    1416                 : /************************************************************************/
    1417                 : 
    1418               9 : char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
    1419                 :                                       int *pnRecordIndex)
    1420                 : {
    1421                 :     DDFRecord * record;
    1422                 :     DDFField* field;
    1423                 :     DDFFieldDefn *fieldDefn;
    1424                 :     DDFSubfieldDefn* subfieldDefn;
    1425               9 :     int nFilenames = 0;
    1426               9 :     char** papszFileNames = NULL;
    1427               9 :     int nRecordIndex = -1;
    1428                 : 
    1429               9 :     if (pnRecordIndex)
    1430               9 :         *pnRecordIndex = -1;
    1431                 : 
    1432               9 :     DDFModule module;
    1433               9 :     if (!module.Open(pszFileName, TRUE))
    1434               0 :         return NULL;    
    1435                 : 
    1436              28 :     while (TRUE)
    1437                 :     {
    1438              37 :         nRecordIndex ++;
    1439                 :         
    1440              37 :         CPLPushErrorHandler( CPLQuietErrorHandler );
    1441              37 :         record = module.ReadRecord();
    1442              37 :         CPLPopErrorHandler();
    1443              37 :         CPLErrorReset();
    1444              37 :         if (record == NULL)
    1445                 :           break;
    1446                 : 
    1447              28 :         if (record->GetFieldCount() >= 5)
    1448                 :         {
    1449              19 :             field = record->GetField(0);
    1450              19 :             fieldDefn = field->GetFieldDefn();
    1451              19 :             if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
    1452                 :                 fieldDefn->GetSubfieldCount() == 2))
    1453                 :             {
    1454               0 :                 continue;
    1455                 :             }
    1456                 : 
    1457              19 :             subfieldDefn = fieldDefn->GetSubfield(0);
    1458              38 :             if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
    1459              19 :                   (subfieldDefn->GetFormat())[0] == 'A'))
    1460                 :             {
    1461               0 :                 continue;
    1462                 :             }
    1463                 :             
    1464              19 :             const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
    1465                 :             
    1466                 :             /* Ignore overviews */
    1467              19 :             if ( strcmp(RTY, "OVV") == 0 )
    1468               9 :                 continue;
    1469                 :             
    1470              10 :             if ( strcmp(RTY, "GIN") != 0 )
    1471               0 :                 continue;
    1472                 : 
    1473              10 :             field = record->GetField(3);
    1474              10 :             fieldDefn = field->GetFieldDefn();
    1475                 :             
    1476              10 :             if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
    1477                 :                     fieldDefn->GetSubfieldCount() == 15))
    1478                 :             {
    1479               0 :                 continue;
    1480                 :             }
    1481                 :                         
    1482              10 :             subfieldDefn = fieldDefn->GetSubfield(13);
    1483              20 :             if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
    1484              10 :                   (subfieldDefn->GetFormat())[0] == 'A'))
    1485                 :             {
    1486               0 :                 continue;
    1487                 :             }
    1488                 :             
    1489              10 :             CPLString osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
    1490                 :             {
    1491              10 :                 char* c = (char*) strchr(osBAD.c_str(), ' ');
    1492              10 :                 if (c)
    1493               0 :                     *c = 0;
    1494                 :             }
    1495              10 :             CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
    1496                 :             
    1497                 :             /* Build full IMG file name from BAD value */
    1498              10 :             CPLString osGENDir(CPLGetDirname(pszFileName));
    1499                 :             
    1500              10 :             CPLString osFileName = CPLFormFilename(osGENDir.c_str(), osBAD.c_str(), NULL);
    1501                 :             VSIStatBufL sStatBuf;
    1502              10 :             if( VSIStatL( osFileName, &sStatBuf ) == 0 )
    1503                 :             {
    1504              10 :                 osBAD = osFileName;
    1505              10 :                 CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
    1506                 :             }
    1507                 :             else
    1508                 :             {
    1509                 :                 char** papszDirContent;
    1510               0 :                 if (strcmp(osGENDir.c_str(), "/vsimem") == 0)
    1511                 :                 {
    1512               0 :                     CPLString osTmp = osGENDir + "/";
    1513               0 :                     papszDirContent = VSIReadDir(osTmp);
    1514                 :                 }
    1515                 :                 else
    1516               0 :                     papszDirContent = VSIReadDir(osGENDir);
    1517               0 :                 char** ptrDir = papszDirContent;
    1518               0 :                 while(ptrDir && *ptrDir)
    1519                 :                 {
    1520               0 :                     if (EQUAL(*ptrDir, osBAD.c_str()))
    1521                 :                     {
    1522               0 :                         osBAD = CPLFormFilename(osGENDir.c_str(), *ptrDir, NULL);
    1523               0 :                         CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
    1524               0 :                         break;
    1525                 :                     }
    1526               0 :                     ptrDir ++;
    1527                 :                 }
    1528               0 :                 CSLDestroy(papszDirContent);
    1529                 :             }
    1530                 :             
    1531              10 :             if (nFilenames == 0 && pnRecordIndex)
    1532               9 :                 *pnRecordIndex = nRecordIndex;
    1533                 :             
    1534              10 :             papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
    1535              10 :             papszFileNames[nFilenames] = CPLStrdup(osBAD.c_str());
    1536              10 :             papszFileNames[nFilenames + 1] = NULL;
    1537              10 :             nFilenames ++;
    1538                 :         }
    1539                 :     }
    1540                 :     
    1541               9 :     return papszFileNames;
    1542                 : }
    1543                 : 
    1544                 : /************************************************************************/
    1545                 : /*                                Open()                                */
    1546                 : /************************************************************************/
    1547                 : 
    1548            8443 : GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
    1549                 : {
    1550            8443 :     int nRecordIndex = -1;
    1551            8443 :     CPLString osGENFileName;
    1552            8443 :     CPLString osIMGFileName;
    1553            8443 :     int bFromSubdataset = FALSE;
    1554                 :     
    1555            8443 :     if( EQUALN(poOpenInfo->pszFilename, "ADRG:", 5) )
    1556                 :     {
    1557               2 :         char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 5, ",", 0);
    1558               2 :         if (CSLCount(papszTokens) == 2)
    1559                 :         {
    1560               2 :             osGENFileName = papszTokens[0];
    1561               2 :             osIMGFileName = papszTokens[1];
    1562               2 :             bFromSubdataset = TRUE;
    1563                 :         }
    1564               2 :         CSLDestroy(papszTokens);
    1565                 :     }
    1566                 :     else
    1567                 :     {
    1568            8441 :         if( poOpenInfo->nHeaderBytes < 500 )
    1569            8319 :             return NULL;
    1570                 : 
    1571             122 :         CPLString osFileName(poOpenInfo->pszFilename);
    1572             122 :         if (EQUAL(CPLGetExtension(osFileName.c_str()), "THF"))
    1573                 :         {
    1574               2 :             char** papszFileNames = GetGENListFromTHF(osFileName.c_str());
    1575               2 :             if (papszFileNames == NULL)
    1576               0 :                 return NULL;
    1577               2 :             if (papszFileNames[1] == NULL)
    1578                 :             {
    1579               2 :                 osFileName = papszFileNames[0];
    1580               2 :                 CSLDestroy(papszFileNames);
    1581                 :             }
    1582                 :             else
    1583                 :             {
    1584               0 :                 char** ptr = papszFileNames;
    1585               0 :                 ADRGDataset* poDS = new ADRGDataset();
    1586               0 :                 while(*ptr)
    1587                 :                 {
    1588               0 :                     char** papszIMGFileNames = GetIMGListFromGEN(*ptr);
    1589               0 :                     char** papszIMGIter = papszIMGFileNames;
    1590               0 :                     while(papszIMGIter && *papszIMGIter)
    1591                 :                     {
    1592               0 :                         poDS->AddSubDataset(*ptr, *papszIMGIter);
    1593               0 :                         papszIMGIter ++;
    1594                 :                     }
    1595               0 :                     CSLDestroy(papszIMGFileNames);
    1596                 :                     
    1597               0 :                     ptr ++;
    1598                 :                 }
    1599               0 :                 CSLDestroy(papszFileNames);
    1600               0 :                 return poDS;
    1601                 :             }
    1602                 :         }
    1603                 :         
    1604             122 :         if (EQUAL(CPLGetExtension(osFileName.c_str()), "GEN"))
    1605                 :         {
    1606               9 :             osGENFileName = osFileName;
    1607                 :                 
    1608               9 :             char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
    1609               9 :             if (papszFileNames == NULL)
    1610               0 :                 return NULL;
    1611               9 :             if (papszFileNames[1] == NULL)
    1612                 :             {
    1613               8 :                 osIMGFileName = papszFileNames[0];
    1614               8 :                 CSLDestroy(papszFileNames);
    1615                 :             }
    1616                 :             else
    1617                 :             {
    1618               1 :                 char** ptr = papszFileNames;
    1619               1 :                 ADRGDataset* poDS = new ADRGDataset();
    1620               4 :                 while(*ptr)
    1621                 :                 {
    1622               2 :                     poDS->AddSubDataset(osFileName.c_str(), *ptr);
    1623               2 :                     ptr ++;
    1624                 :                 }
    1625               1 :                 CSLDestroy(papszFileNames);
    1626               1 :                 return poDS;
    1627                 :             }
    1628               0 :         }
    1629                 :     }
    1630                 :     
    1631             123 :     if (osGENFileName.size() > 0 &&
    1632                 :         osIMGFileName.size() > 0)
    1633                 :     {
    1634              10 :         if( poOpenInfo->eAccess == GA_Update )
    1635                 :         {
    1636                 :             CPLError( CE_Failure, CPLE_NotSupported, 
    1637                 :                       "The ADRG driver does not support update access to existing"
    1638               0 :                       " datasets.\n" );
    1639               0 :             return NULL;
    1640                 :         }
    1641                 :         
    1642              10 :         DDFModule module;
    1643              10 :         DDFRecord* record = NULL;
    1644              10 :         if (nRecordIndex >= 0 &&
    1645                 :             module.Open(osGENFileName.c_str(), TRUE))
    1646                 :         {
    1647                 :             int i;
    1648              32 :             for(i=0;i<=nRecordIndex;i++)
    1649                 :             {
    1650              24 :                 CPLPushErrorHandler( CPLQuietErrorHandler );
    1651              24 :                 record = module.ReadRecord();
    1652              24 :                 CPLPopErrorHandler();
    1653              24 :                 CPLErrorReset();
    1654              24 :                 if (record == NULL)
    1655               0 :                   break;
    1656                 :             }
    1657                 :         }
    1658                 :         
    1659              10 :         ADRGDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
    1660                 : 
    1661              10 :         if (poDS)
    1662                 :         {
    1663                 :             /* -------------------------------------------------------------------- */
    1664                 :             /*      Initialize any PAM information.                                 */
    1665                 :             /* -------------------------------------------------------------------- */
    1666              10 :             poDS->SetDescription( poOpenInfo->pszFilename );
    1667              10 :             poDS->TryLoadXML();
    1668                 : 
    1669                 :             /* -------------------------------------------------------------------- */
    1670                 :             /*      Check for external overviews.                                   */
    1671                 :             /* -------------------------------------------------------------------- */
    1672              10 :             if( bFromSubdataset )
    1673               2 :                 poDS->oOvManager.Initialize( poDS, osIMGFileName.c_str() );
    1674                 :             else
    1675               8 :                 poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    1676                 : 
    1677              10 :             return poDS;
    1678               0 :         }
    1679                 :     }
    1680                 :     
    1681             113 :     return NULL;
    1682                 : }
    1683                 : 
    1684                 : /************************************************************************/
    1685                 : /*                               Create()                               */
    1686                 : /************************************************************************/
    1687                 : 
    1688              34 : GDALDataset *ADRGDataset::Create(const char* pszFilename, int nXSize, int nYSize,
    1689                 :                                  int nBands, GDALDataType eType, char **papszOptions)
    1690                 : {
    1691                 :     int i;
    1692                 : 
    1693              34 :     if( eType != GDT_Byte)
    1694                 :     {
    1695                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1696                 :               "Attempt to create ADRG dataset with an illegal\n"
    1697                 :               "data type (%s), only Byte supported by the format.\n",
    1698              20 :               GDALGetDataTypeName(eType) );
    1699                 : 
    1700              20 :         return NULL;
    1701                 :     }
    1702                 : 
    1703              14 :     if( nBands != 3 )
    1704                 :     {
    1705                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1706                 :                   "ADRG driver doesn't support %d bands. Must be 3 (rgb) bands.\n",
    1707               9 :                   nBands );
    1708               9 :         return NULL;
    1709                 :     }
    1710                 : 
    1711               5 :     if(nXSize < 1 || nYSize < 1)
    1712                 :     {
    1713                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1714                 :                 "Specified pixel dimensions (% d x %d) are bad.\n",
    1715               0 :                 nXSize, nYSize );
    1716                 :     }
    1717                 :     
    1718               5 :     if (!EQUAL(CPLGetExtension(pszFilename), "gen"))
    1719                 :     {
    1720                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1721               2 :                 "Invalid filename. Must be ABCDEF01.GEN\n");
    1722               2 :         return NULL;
    1723                 :     }
    1724                 : 
    1725               3 :     CPLString osBaseFileName(CPLGetBasename(pszFilename));
    1726               3 :     if (strlen(osBaseFileName) != 8 || osBaseFileName[6] != '0' || osBaseFileName[7] != '1')
    1727                 :     {
    1728                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1729               0 :                 "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
    1730               0 :         return NULL;
    1731                 :     }
    1732                 :     
    1733              21 :     for(i=0;i<6;i++)
    1734                 :     {
    1735              18 :         if (!(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z'))
    1736                 :         {
    1737                 :             CPLError( CE_Failure, CPLE_NotSupported,
    1738               0 :                 "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
    1739               0 :             return NULL;
    1740                 :         }
    1741                 :     }
    1742                 : 
    1743               3 :     FILE* fdGEN = VSIFOpenL(pszFilename, "wb");
    1744               3 :     if (fdGEN == NULL)
    1745                 :     {
    1746                 :         CPLError( CE_Failure, CPLE_FileIO,
    1747               0 :                 "Cannot create GEN file : %s.\n", pszFilename);
    1748               0 :         return NULL;
    1749                 :     }
    1750                 :     
    1751               3 :     CPLString osDirname(CPLGetDirname(pszFilename));
    1752               3 :     CPLString osTransh01THF(CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
    1753               3 :     FILE* fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb");
    1754               3 :     if (fdTHF == NULL)
    1755                 :     {
    1756               0 :         VSIFCloseL(fdGEN);
    1757                 :         CPLError( CE_Failure, CPLE_FileIO,
    1758               0 :                 "Cannot create THF file : %s.\n", osTransh01THF.c_str());
    1759               0 :         return NULL;
    1760                 :     }
    1761                 :     
    1762               3 :     CPLString osImgFilename = CPLResetExtension(pszFilename, "IMG");
    1763               3 :     FILE* fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b");
    1764               3 :     if (fdIMG == NULL)
    1765                 :     {
    1766               0 :         VSIFCloseL(fdGEN);
    1767               0 :         VSIFCloseL(fdTHF);
    1768                 :         CPLError( CE_Failure, CPLE_FileIO,
    1769               0 :                 "Cannot create image file : %s.\n", osImgFilename.c_str());
    1770               0 :         return NULL;
    1771                 :     }
    1772                 :     
    1773               3 :     ADRGDataset* poDS = new ADRGDataset();
    1774                 : 
    1775               3 :     poDS->eAccess = GA_Update;
    1776                 : 
    1777               3 :     poDS->fdGEN = fdGEN;
    1778               3 :     poDS->fdIMG = fdIMG;
    1779               3 :     poDS->fdTHF = fdTHF;
    1780                 : 
    1781               3 :     poDS->osBaseFileName = osBaseFileName;
    1782               3 :     poDS->bCreation = TRUE;
    1783               3 :     poDS->nNextAvailableBlock = 1;
    1784               3 :     poDS->NFC = (nXSize + 127) / 128;
    1785               3 :     poDS->NFL = (nYSize + 127) / 128;
    1786               3 :     poDS->nRasterXSize = nXSize;
    1787               3 :     poDS->nRasterYSize = nYSize;
    1788               3 :     poDS->bGeoTransformValid = FALSE;
    1789               3 :     poDS->TILEINDEX = new int [poDS->NFC*poDS->NFL];
    1790               3 :     memset(poDS->TILEINDEX, 0, sizeof(int)*poDS->NFC*poDS->NFL);
    1791               3 :     poDS->offsetInIMG = 2048;
    1792               3 :     poDS->poOverviewDS = NULL;
    1793                 : 
    1794               3 :     poDS->nBands = 3;
    1795              12 :     for( i = 0; i < poDS->nBands; i++ )
    1796               9 :         poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
    1797                 : 
    1798               3 :     return poDS;
    1799                 : }
    1800                 : 
    1801                 : /************************************************************************/
    1802                 : /*                  WriteGENFile_Header()                               */
    1803                 : /************************************************************************/
    1804                 : 
    1805               3 : static void WriteGENFile_Header(FILE* fd)
    1806                 : {
    1807               3 :     int nFields = 0;
    1808               3 :     int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
    1809               3 :     const char* nameOfFields[] = { "000", "001", "DRF", "DSI", "OVI", "GEN", "SPR", "BDF", "TIM" };
    1810               3 :     int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
    1811                 : 
    1812               3 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GENERAL_INFORMATION_FILE", "", ""); /* 000 */
    1813                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
    1814                 :                                                 "RTY!RID",
    1815               3 :                                                 "(A(3),A(2))");
    1816                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '1', "DATA_SET_DESCRIPTION_FIELD", /* DRF */
    1817                 :                                                 "NSH!NSV!NOZ!NOS",
    1818               3 :                                                 "(4I(2))");
    1819                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "DATA_SET-ID_FIELD", /* DSI */
    1820                 :                                                 "PRT!NAM",
    1821               3 :                                                 "(A(4),A(8))");
    1822                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "OVERVIEW_INFORMATION_FIELD", /* OVI */
    1823                 :                                                 "STR!ARV!BRV!LSO!PSO",
    1824               3 :                                                 "(I(1),I(8),I(8),A(11),A(10))");
    1825                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "GENERAL_INFORMATION_FIELD", /* GEN */
    1826                 :                                                 "STR!LOD!LAD!UNIloa!SWO!SWA!NWO!NWA!NEO!NEA!SEO!SEA!SCA!ZNA!PSP!IMR!ARV!BRV!LSO!PSO!TXT",
    1827               3 :                                                 "(I(1),2R(6),I(3),A(11),A(10),A(11),A(10),A(11),A(10),A(11),A(10),I(9),I(2),R(5),A(1),2I(8),A(11),A(10),A(64))");
    1828                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
    1829                 :                                                 "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
    1830               3 :                                                 "(4I(6),2I(3),2I(6),5I(1),A(12),A(1))");
    1831                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
    1832                 :                                                 "*BID!WS1!WS2",
    1833               3 :                                                 "(A(5),I(5),I(5))");
    1834                 :     sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '1', "TILE_INDEX_MAP_FIELD", /* TIM */
    1835                 :                                                 "*TSI",
    1836               3 :                                                 "(I(5))");
    1837                 :     
    1838               3 :     FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    1839               3 : }
    1840                 : 
    1841                 : /************************************************************************/
    1842                 : /*            WriteGENFile_DataSetDescriptionRecord()                   */
    1843                 : /************************************************************************/
    1844                 : 
    1845                 : /* Write DATA_SET_DESCRIPTION_RECORD */
    1846               3 : static void WriteGENFile_DataSetDescriptionRecord(FILE* fd)
    1847                 : {
    1848               3 :     int nFields = 0;
    1849               3 :     int sizeOfFields[] = {0, 0};
    1850               3 :     const char* nameOfFields[] = { "001", "DRF" };
    1851               3 :     int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
    1852                 : 
    1853                 :     /* Field 001 */
    1854               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "DSS", 3); /* RTY */
    1855               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    1856               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1857               3 :     nFields++;
    1858                 : 
    1859                 :     /* Field DRF */
    1860               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSH */
    1861               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSV */
    1862               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOZ */
    1863               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOS */
    1864               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1865               3 :     nFields++;
    1866                 : 
    1867               3 :     FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    1868               3 : }
    1869                 : 
    1870                 : /************************************************************************/
    1871                 : /*                    WriteGENFile_OverviewRecord()                     */
    1872                 : /************************************************************************/
    1873                 : 
    1874                 : /* Write OVERVIEW_RECORD */
    1875               3 : static void WriteGENFile_OverviewRecord(FILE* fd, CPLString& osBaseFileName, int ARV, int BRV, double LSO, double PSO,
    1876                 :                                         int nOvSizeX, int nOvSizeY, int NFL, int NFC, int* TILEINDEX)
    1877                 : {
    1878               3 :     int nFields = 0;
    1879               3 :     int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
    1880               3 :     const char* nameOfFields[] = { "001", "DSI", "OVI", "SPR", "BDF", "TIM" };
    1881               3 :     int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
    1882                 :     
    1883                 :     /* Field 001 */
    1884               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */
    1885               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    1886               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1887               3 :     nFields++;
    1888                 : 
    1889                 :     /* Field DSI */
    1890               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
    1891               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
    1892               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1893               3 :     nFields++;
    1894                 :     
    1895                 :     /* Field OVI */
    1896               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
    1897               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */   /* FIXME */
    1898               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */   /* FIXME */
    1899               3 :     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */   /* FIXME */
    1900               3 :     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */    /* FIXME */
    1901               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1902               3 :     nFields++;
    1903                 :     
    1904                 :     /* Field SPR */
    1905               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
    1906               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX-1, 6); /* NUS */
    1907               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeY-1, 6); /* NLL */
    1908               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
    1909               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */
    1910               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */
    1911               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
    1912               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
    1913               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
    1914               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
    1915               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
    1916               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
    1917               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
    1918                 :     char tmp[12+1];
    1919               3 :     sprintf(tmp, "%s.IMG", osBaseFileName.c_str()); /* FIXME */
    1920               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 12); /* BAD */
    1921               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
    1922               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1923               3 :     nFields++;
    1924                 :     
    1925                 :     /* Field BDF */
    1926               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
    1927               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    1928               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    1929               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
    1930               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    1931               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    1932               3 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
    1933               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    1934               3 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    1935               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1936               3 :     nFields++;
    1937                 :     
    1938                 :     /* Field TIM */
    1939                 :     int i;
    1940               6 :     for(i=0;i<NFL*NFC;i++)
    1941                 :     {
    1942               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
    1943                 :     }
    1944               3 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1945               3 :     nFields++;
    1946                 :     
    1947               3 :     FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    1948               3 : }
    1949                 : 
    1950                 : /************************************************************************/
    1951                 : /*              WriteGENFile_GeneralInformationRecord()                 */
    1952                 : /************************************************************************/
    1953                 : 
    1954                 : /* Write GENERAL_INFORMATION_RECORD */
    1955               4 : static void WriteGENFile_GeneralInformationRecord(FILE* fd, CPLString& osNAM, CPLString& osBAD,
    1956                 :                                                   int ARV, int BRV, double LSO, double PSO,
    1957                 :                                                   double* adfGeoTransform, int SCA,
    1958                 :                                                   int nRasterXSize, int nRasterYSize,
    1959                 :                                                   int NFL, int NFC, int* TILEINDEX)
    1960                 : 
    1961                 : {
    1962               4 :     int nFields = 0;
    1963               4 :     int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
    1964               4 :     const char* nameOfFields[] = { "001", "DSI", "GEN", "SPR", "BDF", "TIM" };
    1965               4 :     int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
    1966                 :     
    1967                 :     /* Field 001 */
    1968               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "GIN", 3); /* RTY */
    1969               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    1970               4 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1971               4 :     nFields++;
    1972                 : 
    1973                 :     /* Field DSI */
    1974               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
    1975               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
    1976               4 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    1977               4 :     nFields++;
    1978                 :     
    1979                 :     /* Field `GEN */
    1980               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
    1981               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LOD */   /* FIXME */
    1982               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LAD */   /* FIXME */
    1983               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3); /* UNIloa */   /* FIXME */
    1984               4 :     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
    1985               4 :     sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
    1986               4 :     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* NWO */
    1987               4 :     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NWA */
    1988               4 :     sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
    1989               4 :     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
    1990               4 :     sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */
    1991               4 :     sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */
    1992               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, SCA, 9); /* SCA */
    1993               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* ZNA */  /* FIXME */
    1994               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "100.0", 5); /* PSP */
    1995               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* IMR */
    1996               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */
    1997               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */
    1998               4 :     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */
    1999               4 :     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */
    2000               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 64); /* TXT */
    2001               4 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2002               4 :     nFields++;
    2003                 : 
    2004                 :     /* Field SPR */
    2005               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
    2006               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterXSize-1, 6); /* NUS */
    2007               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterYSize-1, 6); /* NLL */
    2008               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
    2009               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */
    2010               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */
    2011               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
    2012               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
    2013               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
    2014               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
    2015               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
    2016               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
    2017               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
    2018               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, osBAD.c_str(), 12); /* BAD */
    2019               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
    2020               4 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2021               4 :     nFields++;
    2022                 :     
    2023                 :     /* Field BDF */
    2024               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
    2025               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    2026               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    2027               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
    2028               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    2029               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    2030               4 :     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
    2031               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    2032               4 :     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    2033               4 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2034               4 :     nFields++;
    2035                 :     
    2036                 :     /* Field TIM */
    2037                 :     int i;
    2038               8 :     for(i=0;i<NFL*NFC;i++)
    2039                 :     {
    2040               4 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
    2041                 :     }
    2042               4 :     sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2043               4 :     nFields++;
    2044                 : 
    2045               4 :     FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    2046               4 : }
    2047                 : 
    2048                 : /************************************************************************/
    2049                 : /*                        WriteGENFile()                                */
    2050                 : /************************************************************************/
    2051                 : 
    2052               3 : void ADRGDataset::WriteGENFile()
    2053                 : {
    2054               3 :     if (!bGeoTransformValid)
    2055                 :     {
    2056               0 :         CPLError(CE_Failure, CPLE_AppDefined, "No geo transform available !");
    2057               0 :         adfGeoTransform[0] = 0;
    2058               0 :         adfGeoTransform[3] = 0;
    2059               0 :         adfGeoTransform[1] = 1;
    2060               0 :         adfGeoTransform[5] = 1;
    2061                 :     }
    2062                 : 
    2063               3 :     LSO = adfGeoTransform[0];
    2064               3 :     PSO = adfGeoTransform[3];
    2065               3 :     ARV = (int)floor(360. / adfGeoTransform[1] + .5);
    2066               3 :     BRV = (int)floor(-360. / adfGeoTransform[5] + .5);
    2067                 :     
    2068                 :     /*ARV = ((ARV + 255) / 512) * 512;
    2069                 :     BRV = ((BRV + 255) / 512) * 512;*/
    2070                 :     
    2071               3 :     int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
    2072                 : 
    2073               3 :     int nOvSizeX = nRasterXSize; // FIXME
    2074               3 :     int nOvSizeY = nRasterYSize; // FIXME
    2075                 : 
    2076                 :     /* Write header */
    2077               3 :     WriteGENFile_Header(fdGEN);
    2078                 : 
    2079                 :     /* Write DATA_SET_DESCRIPTION_RECORD */
    2080               3 :     WriteGENFile_DataSetDescriptionRecord(fdGEN);
    2081                 : 
    2082                 :     /* Write OVERVIEW_RECORD */
    2083                 :     WriteGENFile_OverviewRecord(fdGEN, osBaseFileName, ARV, BRV, LSO, PSO,
    2084               3 :                                 nOvSizeX, nOvSizeY, NFL, NFC, TILEINDEX);
    2085                 : 
    2086                 :     /* Write GENERAL_INFORMATION_RECORD */
    2087               3 :     CPLString osNAM = osBaseFileName;
    2088                 :     char tmp[12+1];
    2089               3 :     sprintf(tmp, "%s.IMG", osNAM.c_str());
    2090               3 :     CPLString osBAD = tmp;
    2091                 :     WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
    2092               3 :                                           adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
    2093                 :                                           
    2094               3 :     if (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")))
    2095                 :     {
    2096               1 :         strncpy(tmp, osBaseFileName.c_str(), 6);
    2097               1 :         tmp[6] = '\0';
    2098               1 :         strcat(tmp, "02");
    2099               1 :         osNAM = tmp;
    2100               1 :         sprintf(tmp, "%s.IMG", osNAM.c_str());
    2101               1 :         osBAD = tmp;
    2102                 :         WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
    2103               1 :                                               adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
    2104               3 :     }
    2105               3 : }
    2106                 : 
    2107                 : /************************************************************************/
    2108                 : /*                        WriteTHFFile()                                */
    2109                 : /************************************************************************/
    2110                 : 
    2111               3 : void ADRGDataset::WriteTHFFile()
    2112                 : {
    2113               3 :     FILE* fd = fdTHF;
    2114                 : 
    2115                 :     /* Write header */
    2116                 :     {
    2117               3 :         int nFields = 0;
    2118               3 :         int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    2119               3 :         const char* nameOfFields[] = { "000", "001", "VDR", "FDR", "QSR", "QUV", "CPS", "CPT", "SPR", "BDF", "VFF"};
    2120               3 :         int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
    2121                 : 
    2122               3 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "TRANSMITTAL_HEADER_FILE", "", ""); /* 000 */
    2123                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
    2124                 :                                                   "RTY!RID",
    2125               3 :                                                   "(A(3),A(2))");
    2126                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TRANSMITTAL_HEADER_FIELD", /* VDR */
    2127                 :                                                   "MSD!VOO!ADR!NOV!SQN!NOF!URF!EDN!DAT",
    2128               3 :                                                   "(A(1),A(200),A(1),I(1),I(1),I(3),A(16),I(3),A(12))");
    2129                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_DESCRIPTION_FIELD", /* FDR */
    2130                 :                                                   "NAM!STR!PRT!SWO!SWA!NEO!NEA",
    2131               3 :                                                   "(A(8),I(1),A(4),A(11),A(10),A(11),A(10))");
    2132                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "SECURITY_AND_RELEASE_FIELD", /* QSR */
    2133                 :                                                   "QSS!QOD!DAT!QLE",
    2134               3 :                                                   "(A(1),A(1),A(12),A(200))");
    2135                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "VOLUME_UP_TO_DATENESS_FIELD", /* QUV */
    2136                 :                                                   "SRC!DAT!SPA",
    2137               3 :                                                   "(A(100),A(12),A(20))");
    2138                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_IDENTIFIER_FIELD", /* CPS */
    2139                 :                                                   "PNM!DWV!REF!PUR!PIR!PIG!PIB",
    2140               3 :                                                   "(A(7),I(6),R(5),R(5),I(3),I(3),I(3))");
    2141                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_INFORMATION_FIELD", /* CPT */
    2142                 :                                                   "STR!SCR",
    2143               3 :                                                   "(I(1),A(100))");
    2144                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
    2145                 :                                                   "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
    2146               3 :                                                   "(I(6),I(6),I(6),I(6),I(3),I(3),I(6),I(6),I(1),I(1),I(1),I(1),I(1),A(12),A(1))");
    2147                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
    2148                 :                                                   "*BID!WS1!WS2",
    2149               3 :                                                   "(A(5),I(5),I(5))");
    2150                 :         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD", /* VFF */
    2151                 :                                                   "VFF",
    2152               3 :                                                   "(A(51))");
    2153                 : 
    2154               3 :         FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    2155                 :     }
    2156                 : 
    2157                 :     /* Write TRANSMITTAL_DESCRIPTION_RECORD */
    2158                 :     {
    2159               3 :         int nFields = 0;
    2160               3 :         int sizeOfFields[] = {0, 0, 0};
    2161               3 :         const char* nameOfFields[] = { "001", "VDR", "FDR" };
    2162               3 :         int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
    2163                 : 
    2164                 :         /* Field 001 */
    2165               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "VTH", 3); /* RTY */
    2166               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    2167               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2168               3 :         nFields++;
    2169                 : 
    2170                 :         /* Field VDR */
    2171               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* MSD */
    2172               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* VOO */ /* Title and address of originator */
    2173               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* ADR */
    2174               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* NOV */
    2175               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* SQN */
    2176               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* NOF */
    2177               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16); /* URF */ /* DMA stock number for this CDROM */
    2178               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* EDN */
    2179               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "017,19940101", 12); /* DAT */  /* Publication date */
    2180               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2181               3 :         nFields++;
    2182                 : 
    2183                 :         /* Field FDR */
    2184               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
    2185               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
    2186               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
    2187               3 :         sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
    2188               3 :         sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
    2189               3 :         sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
    2190               3 :         sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
    2191               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2192               3 :         nFields++;
    2193                 : 
    2194               3 :         FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    2195                 :     }
    2196                 : 
    2197                 :     /* Write SECURITY_AND_UPDATE_RECORD */
    2198                 :     {
    2199               3 :         int nFields = 0;
    2200               3 :         int sizeOfFields[] = {0, 0, 0};
    2201               3 :         const char* nameOfFields[] = { "001", "QSR", "QUV" };
    2202               3 :         int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
    2203                 : 
    2204                 :         /* Field 001 */
    2205               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "LCF", 3); /* RTY */
    2206               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    2207               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2208               3 :         nFields++;
    2209                 : 
    2210                 :         /* Field VDR */
    2211               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "U", 1); /* QSS */
    2212               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* QOD */
    2213               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 12); /* DAT */
    2214               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* QLE */
    2215               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2216               3 :         nFields++;
    2217                 : 
    2218                 :         /* Field FDR */
    2219               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)", 100); /* SRC */
    2220               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */
    2221               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */
    2222               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2223               3 :         nFields++;
    2224                 : 
    2225               3 :         FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    2226                 :     }
    2227                 : 
    2228                 :     /* Write TEST_PATCH_DATA_RECORD */
    2229                 :     {
    2230               3 :         int nFields = 0;
    2231               3 :         int sizeOfFields[] = {0, 0, 0, 0, 0};
    2232               3 :         const char* nameOfFields[] = { "001", "CPS", "CPT", "SPR", "BDF" };
    2233               3 :         int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
    2234                 : 
    2235                 :         /* Field 001 */
    2236               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TPA", 3); /* RTY */
    2237               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    2238               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2239               3 :         nFields++;
    2240                 : 
    2241                 :         /* Field CPS */
    2242               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "Black", 7); /* PNM */
    2243               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 6); /* DMV */
    2244               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* REF */
    2245               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* PUR */
    2246               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIR */
    2247               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIG */
    2248               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIB */
    2249               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2250               3 :         nFields++;
    2251                 : 
    2252                 :         /* Field CPT */
    2253               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
    2254               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 100); /* SCR */
    2255               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2256               3 :         nFields++;
    2257                 : 
    2258               3 :         int nPatchXSize = 512;
    2259               3 :         int nPatchYSize = 512;
    2260                 : 
    2261                 :         /* Field SPR */
    2262               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
    2263               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchXSize-1, 6); /* NUS */
    2264               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchYSize-1, 6); /* NLL */
    2265               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
    2266               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */
    2267               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */
    2268               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
    2269               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
    2270               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
    2271               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
    2272               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
    2273               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
    2274               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
    2275               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12); /* BAD */
    2276               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* TIF */
    2277               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2278               3 :         nFields++;
    2279                 : 
    2280                 :         /* Field BDF */
    2281               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
    2282               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    2283               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    2284               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
    2285               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    2286               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    2287               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
    2288               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
    2289               3 :         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
    2290               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2291               3 :         nFields++;
    2292                 : 
    2293               3 :         FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
    2294                 :     }
    2295                 : 
    2296                 :     /* Write TRANSMITTAL_FILENAMES_RECORD */
    2297                 :     {
    2298                 :         char tmp[12+1];
    2299                 : 
    2300               3 :         int nFields = 0;
    2301               3 :         int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0};
    2302                 :         
    2303                 :         /* Debug option to simulate ADRG datasets made of several images */
    2304               3 :         int nTotalFields = (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
    2305                 :         
    2306               3 :         const char* nameOfFields[] = { "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
    2307               3 :         int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
    2308                 : 
    2309                 :         /* Field 001 */
    2310               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TFN", 3); /* RTY */
    2311               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
    2312               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2313               3 :         nFields++;
    2314                 : 
    2315                 :         /* Field VFF */
    2316               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51); /* VFF */
    2317               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2318               3 :         nFields++;
    2319                 : 
    2320                 :         /* Field VFF */
    2321               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51); /* VFF */
    2322               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2323               3 :         nFields++;
    2324                 : 
    2325                 :         /* Field VFF */
    2326               3 :         sprintf(tmp, "%s.GEN", osBaseFileName.c_str());
    2327               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
    2328               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2329               3 :         nFields++;
    2330                 : 
    2331                 :         /* Field VFF */
    2332               3 :         sprintf(tmp, "%s.IMG", osBaseFileName.c_str());
    2333               3 :         sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
    2334               3 :         sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2335               3 :         nFields++;
    2336                 :         
    2337               3 :         if (nTotalFields == 6)
    2338                 :         {
    2339                 :             /* Field VFF */
    2340               1 :             strncpy(tmp, osBaseFileName.c_str(), 6);
    2341               1 :             tmp[6] = '\0';
    2342               1 :             strcat(tmp, "02.IMG");
    2343               1 :             sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
    2344               1 :             sizeOfFields[nFields] += WriteFieldTerminator(fd);
    2345               1 :             nFields++;
    2346                 :         }
    2347                 :         
    2348               3 :         FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, nameOfFields);
    2349                 :     }
    2350               3 : }
    2351                 : 
    2352                 : /************************************************************************/
    2353                 : /*                         GDALRegister_ADRG()                          */
    2354                 : /************************************************************************/
    2355                 : 
    2356             338 : void GDALRegister_ADRG()
    2357                 : 
    2358                 : {
    2359                 :     GDALDriver  *poDriver;
    2360                 : 
    2361             338 :     if( GDALGetDriverByName( "ADRG" ) == NULL )
    2362                 :     {
    2363             336 :         poDriver = new GDALDriver();
    2364                 :         
    2365             336 :         poDriver->SetDescription( "ADRG" );
    2366                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    2367             336 :                                    "ARC Digitized Raster Graphics" );
    2368                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    2369             336 :                                    "frmt_various.html#ADRG" );
    2370             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" );
    2371                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    2372             336 :                                    "Byte" );
    2373                 : 
    2374             336 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2375                 : 
    2376             336 :         poDriver->pfnOpen = ADRGDataset::Open;
    2377             336 :         poDriver->pfnCreate = ADRGDataset::Create;
    2378                 : 
    2379             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2380                 :     }
    2381             338 : }
    2382                 : 

Generated by: LCOV version 1.7