1
/******************************************************************************
2
* $Id: gdal_edb.cpp 20632 2010-09-16 19:49:24Z rouault $
4
* Project: PCIDSK Database File
5
* Purpose: External Database access interface implementation (EDBFile).
6
* Author: Frank Warmerdam, warmerdam@pobox.com
8
******************************************************************************
9
* Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
11
* Permission is hereby granted, free of charge, to any person obtaining a
12
* copy of this software and associated documentation files (the "Software"),
13
* to deal in the Software without restriction, including without limitation
14
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
* and/or sell copies of the Software, and to permit persons to whom the
16
* Software is furnished to do so, subject to the following conditions:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
21
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
* DEALINGS IN THE SOFTWARE.
28
****************************************************************************/
31
#include "cpl_multiproc.h"
32
#include "gdal_priv.h"
35
CPL_CVSID("$Id: gdal_edb.cpp 20632 2010-09-16 19:49:24Z rouault $");
37
using namespace PCIDSK;
39
/************************************************************************/
40
/* ==================================================================== */
42
/* ==================================================================== */
43
/************************************************************************/
45
class GDAL_EDBFile : public EDBFile
51
GDAL_EDBFile( GDALDataset *poDSIn ) { poDS = poDSIn; }
52
~GDAL_EDBFile() { if( poDS ) Close(); }
56
int GetHeight() const;
57
int GetChannels() const;
58
int GetBlockWidth(int channel ) const;
59
int GetBlockHeight(int channel ) const;
60
eChanType GetType(int channel ) const;
61
int ReadBlock(int channel,
62
int block_index, void *buffer,
63
int win_xoff, int win_yoff,
64
int win_xsize, int win_ysize );
65
int WriteBlock( int channel, int block_index, void *buffer);
68
/************************************************************************/
70
/************************************************************************/
72
EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess )
78
poDS = (GDALDataset *) GDALOpen( osFilename.c_str(), GA_ReadOnly );
80
poDS = (GDALDataset *) GDALOpen( osFilename.c_str(), GA_Update );
83
ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );
85
return new GDAL_EDBFile( poDS );
88
/************************************************************************/
90
/************************************************************************/
92
int GDAL_EDBFile::Close() const
98
((GDAL_EDBFile*)this)->poDS = NULL;
104
/************************************************************************/
106
/************************************************************************/
108
int GDAL_EDBFile::GetWidth() const
111
return poDS->GetRasterXSize();
114
/************************************************************************/
116
/************************************************************************/
118
int GDAL_EDBFile::GetHeight() const
121
return poDS->GetRasterYSize();
124
/************************************************************************/
126
/************************************************************************/
128
int GDAL_EDBFile::GetChannels() const
131
return poDS->GetRasterCount();
134
/************************************************************************/
135
/* GetBlockWidth() */
136
/************************************************************************/
138
int GDAL_EDBFile::GetBlockWidth( int nChannel ) const
143
poDS->GetRasterBand(nChannel)->GetBlockSize( &nWidth, &nHeight );
148
/************************************************************************/
149
/* GetBlockHeight() */
150
/************************************************************************/
152
int GDAL_EDBFile::GetBlockHeight( int nChannel ) const
157
poDS->GetRasterBand(nChannel)->GetBlockSize( &nWidth, &nHeight );
162
/************************************************************************/
164
/************************************************************************/
166
eChanType GDAL_EDBFile::GetType( int nChannel ) const
168
switch( poDS->GetRasterBand(nChannel)->GetRasterDataType() )
190
/************************************************************************/
192
/************************************************************************/
194
int GDAL_EDBFile::ReadBlock( int channel,
195
int block_index, void *buffer,
196
int win_xoff, int win_yoff,
197
int win_xsize, int win_ysize )
200
GDALRasterBand *poBand = poDS->GetRasterBand(channel);
201
int nBlockXSize, nBlockYSize;
202
int nBlockX, nBlockY;
207
if( GetType(channel) == CHN_UNKNOWN )
209
ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
210
GDALGetDataTypeName(poBand->GetRasterDataType()) );
213
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
215
nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
217
nBlockX = block_index % nWidthInBlocks;
218
nBlockY = block_index / nWidthInBlocks;
220
nPixelOffset = GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8;
221
nLineOffset = win_xsize * nPixelOffset;
223
/* -------------------------------------------------------------------- */
224
/* Are we reading a partial block at the edge of the database? */
225
/* If so, ensure we don't read off the database. */
226
/* -------------------------------------------------------------------- */
227
if( nBlockX * nBlockXSize + win_xoff + win_xsize > poBand->GetXSize() )
228
win_xsize = poBand->GetXSize() - nBlockX * nBlockXSize - win_xoff;
230
if( nBlockY * nBlockYSize + win_yoff + win_ysize > poBand->GetYSize() )
231
win_ysize = poBand->GetYSize() - nBlockY * nBlockYSize - win_yoff;
233
CPLErr eErr = poBand->RasterIO( GF_Read,
234
nBlockX * nBlockXSize + win_xoff,
235
nBlockY * nBlockYSize + win_yoff,
236
win_xsize, win_ysize,
237
buffer, win_xsize, win_ysize,
238
poBand->GetRasterDataType(),
239
nPixelOffset, nLineOffset );
241
if( eErr != CE_None )
243
ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );
249
/************************************************************************/
251
/************************************************************************/
253
int GDAL_EDBFile::WriteBlock( int channel, int block_index, void *buffer)
256
GDALRasterBand *poBand = poDS->GetRasterBand(channel);
257
int nBlockXSize, nBlockYSize;
258
int nBlockX, nBlockY;
259
int nWinXSize, nWinYSize;
262
if( GetType(channel) == CHN_UNKNOWN )
264
ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
265
GDALGetDataTypeName(poBand->GetRasterDataType()) );
268
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
270
nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
272
nBlockX = block_index % nWidthInBlocks;
273
nBlockY = block_index / nWidthInBlocks;
275
/* -------------------------------------------------------------------- */
276
/* Are we reading a partial block at the edge of the database? */
277
/* If so, ensure we don't read off the database. */
278
/* -------------------------------------------------------------------- */
279
if( nBlockX * nBlockXSize + nBlockXSize > poBand->GetXSize() )
280
nWinXSize = poBand->GetXSize() - nBlockX * nBlockXSize;
282
nWinXSize = nBlockXSize;
284
if( nBlockY * nBlockYSize + nBlockYSize > poBand->GetYSize() )
285
nWinYSize = poBand->GetYSize() - nBlockY * nBlockYSize;
287
nWinYSize = nBlockYSize;
289
CPLErr eErr = poBand->RasterIO( GF_Write,
290
nBlockX * nBlockXSize,
291
nBlockY * nBlockYSize,
292
nWinXSize, nWinYSize,
293
buffer, nWinXSize, nWinYSize,
294
poBand->GetRasterDataType(), 0, 0 );
296
if( eErr != CE_None )
298
ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );