LCOV - code coverage report
Current view: directory - frmts/adrg - adrgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1218 1045 85.8 %
Date: 2012-04-28 Functions: 45 40 88.9 %

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

Generated by: LCOV version 1.7