GDAL
Sample Driver: jdemdataset.cpp
/******************************************************************************
*
* Project: JDEM Reader
* Purpose: All code for Japanese DEM Reader
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
* Copyright (c) 2009-2012, 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 "cpl_port.h"
#include "gdal_frmts.h"
#include "gdal_pam.h"
#include <algorithm>
CPL_CVSID("$Id: jdemdataset.cpp 8e5eeb35bf76390e3134a4ea7076dab7d478ea0e 2018-11-14 22:55:13 +0100 Even Rouault $")
/************************************************************************/
/* JDEMGetField() */
/************************************************************************/
static int JDEMGetField( const char *pszField, int nWidth )
{
char szWork[32] = {};
CPLAssert(nWidth < static_cast<int>(sizeof(szWork)));
strncpy(szWork, pszField, nWidth);
szWork[nWidth] = '\0';
return atoi(szWork);
}
/************************************************************************/
/* JDEMGetAngle() */
/************************************************************************/
static double JDEMGetAngle( const char *pszField )
{
const int nAngle = JDEMGetField(pszField, 7);
// Note, this isn't very general purpose, but it would appear
// from the field widths that angles are never negative. Nice
// to be a country in the "first quadrant".
const int nDegree = nAngle / 10000;
const int nMin = (nAngle / 100) % 100;
const int nSec = nAngle % 100;
return nDegree + nMin / 60.0 + nSec / 3600.0;
}
/************************************************************************/
/* ==================================================================== */
/* JDEMDataset */
/* ==================================================================== */
/************************************************************************/
class JDEMRasterBand;
class JDEMDataset : public GDALPamDataset
{
friend class JDEMRasterBand;
VSILFILE *fp;
GByte abyHeader[1012];
public:
JDEMDataset();
~JDEMDataset();
static int Identify( GDALOpenInfo * );
CPLErr GetGeoTransform( double * padfTransform ) override;
const char *_GetProjectionRef() override;
const OGRSpatialReference* GetSpatialRef() const override {
return GetSpatialRefFromOldGetProjectionRef();
}
};
/************************************************************************/
/* ==================================================================== */
/* JDEMRasterBand */
/* ==================================================================== */
/************************************************************************/
class JDEMRasterBand : public GDALPamRasterBand
{
friend class JDEMDataset;
int nRecordSize;
char *pszRecord;
bool bBufferAllocFailed;
public:
JDEMRasterBand( JDEMDataset *, int );
virtual ~JDEMRasterBand();
virtual CPLErr IReadBlock( int, int, void * ) override;
};
/************************************************************************/
/* JDEMRasterBand() */
/************************************************************************/
JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDSIn, int nBandIn ) :
// Cannot overflow as nBlockXSize <= 999.
nRecordSize(poDSIn->GetRasterXSize() * 5 + 9 + 2),
pszRecord(nullptr),
bBufferAllocFailed(false)
{
poDS = poDSIn;
nBand = nBandIn;
eDataType = GDT_Float32;
nBlockXSize = poDS->GetRasterXSize();
nBlockYSize = 1;
}
/************************************************************************/
/* ~JDEMRasterBand() */
/************************************************************************/
JDEMRasterBand::~JDEMRasterBand() { VSIFree(pszRecord); }
/************************************************************************/
/* IReadBlock() */
/************************************************************************/
CPLErr JDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
int nBlockYOff,
void * pImage )
{
JDEMDataset *poGDS = static_cast<JDEMDataset *>(poDS);
if (pszRecord == nullptr)
{
if (bBufferAllocFailed)
return CE_Failure;
pszRecord = static_cast<char *>(VSI_MALLOC_VERBOSE(nRecordSize));
if (pszRecord == nullptr)
{
bBufferAllocFailed = true;
return CE_Failure;
}
}
CPL_IGNORE_RET_VAL(
VSIFSeekL(poGDS->fp, 1011 + nRecordSize * nBlockYOff, SEEK_SET));
CPL_IGNORE_RET_VAL(VSIFReadL(pszRecord, 1, nRecordSize, poGDS->fp));
if( !EQUALN(reinterpret_cast<char *>(poGDS->abyHeader), pszRecord, 6) )
{
"JDEM Scanline corrupt. Perhaps file was not transferred "
"in binary mode?");
return CE_Failure;
}
if( JDEMGetField(pszRecord + 6, 3) != nBlockYOff + 1 )
{
"JDEM scanline out of order, JDEM driver does not "
"currently support partial datasets.");
return CE_Failure;
}
for( int i = 0; i < nBlockXSize; i++ )
static_cast<float *>(pImage)[i] =
JDEMGetField(pszRecord + 9 + 5 * i, 5) * 0.1f;
return CE_None;
}
/************************************************************************/
/* ==================================================================== */
/* JDEMDataset */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* JDEMDataset() */
/************************************************************************/
JDEMDataset::JDEMDataset() :
fp(nullptr)
{
std::fill_n(abyHeader, CPL_ARRAYSIZE(abyHeader), static_cast<GByte>(0));
}
/************************************************************************/
/* ~JDEMDataset() */
/************************************************************************/
JDEMDataset::~JDEMDataset()
{
FlushCache();
if( fp != nullptr )
CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
}
/************************************************************************/
/* GetGeoTransform() */
/************************************************************************/
CPLErr JDEMDataset::GetGeoTransform( double *padfTransform )
{
const char *psHeader = reinterpret_cast<char *>(abyHeader);
const double dfLLLat = JDEMGetAngle(psHeader + 29);
const double dfLLLong = JDEMGetAngle(psHeader + 36);
const double dfURLat = JDEMGetAngle(psHeader + 43);
const double dfURLong = JDEMGetAngle(psHeader + 50);
padfTransform[0] = dfLLLong;
padfTransform[3] = dfURLat;
padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize();
padfTransform[2] = 0.0;
padfTransform[4] = 0.0;
padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize();
return CE_None;
}
/************************************************************************/
/* GetProjectionRef() */
/************************************************************************/
const char *JDEMDataset::_GetProjectionRef()
{
return
"GEOGCS[\"Tokyo\",DATUM[\"Tokyo\","
"SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,"
"AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,507,685,0,0,0,0],"
"AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\",0,"
"AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,"
"AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4301]]";
}
/************************************************************************/
/* Identify() */
/************************************************************************/
int JDEMDataset::Identify( GDALOpenInfo *poOpenInfo )
{
// Confirm that the header has what appears to be dates in the
// expected locations. Sadly this is a relatively weak test.
if( poOpenInfo->nHeaderBytes < 50 )
return FALSE;
// Check if century values seem reasonable.
const char *psHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
if( (!STARTS_WITH_CI(psHeader + 11, "19") &&
!STARTS_WITH_CI(psHeader + 11, "20")) ||
(!STARTS_WITH_CI(psHeader + 15, "19") &&
!STARTS_WITH_CI(psHeader + 15, "20")) ||
(!STARTS_WITH_CI(psHeader + 19, "19") &&
!STARTS_WITH_CI(psHeader + 19, "20")) )
{
return FALSE;
}
return TRUE;
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset *JDEMDataset::Open( GDALOpenInfo *poOpenInfo )
{
// Confirm that the header is compatible with a JDEM dataset.
if (!Identify(poOpenInfo))
return nullptr;
// Confirm the requested access is supported.
if( poOpenInfo->eAccess == GA_Update )
{
"The JDEM driver does not support update access to existing "
"datasets.");
return nullptr;
}
// Check that the file pointer from GDALOpenInfo* is available.
if( poOpenInfo->fpL == nullptr )
{
return nullptr;
}
// Create a corresponding GDALDataset.
JDEMDataset *poDS = new JDEMDataset();
// Borrow the file pointer from GDALOpenInfo*.
poDS->fp = poOpenInfo->fpL;
poOpenInfo->fpL = nullptr;
// Read the header.
CPL_IGNORE_RET_VAL(VSIFReadL(poDS->abyHeader, 1, 1012, poDS->fp));
const char *psHeader = reinterpret_cast<char *>(poDS->abyHeader);
poDS->nRasterXSize = JDEMGetField(psHeader + 23, 3);
poDS->nRasterYSize = JDEMGetField(psHeader + 26, 3);
if( poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
{
"Invalid dimensions : %d x %d",
poDS->nRasterXSize, poDS->nRasterYSize);
delete poDS;
return nullptr;
}
// Create band information objects.
poDS->SetBand(1, new JDEMRasterBand(poDS, 1));
// Initialize any PAM information.
poDS->SetDescription(poOpenInfo->pszFilename);
poDS->TryLoadXML();
// Check for overviews.
poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
return poDS;
}
/************************************************************************/
/* GDALRegister_JDEM() */
/************************************************************************/
void GDALRegister_JDEM()
{
if( GDALGetDriverByName("JDEM") != nullptr )
return;
GDALDriver *poDriver = new GDALDriver();
poDriver->SetDescription("JDEM");
poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Japanese DEM (.mem)");
poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#JDEM");
poDriver->pfnOpen = JDEMDataset::Open;
poDriver->pfnIdentify = JDEMDataset::Identify;
}
GDAL_DCAP_VIRTUALIO
#define GDAL_DCAP_VIRTUALIO
Capability set by a driver that can read/create datasets through the VSI*L API.
Definition: gdal.h:353
GDALOpenInfo::fpL
VSILFILE * fpL
Pointer to the file.
Definition: gdal_priv.h:292
GByte
unsigned char GByte
Unsigned byte type.
Definition: cpl_port.h:215
GDALOpenInfo
Class for dataset open functions.
Definition: gdal_priv.h:265
VSIFReadL
size_t VSIFReadL(void *, size_t, size_t, VSILFILE *) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
Read bytes from file.
Definition: cpl_vsil.cpp:1690
GDT_Float32
@ GDT_Float32
Definition: gdal.h:69
GDAL_DMD_EXTENSION
#define GDAL_DMD_EXTENSION
Extension handled by the driver.
Definition: gdal.h:289
GDALPamDataset
PAM dataset.
Definition: gdal_pam.h:114
GDALDriver
Format specific driver.
Definition: gdal_priv.h:1423
GDALPamRasterBand
PAM raster band.
Definition: gdal_pam.h:247
OGRSpatialReference
This class represents an OpenGIS Spatial Reference System, and contains methods for converting betwee...
Definition: ogr_spatialref.h:156
GDAL_DMD_LONGNAME
#define GDAL_DMD_LONGNAME
Long name of the driver.
Definition: gdal.h:280
GDALDriverManager::RegisterDriver
int RegisterDriver(GDALDriver *)
Register a driver for use.
Definition: gdaldrivermanager.cpp:425
GDALMajorObject::SetDescription
virtual void SetDescription(const char *)
Set object description.
Definition: gdalmajorobject.cpp:120
VSIFCloseL
int VSIFCloseL(VSILFILE *) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
Close file.
Definition: cpl_vsil.cpp:1472
GDALDataset
A set of associated raster bands, usually from one file.
Definition: gdal_priv.h:335
CPLAssert
#define CPLAssert(expr)
Assert on an expression.
Definition: cpl_error.h:186
GDALOpenInfo::pabyHeader
GByte * pabyHeader
Buffer with first bytes of the file.
Definition: gdal_priv.h:297
GDALOpenInfo::eAccess
GDALAccess eAccess
Access flag.
Definition: gdal_priv.h:282
GDALDataset::Open
static GDALDataset * Open(const char *pszFilename, unsigned int nOpenFlags=0, const char *const *papszAllowedDrivers=nullptr, const char *const *papszOpenOptions=nullptr, const char *const *papszSiblingFiles=nullptr)
Definition: gdal_priv.h:613
GDALRasterBand::IReadBlock
virtual CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void *pData)=0
Read a block of data.
GDALGetDriverByName
GDALDriverH GDALGetDriverByName(const char *)
Fetch a driver based on the short name.
Definition: gdaldrivermanager.cpp:612
GDALPamDataset::GetSpatialRef
const OGRSpatialReference * GetSpatialRef() const override
Fetch the spatial reference for this dataset.
Definition: gdalpamdataset.cpp:1149
VSIFSeekL
int VSIFSeekL(VSILFILE *, vsi_l_offset, int) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
Seek to requested offset.
Definition: cpl_vsil.cpp:1532
CPLError
void CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,...)
Report an error.
Definition: cpl_error.cpp:308
GDALDriver::SetMetadataItem
CPLErr SetMetadataItem(const char *pszName, const char *pszValue, const char *pszDomain="") override
Set single metadata item.
Definition: gdaldriver.cpp:2144
VSIFree
void VSIFree(void *)
Analog of free() for data allocated with VSIMalloc(), VSICalloc(), VSIRealloc()
Definition: cpl_vsisimple.cpp:827
CPLE_NotSupported
#define CPLE_NotSupported
Not supported.
Definition: cpl_error.h:109
CPL_ARRAYSIZE
#define CPL_ARRAYSIZE(array)
Returns the size of C style arrays.
Definition: cpl_port.h:1045
GDALPamDataset::GetGeoTransform
CPLErr GetGeoTransform(double *) override
Fetch the affine transformation coefficients.
Definition: gdalpamdataset.cpp:1182
VSI_MALLOC_VERBOSE
#define VSI_MALLOC_VERBOSE(size)
VSI_MALLOC_VERBOSE.
Definition: cpl_vsi.h:268
GDALOpenInfo::nHeaderBytes
int nHeaderBytes
Number of bytes in pabyHeader.
Definition: gdal_priv.h:295
CPL_UNUSED
#define CPL_UNUSED
Qualifier for an argument that is unused.
Definition: cpl_port.h:948
cpl_port.h
EQUALN
#define EQUALN(a, b, n)
Alias for strncasecmp() == 0.
Definition: cpl_port.h:567
GA_Update
@ GA_Update
Definition: gdal.h:115
CPLErr
CPLErr
Error category.
Definition: cpl_error.h:52
GDALOpenInfo::pszFilename
char * pszFilename
Filename.
Definition: gdal_priv.h:277
GetGDALDriverManager
GDALDriverManager * GetGDALDriverManager(void)
Fetch the global GDAL driver manager.
Definition: gdaldrivermanager.cpp:97
GDAL_DCAP_RASTER
#define GDAL_DCAP_RASTER
Capability set by a driver having raster capability.
Definition: gdal.h:358
GDAL_DMD_HELPTOPIC
#define GDAL_DMD_HELPTOPIC
URL (relative to http://gdal.org/) to the help page of the driver.
Definition: gdal.h:283
VSILFILE
FILE VSILFILE
Opaque type for a FILE that implements the VSIVirtualHandle API.
Definition: cpl_vsi.h:156
STARTS_WITH_CI
#define STARTS_WITH_CI(a, b)
Returns whether a starts with b (case insensitive comparison)
Definition: cpl_port.h:580
CPLE_AppDefined
#define CPLE_AppDefined
Application defined error.
Definition: cpl_error.h:99

Generated for GDAL by doxygen 1.8.17.