ultimatepp/bazaar/plugin/gdal/frmts/pcidsk/gdal_edb.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

302 lines
10 KiB
C++

/******************************************************************************
* $Id: gdal_edb.cpp 28053 2014-12-04 09:31:07Z rouault $
*
* Project: PCIDSK Database File
* Purpose: External Database access interface implementation (EDBFile).
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
*
* 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_conv.h"
#include "cpl_multiproc.h"
#include "gdal_priv.h"
#include "pcidsk.h"
CPL_CVSID("$Id: gdal_edb.cpp 28053 2014-12-04 09:31:07Z rouault $");
using namespace PCIDSK;
/************************************************************************/
/* ==================================================================== */
/* GDAL_EDBFile */
/* ==================================================================== */
/************************************************************************/
class GDAL_EDBFile : public EDBFile
{
GDALDataset *poDS;
public:
GDAL_EDBFile( GDALDataset *poDSIn ) { poDS = poDSIn; }
~GDAL_EDBFile() { if( poDS ) Close(); }
int Close() const;
int GetWidth() const;
int GetHeight() const;
int GetChannels() const;
int GetBlockWidth(int channel ) const;
int GetBlockHeight(int channel ) const;
eChanType GetType(int channel ) const;
int ReadBlock(int channel,
int block_index, void *buffer,
int win_xoff, int win_yoff,
int win_xsize, int win_ysize );
int WriteBlock( int channel, int block_index, void *buffer);
};
/************************************************************************/
/* GDAL_EDBOpen() */
/************************************************************************/
EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess )
{
GDALDataset *poDS;
if( osAccess == "r" )
poDS = (GDALDataset *) GDALOpen( osFilename.c_str(), GA_ReadOnly );
else
poDS = (GDALDataset *) GDALOpen( osFilename.c_str(), GA_Update );
if( poDS == NULL )
ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );
return new GDAL_EDBFile( poDS );
}
/************************************************************************/
/* Close() */
/************************************************************************/
int GDAL_EDBFile::Close() const
{
if( poDS != NULL )
{
delete poDS;
((GDAL_EDBFile*)this)->poDS = NULL;
}
return 1;
}
/************************************************************************/
/* GetWidth() */
/************************************************************************/
int GDAL_EDBFile::GetWidth() const
{
return poDS->GetRasterXSize();
}
/************************************************************************/
/* GetHeight() */
/************************************************************************/
int GDAL_EDBFile::GetHeight() const
{
return poDS->GetRasterYSize();
}
/************************************************************************/
/* GetChannels() */
/************************************************************************/
int GDAL_EDBFile::GetChannels() const
{
return poDS->GetRasterCount();
}
/************************************************************************/
/* GetBlockWidth() */
/************************************************************************/
int GDAL_EDBFile::GetBlockWidth( int nChannel ) const
{
int nWidth, nHeight;
poDS->GetRasterBand(nChannel)->GetBlockSize( &nWidth, &nHeight );
return nWidth;
}
/************************************************************************/
/* GetBlockHeight() */
/************************************************************************/
int GDAL_EDBFile::GetBlockHeight( int nChannel ) const
{
int nWidth, nHeight;
poDS->GetRasterBand(nChannel)->GetBlockSize( &nWidth, &nHeight );
return nHeight;
}
/************************************************************************/
/* GetType() */
/************************************************************************/
eChanType GDAL_EDBFile::GetType( int nChannel ) const
{
switch( poDS->GetRasterBand(nChannel)->GetRasterDataType() )
{
case GDT_Byte:
return CHN_8U;
case GDT_Int16:
return CHN_16S;
case GDT_UInt16:
return CHN_16U;
case GDT_Float32:
return CHN_32R;
case GDT_CInt16:
return CHN_C16S;
default:
return CHN_UNKNOWN;
}
}
/************************************************************************/
/* ReadBlock() */
/************************************************************************/
int GDAL_EDBFile::ReadBlock( int channel,
int block_index, void *buffer,
int win_xoff, int win_yoff,
int win_xsize, int win_ysize )
{
GDALRasterBand *poBand = poDS->GetRasterBand(channel);
int nBlockXSize, nBlockYSize;
int nBlockX, nBlockY;
int nWidthInBlocks;
int nPixelOffset;
int nLineOffset;
if( GetType(channel) == CHN_UNKNOWN )
{
ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
GDALGetDataTypeName(poBand->GetRasterDataType()) );
}
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
nBlockX = block_index % nWidthInBlocks;
nBlockY = block_index / nWidthInBlocks;
nPixelOffset = GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8;
nLineOffset = win_xsize * nPixelOffset;
/* -------------------------------------------------------------------- */
/* Are we reading a partial block at the edge of the database? */
/* If so, ensure we don't read off the database. */
/* -------------------------------------------------------------------- */
if( nBlockX * nBlockXSize + win_xoff + win_xsize > poBand->GetXSize() )
win_xsize = poBand->GetXSize() - nBlockX * nBlockXSize - win_xoff;
if( nBlockY * nBlockYSize + win_yoff + win_ysize > poBand->GetYSize() )
win_ysize = poBand->GetYSize() - nBlockY * nBlockYSize - win_yoff;
CPLErr eErr = poBand->RasterIO( GF_Read,
nBlockX * nBlockXSize + win_xoff,
nBlockY * nBlockYSize + win_yoff,
win_xsize, win_ysize,
buffer, win_xsize, win_ysize,
poBand->GetRasterDataType(),
nPixelOffset, nLineOffset, NULL );
if( eErr != CE_None )
{
ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );
}
return 1;
}
/************************************************************************/
/* WriteBlock() */
/************************************************************************/
int GDAL_EDBFile::WriteBlock( int channel, int block_index, void *buffer)
{
GDALRasterBand *poBand = poDS->GetRasterBand(channel);
int nBlockXSize, nBlockYSize;
int nBlockX, nBlockY;
int nWinXSize, nWinYSize;
int nWidthInBlocks;
if( GetType(channel) == CHN_UNKNOWN )
{
ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
GDALGetDataTypeName(poBand->GetRasterDataType()) );
}
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
nBlockX = block_index % nWidthInBlocks;
nBlockY = block_index / nWidthInBlocks;
/* -------------------------------------------------------------------- */
/* Are we reading a partial block at the edge of the database? */
/* If so, ensure we don't read off the database. */
/* -------------------------------------------------------------------- */
if( nBlockX * nBlockXSize + nBlockXSize > poBand->GetXSize() )
nWinXSize = poBand->GetXSize() - nBlockX * nBlockXSize;
else
nWinXSize = nBlockXSize;
if( nBlockY * nBlockYSize + nBlockYSize > poBand->GetYSize() )
nWinYSize = poBand->GetYSize() - nBlockY * nBlockYSize;
else
nWinYSize = nBlockYSize;
CPLErr eErr = poBand->RasterIO( GF_Write,
nBlockX * nBlockXSize,
nBlockY * nBlockYSize,
nWinXSize, nWinYSize,
buffer, nWinXSize, nWinYSize,
poBand->GetRasterDataType(), 0, 0, NULL );
if( eErr != CE_None )
{
ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );
}
return 1;
}