mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-25 14:22:54 -06:00
2269 lines
82 KiB
C++
2269 lines
82 KiB
C++
/******************************************************************************
|
|
* $Id: adrgdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
|
|
*
|
|
* Purpose: ADRG reader
|
|
* Author: Even Rouault, even.rouault at mines-paris.org
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "gdal_pam.h"
|
|
#include "ogr_spatialref.h"
|
|
#include "cpl_string.h"
|
|
#include "iso8211.h"
|
|
|
|
CPL_CVSID("$Id: adrgdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
|
|
|
|
#define N_ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
|
|
|
|
class ADRGDataset : public GDALPamDataset
|
|
{
|
|
friend class ADRGRasterBand;
|
|
|
|
CPLString osGENFileName;
|
|
CPLString osIMGFileName;
|
|
|
|
VSILFILE* fdIMG;
|
|
int* TILEINDEX;
|
|
int offsetInIMG;
|
|
int NFC;
|
|
int NFL;
|
|
double LSO;
|
|
double PSO;
|
|
int ARV;
|
|
int BRV;
|
|
|
|
char** papszSubDatasets;
|
|
|
|
ADRGDataset* poOverviewDS;
|
|
|
|
/* For creation */
|
|
int bCreation;
|
|
VSILFILE* fdGEN;
|
|
VSILFILE* fdTHF;
|
|
int bGeoTransformValid;
|
|
double adfGeoTransform[6];
|
|
int nNextAvailableBlock;
|
|
CPLString osBaseFileName;
|
|
|
|
static char** GetGENListFromTHF(const char* pszFileName);
|
|
static char** GetIMGListFromGEN(const char* pszFileName, int* pnRecordIndex = NULL);
|
|
static ADRGDataset* OpenDataset(const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record = NULL);
|
|
static DDFRecord* FindRecordInGENForIMG(DDFModule& module,
|
|
const char* pszGENFileName, const char* pszIMGFileName);
|
|
|
|
public:
|
|
ADRGDataset();
|
|
virtual ~ADRGDataset();
|
|
|
|
virtual const char *GetProjectionRef(void);
|
|
virtual CPLErr GetGeoTransform( double * padfGeoTransform );
|
|
virtual CPLErr SetGeoTransform( double * padfGeoTransform );
|
|
|
|
virtual char **GetMetadataDomainList();
|
|
virtual char **GetMetadata( const char * pszDomain = "" );
|
|
|
|
virtual char **GetFileList();
|
|
|
|
void AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
|
|
|
|
static GDALDataset *Open( GDALOpenInfo * );
|
|
static GDALDataset *Create(const char* pszFilename, int nXSize, int nYSize,
|
|
int nBands, GDALDataType eType, char **papszOptions);
|
|
|
|
static double GetLongitudeFromString(const char* str);
|
|
static double GetLatitudeFromString(const char* str);
|
|
|
|
void WriteGENFile();
|
|
void WriteTHFFile();
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* ADRGRasterBand */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
class ADRGRasterBand : public GDALPamRasterBand
|
|
{
|
|
friend class ADRGDataset;
|
|
|
|
public:
|
|
ADRGRasterBand( ADRGDataset *, int );
|
|
|
|
virtual GDALColorInterp GetColorInterpretation();
|
|
virtual CPLErr IReadBlock( int, int, void * );
|
|
virtual CPLErr IWriteBlock( int, int, void * );
|
|
|
|
virtual double GetNoDataValue( int *pbSuccess = NULL );
|
|
|
|
// virtual int GetOverviewCount();
|
|
// virtual GDALRasterBand* GetOverview(int i);
|
|
};
|
|
|
|
|
|
/************************************************************************/
|
|
/* ADRGRasterBand() */
|
|
/************************************************************************/
|
|
|
|
ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDS, int nBand )
|
|
|
|
{
|
|
this->poDS = poDS;
|
|
this->nBand = nBand;
|
|
|
|
eDataType = GDT_Byte;
|
|
|
|
nBlockXSize = 128;
|
|
nBlockYSize = 128;
|
|
}
|
|
|
|
#if 0
|
|
|
|
/* We have a problem with the overview. Its geo bounding box doesn't match */
|
|
/* exactly the one of the main image. We should handle the shift between */
|
|
/* the two top level corners... */
|
|
|
|
/************************************************************************/
|
|
/* GetOverviewCount() */
|
|
/************************************************************************/
|
|
|
|
int ADRGRasterBand::GetOverviewCount()
|
|
|
|
{
|
|
ADRGDataset* poDS = (ADRGDataset*)this->poDS;
|
|
if( poDS->poOverviewDS )
|
|
return 1;
|
|
else
|
|
return GDALRasterBand::GetOverviewCount();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetOverview() */
|
|
/************************************************************************/
|
|
|
|
GDALRasterBand *ADRGRasterBand::GetOverview( int i )
|
|
|
|
{
|
|
ADRGDataset* poDS = (ADRGDataset*)this->poDS;
|
|
if( poDS->poOverviewDS )
|
|
{
|
|
if( i < 0 || i >= 1 )
|
|
return NULL;
|
|
else
|
|
return poDS->poOverviewDS->GetRasterBand(nBand);
|
|
}
|
|
else
|
|
return GDALRasterBand::GetOverview( i );
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* GetNoDataValue() */
|
|
/************************************************************************/
|
|
|
|
double ADRGRasterBand::GetNoDataValue( int *pbSuccess )
|
|
{
|
|
if (pbSuccess)
|
|
*pbSuccess = TRUE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColorInterpretation() */
|
|
/************************************************************************/
|
|
|
|
GDALColorInterp ADRGRasterBand::GetColorInterpretation()
|
|
|
|
{
|
|
if( nBand == 1 )
|
|
return GCI_RedBand;
|
|
|
|
else if( nBand == 2 )
|
|
return GCI_GreenBand;
|
|
|
|
else
|
|
return GCI_BlueBand;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IReadBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
|
|
void * pImage )
|
|
|
|
{
|
|
ADRGDataset* poDS = (ADRGDataset*)this->poDS;
|
|
int offset;
|
|
int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
|
|
if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
|
|
nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
|
|
return CE_Failure;
|
|
}
|
|
CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
|
|
|
|
if (poDS->TILEINDEX)
|
|
{
|
|
if (poDS->TILEINDEX[nBlock] == 0)
|
|
{
|
|
memset(pImage, 0, 128 * 128);
|
|
return CE_None;
|
|
}
|
|
offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
|
|
}
|
|
else
|
|
offset = poDS->offsetInIMG + nBlock * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
|
|
|
|
if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
|
|
{
|
|
CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
|
|
return CE_Failure;
|
|
}
|
|
if (VSIFReadL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
|
|
{
|
|
CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
|
|
return CE_Failure;
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IWriteBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
|
|
void * pImage )
|
|
|
|
{
|
|
ADRGDataset* poDS = (ADRGDataset*)this->poDS;
|
|
int offset;
|
|
int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
|
|
if (poDS->eAccess != GA_Update)
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
|
|
nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
|
|
return CE_Failure;
|
|
}
|
|
CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
|
|
|
|
if (poDS->TILEINDEX[nBlock] == 0)
|
|
{
|
|
unsigned int i;
|
|
int* pi = (int*)pImage;
|
|
for(i=0;i<128*128 / sizeof(int);i++)
|
|
{
|
|
if (pi[i])
|
|
break;
|
|
}
|
|
if (i == 128*128 / sizeof(int))
|
|
{
|
|
return CE_None;
|
|
}
|
|
|
|
poDS->TILEINDEX[nBlock] = poDS->nNextAvailableBlock ++;
|
|
}
|
|
|
|
offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
|
|
|
|
if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
|
|
{
|
|
CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
|
|
return CE_Failure;
|
|
}
|
|
if (VSIFWriteL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
|
|
{
|
|
CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
|
|
return CE_Failure;
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
static unsigned int WriteSubFieldStr(VSILFILE* fd, const char* pszStr, unsigned int size)
|
|
{
|
|
char* str = (char*)CPLMalloc(size+1);
|
|
memset(str, ' ', size);
|
|
if (strlen(pszStr) > size)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "strlen(pszStr) > size");
|
|
CPLFree(str);
|
|
return size;
|
|
}
|
|
strcpy(str, pszStr);
|
|
str[strlen(pszStr)] = ' ';
|
|
VSIFWriteL(str, 1, size, fd);
|
|
CPLFree(str);
|
|
return size;
|
|
}
|
|
|
|
static unsigned int WriteSubFieldInt(VSILFILE* fd, int val, unsigned int size)
|
|
{
|
|
char* str = (char*)CPLMalloc(size+1);
|
|
char formatStr[32];
|
|
sprintf( formatStr, "%%0%dd", size);
|
|
sprintf( str, formatStr, val);
|
|
VSIFWriteL(str, 1, size, fd);
|
|
CPLFree(str);
|
|
return size;
|
|
}
|
|
|
|
static unsigned int WriteFieldTerminator(VSILFILE* fd)
|
|
{
|
|
char fieldTerminator = 30;
|
|
VSIFWriteL(&fieldTerminator, 1, 1, fd);
|
|
return 1;
|
|
}
|
|
|
|
static unsigned int WriteUnitTerminator(VSILFILE* fd)
|
|
{
|
|
char fieldTerminator = 31;
|
|
VSIFWriteL(&fieldTerminator, 1, 1, fd);
|
|
return 1;
|
|
}
|
|
|
|
static unsigned int WriteLongitude(VSILFILE* fd, double val)
|
|
{
|
|
char str[11+1];
|
|
char sign = (val >= 0) ? '+' : '-';
|
|
if (val < 0) val = -val;
|
|
int ddd = (int)val;
|
|
int mm = (int)((val - ddd) * 60);
|
|
double ssdotss = ((val - ddd) * 60 - mm) * 60;
|
|
sprintf(str, "%c%03d%02d%05.2f", sign, ddd, mm, ssdotss);
|
|
CPLAssert((int)strlen(str) == 11);
|
|
VSIFWriteL(str, 1, 11, fd);
|
|
return 11;
|
|
}
|
|
|
|
static unsigned int WriteLatitude(VSILFILE* fd, double val)
|
|
{
|
|
char str[10+1];
|
|
char sign = (val >= 0) ? '+' : '-';
|
|
if (val < 0) val = -val;
|
|
int dd = (int)val;
|
|
int mm = (int)((val - dd) * 60);
|
|
double ssdotss = ((val - dd) * 60 - mm) * 60;
|
|
sprintf(str, "%c%02d%02d%05.2f", sign, dd, mm, ssdotss);
|
|
CPLAssert((int)strlen(str) == 10);
|
|
VSIFWriteL(str, 1, 10, fd);
|
|
return 10;
|
|
}
|
|
|
|
static int BeginLeader(VSILFILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
|
|
int nFields)
|
|
{
|
|
int pos = (int)VSIFTellL(fd);
|
|
VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * (vsi_l_offset)nFields + 1, SEEK_CUR);
|
|
return pos;
|
|
}
|
|
|
|
static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
|
|
int nFields, int* sizeOfFields, const char** nameOfFields)
|
|
{
|
|
int endPos = (int)VSIFTellL(fd);
|
|
VSIFSeekL(fd, beginPos, SEEK_SET);
|
|
|
|
int nLeaderSize = 24;
|
|
char szLeader[24+1];
|
|
memset(szLeader, ' ', nLeaderSize);
|
|
|
|
int i;
|
|
int nDataSize = 0;
|
|
int nFieldOffset = 0;
|
|
for(i=0;i<nFields;i++)
|
|
nDataSize += sizeOfFields[i];
|
|
nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
|
|
nDataSize += nFieldOffset;
|
|
|
|
sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
|
|
szLeader[5] = ' ';
|
|
szLeader[6] = 'D';
|
|
|
|
sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
|
|
szLeader[17] = ' ';
|
|
|
|
szLeader[20] = (char) ('0' + sizeFieldLength);
|
|
szLeader[21] = (char) ('0' + sizeFieldPos);
|
|
szLeader[22] = '0';
|
|
szLeader[23] = (char) ('0' + sizeFieldTag);
|
|
|
|
VSIFWriteL(szLeader, 1, nLeaderSize, fd);
|
|
|
|
int acc = 0;
|
|
for(i=0;i<nFields;i++)
|
|
{
|
|
VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
|
|
WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
|
|
WriteSubFieldInt(fd, acc, sizeFieldPos);
|
|
acc += sizeOfFields[i];
|
|
}
|
|
WriteFieldTerminator(fd);
|
|
|
|
VSIFSeekL(fd, endPos, SEEK_SET);
|
|
}
|
|
|
|
|
|
static int BeginHeader(VSILFILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
|
|
int nFields)
|
|
{
|
|
int pos = (int)VSIFTellL(fd);
|
|
VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1, SEEK_CUR);
|
|
return pos;
|
|
}
|
|
|
|
static void FinishWriteHeader(VSILFILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
|
|
int nFields, int* sizeOfFields, const char** nameOfFields)
|
|
{
|
|
int endPos = (int)VSIFTellL(fd);
|
|
VSIFSeekL(fd, beginPos, SEEK_SET);
|
|
|
|
int nLeaderSize = 24;
|
|
char szLeader[24+1];
|
|
memset(szLeader, ' ', nLeaderSize);
|
|
|
|
int i;
|
|
int nDataSize = 0;
|
|
int nFieldOffset = 0;
|
|
for(i=0;i<nFields;i++)
|
|
nDataSize += sizeOfFields[i];
|
|
nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
|
|
nDataSize += nFieldOffset;
|
|
|
|
sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
|
|
szLeader[5] = '2';
|
|
szLeader[6] = 'L';
|
|
|
|
szLeader[10] = '0';
|
|
szLeader[11] = '6';
|
|
sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
|
|
szLeader[17] = ' ';
|
|
|
|
szLeader[20] = (char) ('0' + sizeFieldLength);
|
|
szLeader[21] = (char) ('0' + sizeFieldPos);
|
|
szLeader[22] = '0';
|
|
szLeader[23] = (char) ('0' + sizeFieldTag);
|
|
|
|
VSIFWriteL(szLeader, 1, nLeaderSize, fd);
|
|
|
|
int acc = 0;
|
|
for(i=0;i<nFields;i++)
|
|
{
|
|
VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
|
|
WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
|
|
WriteSubFieldInt(fd, acc, sizeFieldPos);
|
|
acc += sizeOfFields[i];
|
|
}
|
|
WriteFieldTerminator(fd);
|
|
|
|
VSIFSeekL(fd, endPos, SEEK_SET);
|
|
}
|
|
|
|
static int WriteFieldDecl(VSILFILE* fd, char _data_struct_code , char _data_type_code, const char* _fieldName,
|
|
const char* _arrayDescr, const char* _formatControls)
|
|
{
|
|
VSIFWriteL(&_data_struct_code, 1, 1, fd);
|
|
VSIFWriteL(&_data_type_code, 1, 1, fd);
|
|
if (_data_struct_code == ' ')
|
|
{
|
|
VSIFWriteL(" ", 1 , 4, fd);
|
|
}
|
|
else
|
|
{
|
|
VSIFWriteL("00;&", 1 , 4, fd);
|
|
}
|
|
int len = 6;
|
|
VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd);
|
|
len += strlen(_fieldName);
|
|
if (_arrayDescr[0])
|
|
{
|
|
len += WriteUnitTerminator(fd);
|
|
VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd);
|
|
len += strlen(_arrayDescr);
|
|
|
|
len += WriteUnitTerminator(fd);
|
|
VSIFWriteL(_formatControls, 1, strlen(_formatControls), fd);
|
|
len += strlen(_formatControls);
|
|
}
|
|
len += WriteFieldTerminator(fd);
|
|
return len;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* ADRGDataset() */
|
|
/************************************************************************/
|
|
|
|
ADRGDataset::ADRGDataset()
|
|
{
|
|
bCreation = FALSE;
|
|
poOverviewDS = NULL;
|
|
fdIMG = NULL;
|
|
fdGEN = NULL;
|
|
fdTHF = NULL;
|
|
TILEINDEX = NULL;
|
|
papszSubDatasets = NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~ADRGDataset() */
|
|
/************************************************************************/
|
|
|
|
ADRGDataset::~ADRGDataset()
|
|
{
|
|
if (poOverviewDS)
|
|
{
|
|
delete poOverviewDS;
|
|
}
|
|
|
|
CSLDestroy(papszSubDatasets);
|
|
|
|
if (bCreation)
|
|
{
|
|
GDALPamDataset::FlushCache();
|
|
|
|
/* Write header and padding of image */
|
|
VSIFSeekL(fdIMG, 0, SEEK_SET);
|
|
{
|
|
VSILFILE* fd = fdIMG;
|
|
int nFields = 0;
|
|
int sizeOfFields[] = { 0, 0, 0, 0 };
|
|
const char* nameOfFields[] = { "000", "001", "PAD", "SCN" };
|
|
int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GEO_DATA_FILE", "", ""); /* 000 */
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
|
|
"RTY!RID",
|
|
"(A(3),A(2))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "PADDING_FIELD", /* PAD */
|
|
"PAD",
|
|
"(A)");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '0', "PIXEL_FIELD", /* SCN */
|
|
"*PIX",
|
|
"(A(1))");
|
|
|
|
FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
|
|
/* Write IMAGE_RECORD */
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0};
|
|
const char* nameOfFields[] = { "001", "PAD", "SCN" };
|
|
int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "IMG", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field PAD */
|
|
int endPos = (int)VSIFTellL(fd);
|
|
char* pad = (char*)CPLMalloc(2047 - endPos);
|
|
memset(pad, ' ', 2047 - endPos);
|
|
VSIFWriteL(pad, 1, 2047 - endPos, fd);
|
|
CPLFree(pad);
|
|
WriteFieldTerminator(fd);
|
|
sizeOfFields[nFields] += 2047 - endPos + 1;
|
|
nFields++;
|
|
|
|
/* Field SCN */
|
|
sizeOfFields[nFields] = (nNextAvailableBlock - 1) * 128 * 128 * 3;
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
}
|
|
|
|
/* Write terminal field terminator */
|
|
int offset = offsetInIMG + (nNextAvailableBlock - 1) * 128 * 128 * 3;
|
|
VSIFSeekL(fdIMG, offset, SEEK_SET);
|
|
WriteFieldTerminator(fdIMG);
|
|
|
|
WriteGENFile();
|
|
WriteTHFFile();
|
|
}
|
|
|
|
if (fdIMG)
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
}
|
|
|
|
if (fdGEN)
|
|
{
|
|
VSIFCloseL(fdGEN);
|
|
}
|
|
if (fdTHF)
|
|
{
|
|
VSIFCloseL(fdTHF);
|
|
}
|
|
|
|
if (TILEINDEX)
|
|
{
|
|
delete [] TILEINDEX;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetFileList() */
|
|
/************************************************************************/
|
|
|
|
char ** ADRGDataset::GetFileList()
|
|
{
|
|
char** papszFileList = GDALPamDataset::GetFileList();
|
|
|
|
if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
|
|
{
|
|
CPLString osMainFilename = GetDescription();
|
|
int bMainFileReal;
|
|
VSIStatBufL sStat;
|
|
|
|
bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
|
|
if (bMainFileReal)
|
|
{
|
|
CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
|
|
CPLString osShortGENFileName = CPLGetFilename(osGENFileName);
|
|
if ( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
|
|
papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
|
|
}
|
|
else
|
|
papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
|
|
|
|
papszFileList = CSLAddString(papszFileList, osIMGFileName.c_str());
|
|
}
|
|
|
|
return papszFileList;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AddSubDataset() */
|
|
/************************************************************************/
|
|
|
|
void ADRGDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName )
|
|
{
|
|
char szName[80];
|
|
int nCount = CSLCount(papszSubDatasets ) / 2;
|
|
|
|
CPLString osSubDatasetName;
|
|
osSubDatasetName = "ADRG:";
|
|
osSubDatasetName += pszGENFileName;
|
|
osSubDatasetName += ",";
|
|
osSubDatasetName += pszIMGFileName;
|
|
|
|
sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
|
|
papszSubDatasets =
|
|
CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
|
|
|
|
sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
|
|
papszSubDatasets =
|
|
CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataDomainList() */
|
|
/************************************************************************/
|
|
|
|
char **ADRGDataset::GetMetadataDomainList()
|
|
{
|
|
return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
|
|
TRUE,
|
|
"SUBDATASETS", NULL);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadata() */
|
|
/************************************************************************/
|
|
|
|
char **ADRGDataset::GetMetadata( const char *pszDomain )
|
|
|
|
{
|
|
if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
|
|
return papszSubDatasets;
|
|
|
|
return GDALPamDataset::GetMetadata( pszDomain );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetProjectionRef() */
|
|
/************************************************************************/
|
|
|
|
const char* ADRGDataset::GetProjectionRef()
|
|
{
|
|
return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGeoTransform() */
|
|
/************************************************************************/
|
|
|
|
CPLErr ADRGDataset::GetGeoTransform( double * padfGeoTransform)
|
|
{
|
|
if (papszSubDatasets != NULL)
|
|
return CE_Failure;
|
|
|
|
memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetGeoTransform() */
|
|
/************************************************************************/
|
|
|
|
CPLErr ADRGDataset::SetGeoTransform( double * padfGeoTransform )
|
|
|
|
{
|
|
memcpy( adfGeoTransform, padfGeoTransform, sizeof(double)*6 );
|
|
bGeoTransformValid = TRUE;
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetLongitudeFromString() */
|
|
/************************************************************************/
|
|
|
|
double ADRGDataset::GetLongitudeFromString(const char* str)
|
|
{
|
|
char ddd[3+1] = { 0 };
|
|
char mm[2+1] = { 0 };
|
|
char ssdotss[5+1] = { 0 };
|
|
int sign = (str[0] == '+') ? 1 : - 1;
|
|
str++;
|
|
strncpy(ddd, str, 3);
|
|
str+=3;
|
|
strncpy(mm, str, 2);
|
|
str+=2;
|
|
strncpy(ssdotss, str, 5);
|
|
return sign * (CPLAtof(ddd) + CPLAtof(mm) / 60 + CPLAtof(ssdotss) / 3600);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetLatitudeFromString() */
|
|
/************************************************************************/
|
|
|
|
double ADRGDataset::GetLatitudeFromString(const char* str)
|
|
{
|
|
char ddd[2+1] = { 0 };
|
|
char mm[2+1] = { 0 };
|
|
char ssdotss[5+1] = { 0 };
|
|
int sign = (str[0] == '+') ? 1 : - 1;
|
|
str++;
|
|
strncpy(ddd, str, 2);
|
|
str+=2;
|
|
strncpy(mm, str, 2);
|
|
str+=2;
|
|
strncpy(ssdotss, str, 5);
|
|
return sign * (CPLAtof(ddd) + CPLAtof(mm) / 60 + CPLAtof(ssdotss) / 3600);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* FindRecordInGENForIMG() */
|
|
/************************************************************************/
|
|
|
|
DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
|
|
const char* pszGENFileName,
|
|
const char* pszIMGFileName)
|
|
{
|
|
/* Finds the GEN file corresponding to the IMG file */
|
|
if (!module.Open(pszGENFileName, TRUE))
|
|
return NULL;
|
|
|
|
|
|
CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
|
|
|
|
DDFField* field;
|
|
DDFFieldDefn *fieldDefn;
|
|
|
|
/* Now finds the record */
|
|
while (TRUE)
|
|
{
|
|
CPLPushErrorHandler( CPLQuietErrorHandler );
|
|
DDFRecord* record = module.ReadRecord();
|
|
CPLPopErrorHandler();
|
|
CPLErrorReset();
|
|
if (record == NULL)
|
|
return NULL;
|
|
|
|
if (record->GetFieldCount() >= 5)
|
|
{
|
|
field = record->GetField(0);
|
|
fieldDefn = field->GetFieldDefn();
|
|
if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 2))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
|
|
if( RTY == NULL )
|
|
continue;
|
|
/* Ignore overviews */
|
|
if ( strcmp(RTY, "OVV") == 0 )
|
|
continue;
|
|
|
|
if ( strcmp(RTY, "GIN") != 0 )
|
|
continue;
|
|
|
|
field = record->GetField(3);
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 15))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
|
|
if( pszBAD == NULL || strlen(pszBAD) != 12 )
|
|
continue;
|
|
CPLString osBAD = pszBAD;
|
|
{
|
|
char* c = (char*) strchr(osBAD.c_str(), ' ');
|
|
if (c)
|
|
*c = 0;
|
|
}
|
|
|
|
if (EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()))
|
|
{
|
|
return record;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OpenDataset() */
|
|
/************************************************************************/
|
|
|
|
ADRGDataset* ADRGDataset::OpenDataset(
|
|
const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
|
|
{
|
|
DDFModule module;
|
|
|
|
int SCA = 0;
|
|
int ZNA = 0;
|
|
double PSP;
|
|
int ARV;
|
|
int BRV;
|
|
double LSO;
|
|
double PSO;
|
|
int NFL;
|
|
int NFC;
|
|
CPLString osBAD;
|
|
int TIF;
|
|
int* TILEINDEX = NULL;
|
|
int i;
|
|
|
|
DDFField* field;
|
|
DDFFieldDefn *fieldDefn;
|
|
DDFSubfieldDefn* subfieldDefn;
|
|
|
|
if (record == NULL)
|
|
{
|
|
record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
|
|
if (record == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
field = record->GetField(1);
|
|
if( field == NULL )
|
|
return NULL;
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 2))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
const char* pszPTR = record->GetStringSubfield("DSI", 0, "PRT", 0);
|
|
if( pszPTR == NULL || !EQUAL(pszPTR, "ADRG") )
|
|
return NULL;
|
|
|
|
const char* pszNAM = record->GetStringSubfield("DSI", 0, "NAM", 0);
|
|
if( pszNAM == NULL || strlen(pszNAM) != 8 )
|
|
return NULL;
|
|
CPLString osNAM = pszNAM;
|
|
|
|
field = record->GetField(2);
|
|
if( field == NULL )
|
|
return NULL;
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
int isGIN = TRUE;
|
|
|
|
if (isGIN)
|
|
{
|
|
if (!(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 21))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if( record->GetIntSubfield("GEN", 0, "STR", 0) != 3 )
|
|
return NULL;
|
|
|
|
SCA = record->GetIntSubfield("GEN", 0, "SCA", 0);
|
|
CPLDebug("ADRG", "SCA=%d", SCA);
|
|
|
|
ZNA = record->GetIntSubfield("GEN", 0, "ZNA", 0);
|
|
CPLDebug("ADRG", "ZNA=%d", ZNA);
|
|
|
|
PSP = record->GetFloatSubfield("GEN", 0, "PSP", 0);
|
|
CPLDebug("ADRG", "PSP=%f", PSP);
|
|
|
|
ARV = record->GetIntSubfield("GEN", 0, "ARV", 0);
|
|
CPLDebug("ADRG", "ARV=%d", ARV);
|
|
|
|
BRV = record->GetIntSubfield("GEN", 0, "BRV", 0);
|
|
CPLDebug("ADRG", "BRV=%d", BRV);
|
|
|
|
const char* pszLSO = record->GetStringSubfield("GEN", 0, "LSO", 0);
|
|
if( pszLSO == NULL || strlen(pszLSO) != 11 )
|
|
return NULL;
|
|
LSO = GetLongitudeFromString(pszLSO);
|
|
CPLDebug("ADRG", "LSO=%f", LSO);
|
|
|
|
const char* pszPSO = record->GetStringSubfield("GEN", 0, "PSO", 0);
|
|
if( pszPSO == NULL || strlen(pszPSO) != 10 )
|
|
return NULL;
|
|
PSO = GetLatitudeFromString(pszPSO);
|
|
CPLDebug("ADRG", "PSO=%f", PSO);
|
|
}
|
|
else
|
|
{
|
|
if (!(strcmp(fieldDefn->GetName(), "OVI") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 5))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if( record->GetIntSubfield("OVI", 0, "STR", 0) != 3 )
|
|
return NULL;
|
|
|
|
ARV = record->GetIntSubfield("OVI", 0, "ARV", 0);
|
|
CPLDebug("ADRG", "ARV=%d", ARV);
|
|
|
|
BRV = record->GetIntSubfield("OVI", 0, "BRV", 0);
|
|
CPLDebug("ADRG", "BRV=%d", BRV);
|
|
|
|
const char* pszLSO = record->GetStringSubfield("OVI", 0, "LSO", 0);
|
|
if( pszLSO == NULL || strlen(pszLSO) != 11 )
|
|
return NULL;
|
|
LSO = GetLongitudeFromString(pszLSO);
|
|
CPLDebug("ADRG", "LSO=%f", LSO);
|
|
|
|
const char* pszPSO = record->GetStringSubfield("OVI", 0, "PSO", 0);
|
|
if( pszPSO == NULL || strlen(pszPSO) != 10 )
|
|
return NULL;
|
|
PSO = GetLatitudeFromString(pszPSO);
|
|
CPLDebug("ADRG", "PSO=%f", PSO);
|
|
}
|
|
|
|
field = record->GetField(3);
|
|
if( field == NULL )
|
|
return NULL;
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 15))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
NFL = record->GetIntSubfield("SPR", 0, "NFL", 0);
|
|
CPLDebug("ADRG", "NFL=%d", NFL);
|
|
|
|
NFC = record->GetIntSubfield("SPR", 0, "NFC", 0);
|
|
CPLDebug("ADRG", "NFC=%d", NFC);
|
|
|
|
int PNC = record->GetIntSubfield("SPR", 0, "PNC", 0);
|
|
CPLDebug("ADRG", "PNC=%d", PNC);
|
|
if (PNC != 128)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int PNL = record->GetIntSubfield("SPR", 0, "PNL", 0);
|
|
CPLDebug("ADRG", "PNL=%d", PNL);
|
|
if (PNL != 128)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
|
|
if( pszBAD == NULL || strlen(pszBAD) != 12 )
|
|
return NULL;
|
|
osBAD = pszBAD;
|
|
{
|
|
char* c = (char*) strchr(osBAD.c_str(), ' ');
|
|
if (c)
|
|
*c = 0;
|
|
}
|
|
CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
|
|
|
|
subfieldDefn = fieldDefn->GetSubfield(14);
|
|
if (!(strcmp(subfieldDefn->GetName(), "TIF") == 0 &&
|
|
(subfieldDefn->GetFormat())[0] == 'A'))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
const char* pszTIF = record->GetStringSubfield("SPR", 0, "TIF", 0);
|
|
if( pszTIF == NULL)
|
|
return NULL;
|
|
TIF = pszTIF[0] == 'Y';
|
|
CPLDebug("ADRG", "TIF=%d", TIF);
|
|
|
|
if (TIF)
|
|
{
|
|
if (record->GetFieldCount() != 6)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
field = record->GetField(5);
|
|
if( field == NULL )
|
|
return NULL;
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
if (!(strcmp(fieldDefn->GetName(), "TIM") == 0))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (field->GetDataSize() != 5 * NFL * NFC + 1)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
TILEINDEX = new int [NFL * NFC];
|
|
const char* ptr = field->GetData();
|
|
char offset[5+1]={0};
|
|
for(i=0;i<NFL*NFC;i++)
|
|
{
|
|
strncpy(offset, ptr, 5);
|
|
ptr += 5;
|
|
TILEINDEX[i] = atoi(offset);
|
|
//CPLDebug("ADRG", "TSI[%d]=%d", i, TILEINDEX[i]);
|
|
}
|
|
}
|
|
|
|
VSILFILE* fdIMG = VSIFOpenL(pszIMGFileName, "rb");
|
|
if (fdIMG == NULL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s\n", pszIMGFileName);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
|
|
if (ZNA == 9 || ZNA == 18)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by ADRG driver");
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
|
|
/* Skip ISO8211 header of IMG file */
|
|
int offsetInIMG = 0;
|
|
char c;
|
|
char recordName[3];
|
|
if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
while (!VSIFEofL(fdIMG))
|
|
{
|
|
if (c == 30)
|
|
{
|
|
if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
offsetInIMG += 3;
|
|
if (strncmp(recordName,"IMG",3) == 0)
|
|
{
|
|
offsetInIMG += 4;
|
|
if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0 ||
|
|
VSIFReadL(&c, 1, 1, fdIMG) != 1)
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
while(c ==' ')
|
|
{
|
|
offsetInIMG ++;
|
|
if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
}
|
|
offsetInIMG ++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
offsetInIMG ++;
|
|
if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (VSIFEofL(fdIMG))
|
|
{
|
|
VSIFCloseL(fdIMG);
|
|
delete[] TILEINDEX;
|
|
return NULL;
|
|
}
|
|
|
|
CPLDebug("ADRG", "Img offset data = %d", offsetInIMG);
|
|
|
|
ADRGDataset* poDS = new ADRGDataset();
|
|
|
|
poDS->osGENFileName = pszGENFileName;
|
|
poDS->osIMGFileName = pszIMGFileName;
|
|
poDS->NFC = NFC;
|
|
poDS->NFL = NFL;
|
|
poDS->nRasterXSize = NFC * 128;
|
|
poDS->nRasterYSize = NFL * 128;
|
|
poDS->LSO = LSO;
|
|
poDS->PSO = PSO;
|
|
poDS->ARV = ARV;
|
|
poDS->BRV = BRV;
|
|
poDS->TILEINDEX = TILEINDEX;
|
|
poDS->fdIMG = fdIMG;
|
|
poDS->offsetInIMG = offsetInIMG;
|
|
poDS->poOverviewDS = NULL;
|
|
|
|
poDS->adfGeoTransform[0] = LSO;
|
|
poDS->adfGeoTransform[1] = 360. / ARV;
|
|
poDS->adfGeoTransform[2] = 0.0;
|
|
poDS->adfGeoTransform[3] = PSO;
|
|
poDS->adfGeoTransform[4] = 0.0;
|
|
poDS->adfGeoTransform[5] = - 360. / BRV;
|
|
|
|
if (isGIN)
|
|
{
|
|
char pszValue[32];
|
|
sprintf(pszValue, "%d", SCA);
|
|
poDS->SetMetadataItem( "ADRG_SCA", pszValue );
|
|
}
|
|
|
|
poDS->SetMetadataItem( "ADRG_NAM", osNAM.c_str() );
|
|
|
|
poDS->nBands = 3;
|
|
for( i = 0; i < poDS->nBands; i++ )
|
|
poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
|
|
|
|
return poDS;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGENListFromTHF() */
|
|
/************************************************************************/
|
|
|
|
char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
|
|
{
|
|
DDFModule module;
|
|
DDFRecord * record;
|
|
DDFField* field;
|
|
DDFFieldDefn *fieldDefn;
|
|
int i;
|
|
int nFilenames = 0;
|
|
char** papszFileNames = NULL;
|
|
|
|
if (!module.Open(pszFileName, TRUE))
|
|
return papszFileNames;
|
|
|
|
while (TRUE)
|
|
{
|
|
CPLPushErrorHandler( CPLQuietErrorHandler );
|
|
record = module.ReadRecord();
|
|
CPLPopErrorHandler();
|
|
CPLErrorReset();
|
|
if (record == NULL)
|
|
break;
|
|
|
|
if (record->GetFieldCount() >= 2)
|
|
{
|
|
field = record->GetField(0);
|
|
fieldDefn = field->GetFieldDefn();
|
|
if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 2))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
|
|
if ( RTY == NULL || !( strcmp(RTY, "TFN") == 0 ))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int iVFFFieldInstance = 0;
|
|
for (i = 1; i < record->GetFieldCount() ; i++)
|
|
{
|
|
field = record->GetField(i);
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
if (!(strcmp(fieldDefn->GetName(), "VFF") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 1))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const char* pszVFF = record->GetStringSubfield("VFF", iVFFFieldInstance++, "VFF", 0);
|
|
if( pszVFF == NULL )
|
|
continue;
|
|
CPLString osSubFileName(pszVFF);
|
|
char* c = (char*) strchr(osSubFileName.c_str(), ' ');
|
|
if (c)
|
|
*c = 0;
|
|
if (EQUAL(CPLGetExtension(osSubFileName.c_str()), "GEN"))
|
|
{
|
|
CPLDebug("ADRG", "Found GEN file in THF : %s", osSubFileName.c_str());
|
|
CPLString osGENFileName(CPLGetDirname(pszFileName));
|
|
char** tokens = CSLTokenizeString2( osSubFileName.c_str(), "/\"", 0);
|
|
char** ptr = tokens;
|
|
if (ptr == NULL)
|
|
continue;
|
|
while(*ptr)
|
|
{
|
|
char** papszDirContent = VSIReadDir(osGENFileName.c_str());
|
|
char** ptrDir = papszDirContent;
|
|
if (ptrDir)
|
|
{
|
|
while(*ptrDir)
|
|
{
|
|
if (EQUAL(*ptrDir, *ptr))
|
|
{
|
|
osGENFileName = CPLFormFilename(osGENFileName.c_str(), *ptrDir, NULL);
|
|
CPLDebug("ADRG", "Building GEN full file name : %s", osGENFileName.c_str());
|
|
break;
|
|
}
|
|
ptrDir ++;
|
|
}
|
|
}
|
|
if (ptrDir == NULL)
|
|
break;
|
|
CSLDestroy(papszDirContent);
|
|
ptr++;
|
|
}
|
|
int isNameValid = *ptr == NULL;
|
|
CSLDestroy(tokens);
|
|
if (isNameValid)
|
|
{
|
|
papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
|
|
papszFileNames[nFilenames] = CPLStrdup(osGENFileName.c_str());
|
|
papszFileNames[nFilenames + 1] = NULL;
|
|
nFilenames ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return papszFileNames;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetIMGListFromGEN() */
|
|
/************************************************************************/
|
|
|
|
char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
|
|
int *pnRecordIndex)
|
|
{
|
|
DDFRecord * record;
|
|
DDFField* field;
|
|
DDFFieldDefn *fieldDefn;
|
|
int nFilenames = 0;
|
|
char** papszFileNames = NULL;
|
|
int nRecordIndex = -1;
|
|
|
|
if (pnRecordIndex)
|
|
*pnRecordIndex = -1;
|
|
|
|
DDFModule module;
|
|
if (!module.Open(pszFileName, TRUE))
|
|
return NULL;
|
|
|
|
while (TRUE)
|
|
{
|
|
nRecordIndex ++;
|
|
|
|
CPLPushErrorHandler( CPLQuietErrorHandler );
|
|
record = module.ReadRecord();
|
|
CPLPopErrorHandler();
|
|
CPLErrorReset();
|
|
if (record == NULL)
|
|
break;
|
|
|
|
if (record->GetFieldCount() >= 5)
|
|
{
|
|
field = record->GetField(0);
|
|
fieldDefn = field->GetFieldDefn();
|
|
if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 2))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
|
|
if( RTY == NULL )
|
|
continue;
|
|
/* Ignore overviews */
|
|
if ( strcmp(RTY, "OVV") == 0 )
|
|
continue;
|
|
|
|
if ( strcmp(RTY, "GIN") != 0 )
|
|
continue;
|
|
|
|
field = record->GetField(3);
|
|
if( field == NULL )
|
|
continue;
|
|
fieldDefn = field->GetFieldDefn();
|
|
|
|
if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
|
|
fieldDefn->GetSubfieldCount() == 15))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
|
|
if( pszBAD == NULL || strlen(pszBAD) != 12 )
|
|
continue;
|
|
CPLString osBAD = pszBAD;
|
|
{
|
|
char* c = (char*) strchr(osBAD.c_str(), ' ');
|
|
if (c)
|
|
*c = 0;
|
|
}
|
|
CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
|
|
|
|
/* Build full IMG file name from BAD value */
|
|
CPLString osGENDir(CPLGetDirname(pszFileName));
|
|
|
|
CPLString osFileName = CPLFormFilename(osGENDir.c_str(), osBAD.c_str(), NULL);
|
|
VSIStatBufL sStatBuf;
|
|
if( VSIStatL( osFileName, &sStatBuf ) == 0 )
|
|
{
|
|
osBAD = osFileName;
|
|
CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
|
|
}
|
|
else
|
|
{
|
|
char** papszDirContent;
|
|
if (strcmp(osGENDir.c_str(), "/vsimem") == 0)
|
|
{
|
|
CPLString osTmp = osGENDir + "/";
|
|
papszDirContent = VSIReadDir(osTmp);
|
|
}
|
|
else
|
|
papszDirContent = VSIReadDir(osGENDir);
|
|
char** ptrDir = papszDirContent;
|
|
while(ptrDir && *ptrDir)
|
|
{
|
|
if (EQUAL(*ptrDir, osBAD.c_str()))
|
|
{
|
|
osBAD = CPLFormFilename(osGENDir.c_str(), *ptrDir, NULL);
|
|
CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
|
|
break;
|
|
}
|
|
ptrDir ++;
|
|
}
|
|
CSLDestroy(papszDirContent);
|
|
}
|
|
|
|
if (nFilenames == 0 && pnRecordIndex)
|
|
*pnRecordIndex = nRecordIndex;
|
|
|
|
papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
|
|
papszFileNames[nFilenames] = CPLStrdup(osBAD.c_str());
|
|
papszFileNames[nFilenames + 1] = NULL;
|
|
nFilenames ++;
|
|
}
|
|
}
|
|
|
|
return papszFileNames;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Open() */
|
|
/************************************************************************/
|
|
|
|
GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
|
|
{
|
|
int nRecordIndex = -1;
|
|
CPLString osGENFileName;
|
|
CPLString osIMGFileName;
|
|
int bFromSubdataset = FALSE;
|
|
|
|
if( EQUALN(poOpenInfo->pszFilename, "ADRG:", 5) )
|
|
{
|
|
char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 5, ",", 0);
|
|
if (CSLCount(papszTokens) == 2)
|
|
{
|
|
osGENFileName = papszTokens[0];
|
|
osIMGFileName = papszTokens[1];
|
|
bFromSubdataset = TRUE;
|
|
}
|
|
CSLDestroy(papszTokens);
|
|
}
|
|
else
|
|
{
|
|
if( poOpenInfo->nHeaderBytes < 500 )
|
|
return NULL;
|
|
|
|
CPLString osFileName(poOpenInfo->pszFilename);
|
|
if (EQUAL(CPLGetExtension(osFileName.c_str()), "THF"))
|
|
{
|
|
char** papszFileNames = GetGENListFromTHF(osFileName.c_str());
|
|
if (papszFileNames == NULL)
|
|
return NULL;
|
|
if (papszFileNames[1] == NULL)
|
|
{
|
|
osFileName = papszFileNames[0];
|
|
CSLDestroy(papszFileNames);
|
|
}
|
|
else
|
|
{
|
|
char** ptr = papszFileNames;
|
|
ADRGDataset* poDS = new ADRGDataset();
|
|
while(*ptr)
|
|
{
|
|
char** papszIMGFileNames = GetIMGListFromGEN(*ptr);
|
|
char** papszIMGIter = papszIMGFileNames;
|
|
while(papszIMGIter && *papszIMGIter)
|
|
{
|
|
poDS->AddSubDataset(*ptr, *papszIMGIter);
|
|
papszIMGIter ++;
|
|
}
|
|
CSLDestroy(papszIMGFileNames);
|
|
|
|
ptr ++;
|
|
}
|
|
CSLDestroy(papszFileNames);
|
|
return poDS;
|
|
}
|
|
}
|
|
|
|
if (EQUAL(CPLGetExtension(osFileName.c_str()), "GEN"))
|
|
{
|
|
osGENFileName = osFileName;
|
|
|
|
char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
|
|
if (papszFileNames == NULL)
|
|
return NULL;
|
|
if (papszFileNames[1] == NULL)
|
|
{
|
|
osIMGFileName = papszFileNames[0];
|
|
CSLDestroy(papszFileNames);
|
|
}
|
|
else
|
|
{
|
|
char** ptr = papszFileNames;
|
|
ADRGDataset* poDS = new ADRGDataset();
|
|
while(*ptr)
|
|
{
|
|
poDS->AddSubDataset(osFileName.c_str(), *ptr);
|
|
ptr ++;
|
|
}
|
|
CSLDestroy(papszFileNames);
|
|
return poDS;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (osGENFileName.size() > 0 &&
|
|
osIMGFileName.size() > 0)
|
|
{
|
|
if( poOpenInfo->eAccess == GA_Update )
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"The ADRG driver does not support update access to existing"
|
|
" datasets.\n" );
|
|
return NULL;
|
|
}
|
|
|
|
DDFModule module;
|
|
DDFRecord* record = NULL;
|
|
if (nRecordIndex >= 0 &&
|
|
module.Open(osGENFileName.c_str(), TRUE))
|
|
{
|
|
int i;
|
|
for(i=0;i<=nRecordIndex;i++)
|
|
{
|
|
CPLPushErrorHandler( CPLQuietErrorHandler );
|
|
record = module.ReadRecord();
|
|
CPLPopErrorHandler();
|
|
CPLErrorReset();
|
|
if (record == NULL)
|
|
break;
|
|
}
|
|
}
|
|
|
|
ADRGDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
|
|
|
|
if (poDS)
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize any PAM information. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->SetDescription( poOpenInfo->pszFilename );
|
|
poDS->TryLoadXML();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for external overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( bFromSubdataset )
|
|
poDS->oOvManager.Initialize( poDS, osIMGFileName.c_str() );
|
|
else
|
|
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
|
|
|
|
return poDS;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Create() */
|
|
/************************************************************************/
|
|
|
|
GDALDataset *ADRGDataset::Create(const char* pszFilename,
|
|
int nXSize,
|
|
int nYSize,
|
|
int nBands,
|
|
GDALDataType eType,
|
|
CPL_UNUSED char **papszOptions)
|
|
{
|
|
int i;
|
|
|
|
if( eType != GDT_Byte)
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Attempt to create ADRG dataset with an illegal\n"
|
|
"data type (%s), only Byte supported by the format.\n",
|
|
GDALGetDataTypeName(eType) );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if( nBands != 3 )
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"ADRG driver doesn't support %d bands. Must be 3 (rgb) bands.\n",
|
|
nBands );
|
|
return NULL;
|
|
}
|
|
|
|
if(nXSize < 1 || nYSize < 1)
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"Specified pixel dimensions (% d x %d) are bad.\n",
|
|
nXSize, nYSize );
|
|
}
|
|
|
|
if (!EQUAL(CPLGetExtension(pszFilename), "gen"))
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"Invalid filename. Must be ABCDEF01.GEN\n");
|
|
return NULL;
|
|
}
|
|
|
|
CPLString osBaseFileName(CPLGetBasename(pszFilename));
|
|
if (strlen(osBaseFileName) != 8 || osBaseFileName[6] != '0' || osBaseFileName[7] != '1')
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
|
|
return NULL;
|
|
}
|
|
|
|
for(i=0;i<6;i++)
|
|
{
|
|
if (!(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z'))
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
VSILFILE* fdGEN = VSIFOpenL(pszFilename, "wb");
|
|
if (fdGEN == NULL)
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Cannot create GEN file : %s.\n", pszFilename);
|
|
return NULL;
|
|
}
|
|
|
|
CPLString osDirname(CPLGetDirname(pszFilename));
|
|
CPLString osTransh01THF(CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
|
|
VSILFILE* fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb");
|
|
if (fdTHF == NULL)
|
|
{
|
|
VSIFCloseL(fdGEN);
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Cannot create THF file : %s.\n", osTransh01THF.c_str());
|
|
return NULL;
|
|
}
|
|
|
|
CPLString osImgFilename = CPLResetExtension(pszFilename, "IMG");
|
|
VSILFILE* fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b");
|
|
if (fdIMG == NULL)
|
|
{
|
|
VSIFCloseL(fdGEN);
|
|
VSIFCloseL(fdTHF);
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Cannot create image file : %s.\n", osImgFilename.c_str());
|
|
return NULL;
|
|
}
|
|
|
|
ADRGDataset* poDS = new ADRGDataset();
|
|
|
|
poDS->eAccess = GA_Update;
|
|
|
|
poDS->fdGEN = fdGEN;
|
|
poDS->fdIMG = fdIMG;
|
|
poDS->fdTHF = fdTHF;
|
|
|
|
poDS->osBaseFileName = osBaseFileName;
|
|
poDS->bCreation = TRUE;
|
|
poDS->nNextAvailableBlock = 1;
|
|
poDS->NFC = (nXSize + 127) / 128;
|
|
poDS->NFL = (nYSize + 127) / 128;
|
|
poDS->nRasterXSize = nXSize;
|
|
poDS->nRasterYSize = nYSize;
|
|
poDS->bGeoTransformValid = FALSE;
|
|
poDS->TILEINDEX = new int [poDS->NFC*poDS->NFL];
|
|
memset(poDS->TILEINDEX, 0, sizeof(int)*poDS->NFC*poDS->NFL);
|
|
poDS->offsetInIMG = 2048;
|
|
poDS->poOverviewDS = NULL;
|
|
|
|
poDS->nBands = 3;
|
|
for( i = 0; i < poDS->nBands; i++ )
|
|
poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
|
|
|
|
return poDS;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* WriteGENFile_Header() */
|
|
/************************************************************************/
|
|
|
|
static void WriteGENFile_Header(VSILFILE* fd)
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
|
|
const char* nameOfFields[] = { "000", "001", "DRF", "DSI", "OVI", "GEN", "SPR", "BDF", "TIM" };
|
|
int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GENERAL_INFORMATION_FILE", "", ""); /* 000 */
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
|
|
"RTY!RID",
|
|
"(A(3),A(2))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '1', "DATA_SET_DESCRIPTION_FIELD", /* DRF */
|
|
"NSH!NSV!NOZ!NOS",
|
|
"(4I(2))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "DATA_SET-ID_FIELD", /* DSI */
|
|
"PRT!NAM",
|
|
"(A(4),A(8))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "OVERVIEW_INFORMATION_FIELD", /* OVI */
|
|
"STR!ARV!BRV!LSO!PSO",
|
|
"(I(1),I(8),I(8),A(11),A(10))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "GENERAL_INFORMATION_FIELD", /* GEN */
|
|
"STR!LOD!LAD!UNIloa!SWO!SWA!NWO!NWA!NEO!NEA!SEO!SEA!SCA!ZNA!PSP!IMR!ARV!BRV!LSO!PSO!TXT",
|
|
"(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))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
|
|
"NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
|
|
"(4I(6),2I(3),2I(6),5I(1),A(12),A(1))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
|
|
"*BID!WS1!WS2",
|
|
"(A(5),I(5),I(5))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '1', "TILE_INDEX_MAP_FIELD", /* TIM */
|
|
"*TSI",
|
|
"(I(5))");
|
|
|
|
FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* WriteGENFile_DataSetDescriptionRecord() */
|
|
/************************************************************************/
|
|
|
|
/* Write DATA_SET_DESCRIPTION_RECORD */
|
|
static void WriteGENFile_DataSetDescriptionRecord(VSILFILE* fd)
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0};
|
|
const char* nameOfFields[] = { "001", "DRF" };
|
|
int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "DSS", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field DRF */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSH */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSV */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOZ */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOS */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* WriteGENFile_OverviewRecord() */
|
|
/************************************************************************/
|
|
|
|
/* Write OVERVIEW_RECORD */
|
|
static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName, int ARV, int BRV, double LSO, double PSO,
|
|
int nOvSizeX, int nOvSizeY, int NFL, int NFC, int* TILEINDEX)
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
|
|
const char* nameOfFields[] = { "001", "DSI", "OVI", "SPR", "BDF", "TIM" };
|
|
int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field DSI */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field OVI */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field SPR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX-1, 6); /* NUS */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeY-1, 6); /* NLL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
|
|
char tmp[12+1];
|
|
sprintf(tmp, "%s.IMG", osBaseFileName.c_str()); /* FIXME */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 12); /* BAD */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field BDF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field TIM */
|
|
int i;
|
|
for(i=0;i<NFL*NFC;i++)
|
|
{
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
|
|
}
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* WriteGENFile_GeneralInformationRecord() */
|
|
/************************************************************************/
|
|
|
|
/* Write GENERAL_INFORMATION_RECORD */
|
|
static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM, CPLString& osBAD,
|
|
int ARV, int BRV, double LSO, double PSO,
|
|
double* adfGeoTransform, int SCA,
|
|
int nRasterXSize, int nRasterYSize,
|
|
int NFL, int NFC, int* TILEINDEX)
|
|
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
|
|
const char* nameOfFields[] = { "001", "DSI", "GEN", "SPR", "BDF", "TIM" };
|
|
int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "GIN", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field DSI */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field `GEN */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LOD */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LAD */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3); /* UNIloa */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* NWO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NWA */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, SCA, 9); /* SCA */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* ZNA */ /* FIXME */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "100.0", 5); /* PSP */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* IMR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 64); /* TXT */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field SPR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterXSize-1, 6); /* NUS */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterYSize-1, 6); /* NLL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, osBAD.c_str(), 12); /* BAD */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field BDF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field TIM */
|
|
int i;
|
|
for(i=0;i<NFL*NFC;i++)
|
|
{
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
|
|
}
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* WriteGENFile() */
|
|
/************************************************************************/
|
|
|
|
void ADRGDataset::WriteGENFile()
|
|
{
|
|
if (!bGeoTransformValid)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "No geo transform available !");
|
|
adfGeoTransform[0] = 0;
|
|
adfGeoTransform[3] = 0;
|
|
adfGeoTransform[1] = 1;
|
|
adfGeoTransform[5] = 1;
|
|
}
|
|
|
|
LSO = adfGeoTransform[0];
|
|
PSO = adfGeoTransform[3];
|
|
ARV = (int)floor(360. / adfGeoTransform[1] + .5);
|
|
BRV = (int)floor(-360. / adfGeoTransform[5] + .5);
|
|
|
|
/*ARV = ((ARV + 255) / 512) * 512;
|
|
BRV = ((BRV + 255) / 512) * 512;*/
|
|
|
|
int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
|
|
|
|
int nOvSizeX = nRasterXSize; // FIXME
|
|
int nOvSizeY = nRasterYSize; // FIXME
|
|
|
|
/* Write header */
|
|
WriteGENFile_Header(fdGEN);
|
|
|
|
/* Write DATA_SET_DESCRIPTION_RECORD */
|
|
WriteGENFile_DataSetDescriptionRecord(fdGEN);
|
|
|
|
/* Write OVERVIEW_RECORD */
|
|
WriteGENFile_OverviewRecord(fdGEN, osBaseFileName, ARV, BRV, LSO, PSO,
|
|
nOvSizeX, nOvSizeY, NFL, NFC, TILEINDEX);
|
|
|
|
/* Write GENERAL_INFORMATION_RECORD */
|
|
CPLString osNAM = osBaseFileName;
|
|
char tmp[12+1];
|
|
sprintf(tmp, "%s.IMG", osNAM.c_str());
|
|
CPLString osBAD = tmp;
|
|
WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
|
|
adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
|
|
|
|
if (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")))
|
|
{
|
|
strncpy(tmp, osBaseFileName.c_str(), 6);
|
|
tmp[6] = '\0';
|
|
strcat(tmp, "02");
|
|
osNAM = tmp;
|
|
sprintf(tmp, "%s.IMG", osNAM.c_str());
|
|
osBAD = tmp;
|
|
WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
|
|
adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* WriteTHFFile() */
|
|
/************************************************************************/
|
|
|
|
void ADRGDataset::WriteTHFFile()
|
|
{
|
|
VSILFILE* fd = fdTHF;
|
|
|
|
/* Write header */
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
const char* nameOfFields[] = { "000", "001", "VDR", "FDR", "QSR", "QUV", "CPS", "CPT", "SPR", "BDF", "VFF"};
|
|
int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "TRANSMITTAL_HEADER_FILE", "", ""); /* 000 */
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
|
|
"RTY!RID",
|
|
"(A(3),A(2))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TRANSMITTAL_HEADER_FIELD", /* VDR */
|
|
"MSD!VOO!ADR!NOV!SQN!NOF!URF!EDN!DAT",
|
|
"(A(1),A(200),A(1),I(1),I(1),I(3),A(16),I(3),A(12))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_DESCRIPTION_FIELD", /* FDR */
|
|
"NAM!STR!PRT!SWO!SWA!NEO!NEA",
|
|
"(A(8),I(1),A(4),A(11),A(10),A(11),A(10))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "SECURITY_AND_RELEASE_FIELD", /* QSR */
|
|
"QSS!QOD!DAT!QLE",
|
|
"(A(1),A(1),A(12),A(200))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "VOLUME_UP_TO_DATENESS_FIELD", /* QUV */
|
|
"SRC!DAT!SPA",
|
|
"(A(100),A(12),A(20))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_IDENTIFIER_FIELD", /* CPS */
|
|
"PNM!DWV!REF!PUR!PIR!PIG!PIB",
|
|
"(A(7),I(6),R(5),R(5),I(3),I(3),I(3))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_INFORMATION_FIELD", /* CPT */
|
|
"STR!SCR",
|
|
"(I(1),A(100))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
|
|
"NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
|
|
"(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))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
|
|
"*BID!WS1!WS2",
|
|
"(A(5),I(5),I(5))");
|
|
sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD", /* VFF */
|
|
"VFF",
|
|
"(A(51))");
|
|
|
|
FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/* Write TRANSMITTAL_DESCRIPTION_RECORD */
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0};
|
|
const char* nameOfFields[] = { "001", "VDR", "FDR" };
|
|
int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "VTH", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field VDR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* MSD */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* VOO */ /* Title and address of originator */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* ADR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* NOV */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* SQN */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* NOF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16); /* URF */ /* DMA stock number for this CDROM */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* EDN */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "017,19940101", 12); /* DAT */ /* Publication date */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field FDR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
|
|
sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
|
|
sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/* Write SECURITY_AND_UPDATE_RECORD */
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0};
|
|
const char* nameOfFields[] = { "001", "QSR", "QUV" };
|
|
int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "LCF", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field VDR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "U", 1); /* QSS */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* QOD */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 12); /* DAT */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* QLE */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field FDR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)", 100); /* SRC */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/* Write TEST_PATCH_DATA_RECORD */
|
|
{
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0, 0, 0};
|
|
const char* nameOfFields[] = { "001", "CPS", "CPT", "SPR", "BDF" };
|
|
int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "TPA", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field CPS */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Black", 7); /* PNM */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 6); /* DMV */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* REF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* PUR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIG */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIB */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field CPT */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 100); /* SCR */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
int nPatchXSize = 512;
|
|
int nPatchYSize = 512;
|
|
|
|
/* Field SPR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchXSize-1, 6); /* NUS */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchYSize-1, 6); /* NLL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12); /* BAD */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* TIF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field BDF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
|
|
sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
|
|
}
|
|
|
|
/* Write TRANSMITTAL_FILENAMES_RECORD */
|
|
{
|
|
char tmp[12+1];
|
|
|
|
int nFields = 0;
|
|
int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0};
|
|
|
|
/* Debug option to simulate ADRG datasets made of several images */
|
|
int nTotalFields = (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
|
|
|
|
const char* nameOfFields[] = { "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
|
|
int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
|
|
|
|
/* Field 001 */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "TFN", 3); /* RTY */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field VFF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51); /* VFF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field VFF */
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51); /* VFF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field VFF */
|
|
sprintf(tmp, "%s.GEN", osBaseFileName.c_str());
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
/* Field VFF */
|
|
sprintf(tmp, "%s.IMG", osBaseFileName.c_str());
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
|
|
if (nTotalFields == 6)
|
|
{
|
|
/* Field VFF */
|
|
strncpy(tmp, osBaseFileName.c_str(), 6);
|
|
tmp[6] = '\0';
|
|
strcat(tmp, "02.IMG");
|
|
sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
|
|
sizeOfFields[nFields] += WriteFieldTerminator(fd);
|
|
nFields++;
|
|
}
|
|
|
|
FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, nameOfFields);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRegister_ADRG() */
|
|
/************************************************************************/
|
|
|
|
void GDALRegister_ADRG()
|
|
|
|
{
|
|
GDALDriver *poDriver;
|
|
|
|
if( GDALGetDriverByName( "ADRG" ) == NULL )
|
|
{
|
|
poDriver = new GDALDriver();
|
|
|
|
poDriver->SetDescription( "ADRG" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
|
"ARC Digitized Raster Graphics" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
|
"frmt_various.html#ADRG" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
|
|
"Byte" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
|
|
|
poDriver->pfnOpen = ADRGDataset::Open;
|
|
poDriver->pfnCreate = ADRGDataset::Create;
|
|
|
|
GetGDALDriverManager()->RegisterDriver( poDriver );
|
|
}
|
|
}
|