LTP GCOV extension - code coverage report
Current view: directory - frmts/adrg - adrgdataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 1192
Code covered: 85.9 % Executed lines: 1024

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

Generated by: LTP GCOV extension version 1.5