mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-19 22:03:51 -06:00
1242 lines
48 KiB
C++
1242 lines
48 KiB
C++
/******************************************************************************
|
|
* $Id: rawdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
|
|
*
|
|
* Project: Generic Raw Binary Driver
|
|
* Purpose: Implementation of RawDataset and RawRasterBand classes.
|
|
* Author: Frank Warmerdam, warmerda@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 1999, Frank Warmerdam
|
|
* Copyright (c) 2007-2014, 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 "rawdataset.h"
|
|
#include "cpl_conv.h"
|
|
#include "cpl_string.h"
|
|
|
|
CPL_CVSID("$Id: rawdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
|
|
|
|
/************************************************************************/
|
|
/* RawRasterBand() */
|
|
/************************************************************************/
|
|
|
|
RawRasterBand::RawRasterBand( GDALDataset *poDS, int nBand,
|
|
void * fpRaw, vsi_l_offset nImgOffset,
|
|
int nPixelOffset, int nLineOffset,
|
|
GDALDataType eDataType, int bNativeOrder,
|
|
int bIsVSIL, int bOwnsFP )
|
|
|
|
{
|
|
this->poDS = poDS;
|
|
this->nBand = nBand;
|
|
this->eDataType = eDataType;
|
|
this->bIsVSIL = bIsVSIL;
|
|
this->bOwnsFP =bOwnsFP;
|
|
|
|
if (bIsVSIL)
|
|
{
|
|
this->fpRaw = NULL;
|
|
this->fpRawL = (VSILFILE*) fpRaw;
|
|
}
|
|
else
|
|
{
|
|
this->fpRaw = (FILE*) fpRaw;
|
|
this->fpRawL = NULL;
|
|
}
|
|
this->nImgOffset = nImgOffset;
|
|
this->nPixelOffset = nPixelOffset;
|
|
this->nLineOffset = nLineOffset;
|
|
this->bNativeOrder = bNativeOrder;
|
|
|
|
CPLDebug( "GDALRaw",
|
|
"RawRasterBand(%p,%d,%p,\n"
|
|
" Off=%d,PixOff=%d,LineOff=%d,%s,%d)\n",
|
|
poDS, nBand, fpRaw,
|
|
(unsigned int) nImgOffset, nPixelOffset, nLineOffset,
|
|
GDALGetDataTypeName(eDataType), bNativeOrder );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Treat one scanline as the block size. */
|
|
/* -------------------------------------------------------------------- */
|
|
nBlockXSize = poDS->GetRasterXSize();
|
|
nBlockYSize = 1;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize other fields, and setup the line buffer. */
|
|
/* -------------------------------------------------------------------- */
|
|
Initialize();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* RawRasterBand() */
|
|
/************************************************************************/
|
|
|
|
RawRasterBand::RawRasterBand( void * fpRaw, vsi_l_offset nImgOffset,
|
|
int nPixelOffset, int nLineOffset,
|
|
GDALDataType eDataType, int bNativeOrder,
|
|
int nXSize, int nYSize, int bIsVSIL, int bOwnsFP )
|
|
|
|
{
|
|
this->poDS = NULL;
|
|
this->nBand = 1;
|
|
this->eDataType = eDataType;
|
|
this->bIsVSIL = bIsVSIL;
|
|
this->bOwnsFP =bOwnsFP;
|
|
|
|
if (bIsVSIL)
|
|
{
|
|
this->fpRaw = NULL;
|
|
this->fpRawL = (VSILFILE*) fpRaw;
|
|
}
|
|
else
|
|
{
|
|
this->fpRaw = (FILE*) fpRaw;
|
|
this->fpRawL = NULL;
|
|
}
|
|
this->nImgOffset = nImgOffset;
|
|
this->nPixelOffset = nPixelOffset;
|
|
this->nLineOffset = nLineOffset;
|
|
this->bNativeOrder = bNativeOrder;
|
|
|
|
|
|
CPLDebug( "GDALRaw",
|
|
"RawRasterBand(floating,Off=%d,PixOff=%d,LineOff=%d,%s,%d)\n",
|
|
(unsigned int) nImgOffset, nPixelOffset, nLineOffset,
|
|
GDALGetDataTypeName(eDataType), bNativeOrder );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Treat one scanline as the block size. */
|
|
/* -------------------------------------------------------------------- */
|
|
nBlockXSize = nXSize;
|
|
nBlockYSize = 1;
|
|
nRasterXSize = nXSize;
|
|
nRasterYSize = nYSize;
|
|
if (!GDALCheckDatasetDimensions(nXSize, nYSize))
|
|
{
|
|
pLineBuffer = NULL;
|
|
return;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize other fields, and setup the line buffer. */
|
|
/* -------------------------------------------------------------------- */
|
|
Initialize();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Initialize() */
|
|
/************************************************************************/
|
|
|
|
void RawRasterBand::Initialize()
|
|
|
|
{
|
|
poCT = NULL;
|
|
eInterp = GCI_Undefined;
|
|
|
|
papszCategoryNames = NULL;
|
|
|
|
bDirty = FALSE;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Allocate working scanline. */
|
|
/* -------------------------------------------------------------------- */
|
|
nLoadedScanline = -1;
|
|
if (nBlockXSize <= 0 || nPixelOffset > INT_MAX / nBlockXSize)
|
|
{
|
|
nLineSize = 0;
|
|
pLineBuffer = NULL;
|
|
}
|
|
else
|
|
{
|
|
nLineSize = ABS(nPixelOffset) * nBlockXSize;
|
|
pLineBuffer = VSIMalloc2( ABS(nPixelOffset), nBlockXSize );
|
|
}
|
|
if (pLineBuffer == NULL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Could not allocate line buffer : nPixelOffset=%d, nBlockXSize=%d",
|
|
nPixelOffset, nBlockXSize);
|
|
}
|
|
|
|
if( nPixelOffset >= 0 )
|
|
pLineStart = pLineBuffer;
|
|
else
|
|
pLineStart = ((char *) pLineBuffer) + ABS(nPixelOffset) * (nBlockXSize-1);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~RawRasterBand() */
|
|
/************************************************************************/
|
|
|
|
RawRasterBand::~RawRasterBand()
|
|
|
|
{
|
|
if( poCT )
|
|
delete poCT;
|
|
|
|
CSLDestroy( papszCategoryNames );
|
|
|
|
FlushCache();
|
|
|
|
if (bOwnsFP)
|
|
{
|
|
if ( bIsVSIL )
|
|
VSIFCloseL( fpRawL );
|
|
else
|
|
VSIFClose( fpRaw );
|
|
}
|
|
|
|
CPLFree( pLineBuffer );
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* SetAccess() */
|
|
/************************************************************************/
|
|
|
|
void RawRasterBand::SetAccess( GDALAccess eAccess )
|
|
{
|
|
this->eAccess = eAccess;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* FlushCache() */
|
|
/* */
|
|
/* We override this so we have the opportunity to call */
|
|
/* fflush(). We don't want to do this all the time in the */
|
|
/* write block function as it is kind of expensive. */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::FlushCache()
|
|
|
|
{
|
|
CPLErr eErr;
|
|
|
|
eErr = GDALRasterBand::FlushCache();
|
|
if( eErr != CE_None )
|
|
return eErr;
|
|
|
|
// If we have unflushed raw, flush it to disk now.
|
|
if ( bDirty )
|
|
{
|
|
if( bIsVSIL )
|
|
VSIFFlushL( fpRawL );
|
|
else
|
|
VSIFFlush( fpRaw );
|
|
|
|
bDirty = FALSE;
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AccessLine() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::AccessLine( int iLine )
|
|
|
|
{
|
|
if (pLineBuffer == NULL)
|
|
return CE_Failure;
|
|
|
|
if( nLoadedScanline == iLine )
|
|
return CE_None;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Figure out where to start reading. */
|
|
/* -------------------------------------------------------------------- */
|
|
vsi_l_offset nReadStart;
|
|
if( nPixelOffset >= 0 )
|
|
nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset;
|
|
else
|
|
{
|
|
nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset
|
|
- ABS(nPixelOffset) * (nBlockXSize-1);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Seek to the right line. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( Seek(nReadStart, SEEK_SET) == -1 )
|
|
{
|
|
if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to seek to scanline %d @ " CPL_FRMT_GUIB ".\n",
|
|
iLine, nImgOffset + (vsi_l_offset)iLine * nLineOffset );
|
|
return CE_Failure;
|
|
}
|
|
else
|
|
{
|
|
memset( pLineBuffer, 0, nPixelOffset * nBlockXSize );
|
|
nLoadedScanline = iLine;
|
|
return CE_None;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Read the line. Take care not to request any more bytes than */
|
|
/* are needed, and not to lose a partially successful scanline */
|
|
/* read. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nBytesToRead, nBytesActuallyRead;
|
|
|
|
nBytesToRead = ABS(nPixelOffset) * (nBlockXSize - 1)
|
|
+ GDALGetDataTypeSize(GetRasterDataType()) / 8;
|
|
|
|
nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead );
|
|
if( nBytesActuallyRead < nBlockXSize )
|
|
{
|
|
if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to read scanline %d.\n",
|
|
iLine);
|
|
return CE_Failure;
|
|
}
|
|
else
|
|
{
|
|
memset( ((GByte *) pLineBuffer) + nBytesActuallyRead,
|
|
0, nBytesToRead - nBytesActuallyRead );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap the interesting data, if required. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) );
|
|
GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize,
|
|
nWordSize, nBlockXSize, ABS(nPixelOffset) );
|
|
}
|
|
else
|
|
GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
|
|
nBlockXSize, ABS(nPixelOffset) );
|
|
}
|
|
|
|
nLoadedScanline = iLine;
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IReadBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
|
|
int nBlockYOff,
|
|
void * pImage )
|
|
{
|
|
CPLErr eErr;
|
|
|
|
CPLAssert( nBlockXOff == 0 );
|
|
|
|
if (pLineBuffer == NULL)
|
|
return CE_Failure;
|
|
|
|
eErr = AccessLine( nBlockYOff );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy data from disk buffer to user block buffer. */
|
|
/* -------------------------------------------------------------------- */
|
|
GDALCopyWords( pLineStart, eDataType, nPixelOffset,
|
|
pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
|
|
nBlockXSize );
|
|
|
|
return eErr;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IWriteBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
|
|
int nBlockYOff,
|
|
void * pImage )
|
|
{
|
|
CPLErr eErr = CE_None;
|
|
|
|
CPLAssert( nBlockXOff == 0 );
|
|
|
|
if (pLineBuffer == NULL)
|
|
return CE_Failure;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If the data for this band is completely contiguous we don't */
|
|
/* have to worry about pre-reading from disk. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( ABS(nPixelOffset) > GDALGetDataTypeSize(eDataType) / 8 )
|
|
eErr = AccessLine( nBlockYOff );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy data from user buffer into disk buffer. */
|
|
/* -------------------------------------------------------------------- */
|
|
GDALCopyWords( pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
|
|
pLineStart, eDataType, nPixelOffset,
|
|
nBlockXSize );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap (if necessary) back into disk order before writing. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
|
|
ABS(nPixelOffset) );
|
|
GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize,
|
|
nWordSize, nBlockXSize, ABS(nPixelOffset) );
|
|
}
|
|
else
|
|
GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
|
|
nBlockXSize, ABS(nPixelOffset) );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Figure out where to start reading. */
|
|
/* -------------------------------------------------------------------- */
|
|
vsi_l_offset nWriteStart;
|
|
if( nPixelOffset >= 0 )
|
|
nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset;
|
|
else
|
|
{
|
|
nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset
|
|
- ABS(nPixelOffset) * (nBlockXSize-1);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Seek to correct location. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( Seek( nWriteStart, SEEK_SET ) == -1 )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to seek to scanline %d @ " CPL_FRMT_GUIB " to write to file.\n",
|
|
nBlockYOff, nImgOffset + nBlockYOff * nLineOffset );
|
|
|
|
eErr = CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Write data buffer. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nBytesToWrite;
|
|
|
|
nBytesToWrite = ABS(nPixelOffset) * (nBlockXSize - 1)
|
|
+ GDALGetDataTypeSize(GetRasterDataType()) / 8;
|
|
|
|
if( eErr == CE_None
|
|
&& Write( pLineBuffer, 1, nBytesToWrite ) < (size_t) nBytesToWrite )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to write scanline %d to file.\n",
|
|
nBlockYOff );
|
|
|
|
eErr = CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap (if necessary) back into machine order so the */
|
|
/* buffer is still usable for reading purposes. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
|
|
ABS(nPixelOffset) );
|
|
GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize,
|
|
nWordSize, nBlockXSize,
|
|
ABS(nPixelOffset) );
|
|
}
|
|
else
|
|
GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
|
|
nBlockXSize, ABS(nPixelOffset) );
|
|
}
|
|
|
|
bDirty = TRUE;
|
|
return eErr;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AccessBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
|
|
void * pData )
|
|
{
|
|
int nBytesActuallyRead;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Seek to the right block. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( Seek( nBlockOff, SEEK_SET ) == -1 )
|
|
{
|
|
memset( pData, 0, nBlockSize );
|
|
return CE_None;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Read the block. */
|
|
/* -------------------------------------------------------------------- */
|
|
nBytesActuallyRead = Read( pData, 1, nBlockSize );
|
|
if( nBytesActuallyRead < nBlockSize )
|
|
{
|
|
|
|
memset( ((GByte *) pData) + nBytesActuallyRead,
|
|
0, nBlockSize - nBytesActuallyRead );
|
|
return CE_None;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap the interesting data, if required. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pData, nWordSize, nBlockSize / nPixelOffset,
|
|
nPixelOffset );
|
|
GDALSwapWords( ((GByte *) pData) + nWordSize,
|
|
nWordSize, nBlockSize / nPixelOffset, nPixelOffset );
|
|
}
|
|
else
|
|
GDALSwapWords( pData, GDALGetDataTypeSize(eDataType) / 8,
|
|
nBlockSize / nPixelOffset, nPixelOffset );
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IsSignificantNumberOfLinesLoaded() */
|
|
/* */
|
|
/* Check if there is a significant number of scanlines (>20%) from the */
|
|
/* specified block of lines already cached. */
|
|
/************************************************************************/
|
|
|
|
int RawRasterBand::IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines )
|
|
{
|
|
int iLine;
|
|
int nCountLoaded = 0;
|
|
|
|
for ( iLine = nLineOff; iLine < nLineOff + nLines; iLine++ )
|
|
{
|
|
GDALRasterBlock *poBlock = TryGetLockedBlockRef( 0, iLine );
|
|
if( poBlock != NULL )
|
|
{
|
|
poBlock->DropLock();
|
|
nCountLoaded ++;
|
|
if( nCountLoaded > nLines / 20 )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CanUseDirectIO() */
|
|
/************************************************************************/
|
|
|
|
int RawRasterBand::CanUseDirectIO(CPL_UNUSED int nXOff,
|
|
int nYOff,
|
|
int nXSize,
|
|
int nYSize,
|
|
CPL_UNUSED GDALDataType eBufType)
|
|
{
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Use direct IO without caching if: */
|
|
/* */
|
|
/* GDAL_ONE_BIG_READ is enabled */
|
|
/* */
|
|
/* or */
|
|
/* */
|
|
/* the length of a scanline on disk is more than 50000 bytes, and the */
|
|
/* width of the requested chunk is less than 40% of the whole scanline */
|
|
/* and no significant number of requested scanlines are already in the */
|
|
/* cache. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nPixelOffset < 0 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
const char* pszGDAL_ONE_BIG_READ = CPLGetConfigOption( "GDAL_ONE_BIG_READ", NULL);
|
|
if ( pszGDAL_ONE_BIG_READ == NULL )
|
|
{
|
|
int nBytesToRW = nPixelOffset * nXSize;
|
|
if ( nLineSize < 50000
|
|
|| nBytesToRW > nLineSize / 5 * 2
|
|
|| IsSignificantNumberOfLinesLoaded( nYOff, nYSize ) )
|
|
{
|
|
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
return CSLTestBoolean(pszGDAL_ONE_BIG_READ);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IRasterIO() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
|
|
int nXOff, int nYOff, int nXSize, int nYSize,
|
|
void * pData, int nBufXSize, int nBufYSize,
|
|
GDALDataType eBufType,
|
|
GSpacing nPixelSpace, GSpacing nLineSpace,
|
|
GDALRasterIOExtraArg* psExtraArg )
|
|
|
|
{
|
|
int nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
|
|
int nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
|
|
int nBytesToRW = nPixelOffset * nXSize;
|
|
|
|
if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
|
|
{
|
|
return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
|
|
nXSize, nYSize,
|
|
pData, nBufXSize, nBufYSize,
|
|
eBufType,
|
|
nPixelSpace, nLineSpace, psExtraArg );
|
|
}
|
|
|
|
CPLDebug("RAW", "Using direct IO implementation");
|
|
|
|
/* ==================================================================== */
|
|
/* Read data. */
|
|
/* ==================================================================== */
|
|
if ( eRWFlag == GF_Read )
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do we have overviews that would be appropriate to satisfy */
|
|
/* this request? */
|
|
/* -------------------------------------------------------------------- */
|
|
if( (nBufXSize < nXSize || nBufYSize < nYSize)
|
|
&& GetOverviewCount() > 0 )
|
|
{
|
|
if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
|
|
pData, nBufXSize, nBufYSize,
|
|
eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
|
|
return CE_None;
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
/* 1. Simplest case when we should get contiguous block */
|
|
/* of uninterleaved pixels. */
|
|
/* ==================================================================== */
|
|
if ( nXSize == GetXSize()
|
|
&& nXSize == nBufXSize
|
|
&& nYSize == nBufYSize
|
|
&& eBufType == eDataType
|
|
&& nPixelOffset == nBandDataSize
|
|
&& nPixelSpace == nBufDataSize
|
|
&& nLineSpace == nPixelSpace * nXSize )
|
|
{
|
|
vsi_l_offset nOffset = nImgOffset
|
|
+ (vsi_l_offset)nYOff * nLineOffset + nXOff;
|
|
if ( AccessBlock( nOffset,
|
|
nXSize * nYSize * nBandDataSize, pData ) != CE_None )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to read %d bytes at " CPL_FRMT_GUIB ".",
|
|
nXSize * nYSize * nBandDataSize, nOffset);
|
|
}
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
/* 2. Case when we need deinterleave and/or subsample data. */
|
|
/* ==================================================================== */
|
|
else
|
|
{
|
|
GByte *pabyData;
|
|
double dfSrcXInc, dfSrcYInc;
|
|
int iLine;
|
|
|
|
dfSrcXInc = (double)nXSize / nBufXSize;
|
|
dfSrcYInc = (double)nYSize / nBufYSize;
|
|
|
|
|
|
pabyData = (GByte *) CPLMalloc( nBytesToRW );
|
|
|
|
for ( iLine = 0; iLine < nBufYSize; iLine++ )
|
|
{
|
|
vsi_l_offset nOffset = nImgOffset
|
|
+ ((vsi_l_offset)nYOff
|
|
+ (vsi_l_offset)(iLine * dfSrcYInc)) * nLineOffset
|
|
+ nXOff * nPixelOffset;
|
|
if ( AccessBlock( nOffset,
|
|
nBytesToRW, pabyData ) != CE_None )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to read %d bytes at " CPL_FRMT_GUIB ".",
|
|
nBytesToRW, nOffset );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy data from disk buffer to user block buffer and subsample, */
|
|
/* if needed. */
|
|
/* -------------------------------------------------------------------- */
|
|
if ( nXSize == nBufXSize && nYSize == nBufYSize )
|
|
{
|
|
GDALCopyWords( pabyData, eDataType, nPixelOffset,
|
|
(GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
|
|
eBufType, nPixelSpace, nXSize );
|
|
}
|
|
else
|
|
{
|
|
int iPixel;
|
|
|
|
for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
|
|
{
|
|
GDALCopyWords( pabyData +
|
|
(vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
|
|
eDataType, nPixelOffset,
|
|
(GByte *)pData + (vsi_l_offset)iLine * nLineSpace +
|
|
(vsi_l_offset)iPixel * nPixelSpace,
|
|
eBufType, nPixelSpace, 1 );
|
|
}
|
|
}
|
|
|
|
if( psExtraArg->pfnProgress != NULL &&
|
|
!psExtraArg->pfnProgress(1.0 * (iLine + 1) / nBufYSize, "",
|
|
psExtraArg->pProgressData) )
|
|
{
|
|
CPLFree( pabyData );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
CPLFree( pabyData );
|
|
}
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
/* Write data. */
|
|
/* ==================================================================== */
|
|
else
|
|
{
|
|
int nBytesActuallyWritten;
|
|
|
|
/* ==================================================================== */
|
|
/* 1. Simplest case when we should write contiguous block */
|
|
/* of uninterleaved pixels. */
|
|
/* ==================================================================== */
|
|
if ( nXSize == GetXSize()
|
|
&& nXSize == nBufXSize
|
|
&& nYSize == nBufYSize
|
|
&& eBufType == eDataType
|
|
&& nPixelOffset == nBandDataSize
|
|
&& nPixelSpace == nBufDataSize
|
|
&& nLineSpace == nPixelSpace * nXSize )
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap the data buffer, if required. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
|
|
GDALSwapWords( ((GByte *) pData) + nWordSize,
|
|
nWordSize, nXSize, nPixelOffset );
|
|
}
|
|
else
|
|
GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Seek to the right block. */
|
|
/* -------------------------------------------------------------------- */
|
|
vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff;
|
|
if( Seek( nOffset, SEEK_SET) == -1 )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to seek to " CPL_FRMT_GUIB " to write data.\n",
|
|
nOffset);
|
|
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Write the block. */
|
|
/* -------------------------------------------------------------------- */
|
|
nBytesToRW = nXSize * nYSize * nBandDataSize;
|
|
|
|
nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
|
|
if( nBytesActuallyWritten < nBytesToRW )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to write %d bytes to file. %d bytes written",
|
|
nBytesToRW, nBytesActuallyWritten );
|
|
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap (if necessary) back into machine order so the */
|
|
/* buffer is still usable for reading purposes. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
|
|
GDALSwapWords( ((GByte *) pData) + nWordSize,
|
|
nWordSize, nXSize, nPixelOffset );
|
|
}
|
|
else
|
|
GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
|
|
}
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
/* 2. Case when we need deinterleave and/or subsample data. */
|
|
/* ==================================================================== */
|
|
else
|
|
{
|
|
GByte *pabyData;
|
|
double dfSrcXInc, dfSrcYInc;
|
|
vsi_l_offset nBlockOff;
|
|
int iLine;
|
|
|
|
dfSrcXInc = (double)nXSize / nBufXSize;
|
|
dfSrcYInc = (double)nYSize / nBufYSize;
|
|
|
|
pabyData = (GByte *) CPLMalloc( nBytesToRW );
|
|
|
|
for ( iLine = 0; iLine < nBufYSize; iLine++ )
|
|
{
|
|
nBlockOff = nImgOffset
|
|
+ ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine*dfSrcYInc))*nLineOffset
|
|
+ nXOff * nPixelOffset;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If the data for this band is completely contiguous we don't */
|
|
/* have to worry about pre-reading from disk. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nPixelOffset > nBandDataSize )
|
|
AccessBlock( nBlockOff, nBytesToRW, pabyData );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy data from user block buffer to disk buffer and subsample, */
|
|
/* if needed. */
|
|
/* -------------------------------------------------------------------- */
|
|
if ( nXSize == nBufXSize && nYSize == nBufYSize )
|
|
{
|
|
GDALCopyWords( (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
|
|
eBufType, nPixelSpace,
|
|
pabyData, eDataType, nPixelOffset, nXSize );
|
|
}
|
|
else
|
|
{
|
|
int iPixel;
|
|
|
|
for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
|
|
{
|
|
GDALCopyWords( (GByte *)pData+(vsi_l_offset)iLine*nLineSpace +
|
|
(vsi_l_offset)iPixel * nPixelSpace,
|
|
eBufType, nPixelSpace,
|
|
pabyData +
|
|
(vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
|
|
eDataType, nPixelOffset, 1 );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap the data buffer, if required. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
|
|
GDALSwapWords( ((GByte *) pabyData) + nWordSize,
|
|
nWordSize, nXSize, nPixelOffset );
|
|
}
|
|
else
|
|
GDALSwapWords( pabyData, nBandDataSize, nXSize,
|
|
nPixelOffset );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Seek to the right line in block. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( Seek( nBlockOff, SEEK_SET) == -1 )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to seek to " CPL_FRMT_GUIB " to read.\n",
|
|
nBlockOff );
|
|
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Write the line of block. */
|
|
/* -------------------------------------------------------------------- */
|
|
nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW );
|
|
if( nBytesActuallyWritten < nBytesToRW )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Failed to write %d bytes to file. %d bytes written",
|
|
nBytesToRW, nBytesActuallyWritten );
|
|
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Byte swap (if necessary) back into machine order so the */
|
|
/* buffer is still usable for reading purposes. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bNativeOrder && eDataType != GDT_Byte )
|
|
{
|
|
if( GDALDataTypeIsComplex( eDataType ) )
|
|
{
|
|
int nWordSize;
|
|
|
|
nWordSize = GDALGetDataTypeSize(eDataType)/16;
|
|
GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
|
|
GDALSwapWords( ((GByte *) pabyData) + nWordSize,
|
|
nWordSize, nXSize, nPixelOffset );
|
|
}
|
|
else
|
|
GDALSwapWords( pabyData, nBandDataSize, nXSize,
|
|
nPixelOffset );
|
|
}
|
|
|
|
}
|
|
|
|
bDirty = TRUE;
|
|
CPLFree( pabyData );
|
|
}
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Seek() */
|
|
/************************************************************************/
|
|
|
|
int RawRasterBand::Seek( vsi_l_offset nOffset, int nSeekMode )
|
|
|
|
{
|
|
if( bIsVSIL )
|
|
return VSIFSeekL( fpRawL, nOffset, nSeekMode );
|
|
else
|
|
return VSIFSeek( fpRaw, (long) nOffset, nSeekMode );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Read() */
|
|
/************************************************************************/
|
|
|
|
size_t RawRasterBand::Read( void *pBuffer, size_t nSize, size_t nCount )
|
|
|
|
{
|
|
if( bIsVSIL )
|
|
return VSIFReadL( pBuffer, nSize, nCount, fpRawL );
|
|
else
|
|
return VSIFRead( pBuffer, nSize, nCount, fpRaw );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Write() */
|
|
/************************************************************************/
|
|
|
|
size_t RawRasterBand::Write( void *pBuffer, size_t nSize, size_t nCount )
|
|
|
|
{
|
|
if( bIsVSIL )
|
|
return VSIFWriteL( pBuffer, nSize, nCount, fpRawL );
|
|
else
|
|
return VSIFWrite( pBuffer, nSize, nCount, fpRaw );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* StoreNoDataValue() */
|
|
/* */
|
|
/* This is a helper function for datasets to associate a no */
|
|
/* data value with this band, it isn't intended to be called by */
|
|
/* applications. */
|
|
/************************************************************************/
|
|
|
|
void RawRasterBand::StoreNoDataValue( double dfValue )
|
|
|
|
{
|
|
SetNoDataValue( dfValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetCategoryNames() */
|
|
/************************************************************************/
|
|
|
|
char **RawRasterBand::GetCategoryNames()
|
|
|
|
{
|
|
return papszCategoryNames;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetCategoryNames() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::SetCategoryNames( char ** papszNewNames )
|
|
|
|
{
|
|
CSLDestroy( papszCategoryNames );
|
|
papszCategoryNames = CSLDuplicate( papszNewNames );
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetColorTable() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::SetColorTable( GDALColorTable *poNewCT )
|
|
|
|
{
|
|
if( poCT )
|
|
delete poCT;
|
|
if( poNewCT == NULL )
|
|
poCT = NULL;
|
|
else
|
|
poCT = poNewCT->Clone();
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColorTable() */
|
|
/************************************************************************/
|
|
|
|
GDALColorTable *RawRasterBand::GetColorTable()
|
|
|
|
{
|
|
return poCT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetColorInterpretation() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
|
|
|
|
{
|
|
eInterp = eNewInterp;
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColorInterpretation() */
|
|
/************************************************************************/
|
|
|
|
GDALColorInterp RawRasterBand::GetColorInterpretation()
|
|
|
|
{
|
|
return eInterp;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetVirtualMemAuto() */
|
|
/************************************************************************/
|
|
|
|
CPLVirtualMem *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
|
|
int *pnPixelSpace,
|
|
GIntBig *pnLineSpace,
|
|
char **papszOptions )
|
|
{
|
|
CPLAssert(pnPixelSpace);
|
|
CPLAssert(pnLineSpace);
|
|
|
|
vsi_l_offset nSize = (vsi_l_offset)(nRasterYSize - 1) * nLineOffset +
|
|
(nRasterXSize - 1) * nPixelOffset + GDALGetDataTypeSize(eDataType) / 8;
|
|
|
|
if( !bIsVSIL || VSIFGetNativeFileDescriptorL(fpRawL) == NULL ||
|
|
!CPLIsVirtualMemFileMapAvailable() || (eDataType != GDT_Byte && !bNativeOrder) ||
|
|
(size_t)nSize != nSize || nPixelOffset < 0 || nLineOffset < 0 ||
|
|
CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
|
|
{
|
|
return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
|
|
pnLineSpace, papszOptions);
|
|
}
|
|
|
|
FlushCache();
|
|
|
|
CPLVirtualMem* pVMem = CPLVirtualMemFileMapNew(
|
|
fpRawL, nImgOffset, nSize,
|
|
(eRWFlag == GF_Write) ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
|
|
NULL, NULL);
|
|
if( pVMem == NULL )
|
|
{
|
|
return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
|
|
pnLineSpace, papszOptions);
|
|
}
|
|
else
|
|
{
|
|
*pnPixelSpace = nPixelOffset;
|
|
*pnLineSpace = nLineOffset;
|
|
return pVMem;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* RawDataset */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
|
|
/************************************************************************/
|
|
/* RawDataset() */
|
|
/************************************************************************/
|
|
|
|
RawDataset::RawDataset()
|
|
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~RawDataset() */
|
|
/************************************************************************/
|
|
|
|
RawDataset::~RawDataset()
|
|
|
|
{
|
|
/* It's pure virtual function but must be defined, even if empty. */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IRasterIO() */
|
|
/* */
|
|
/* Multi-band raster io handler. */
|
|
/************************************************************************/
|
|
|
|
CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
|
|
int nXOff, int nYOff, int nXSize, int nYSize,
|
|
void *pData, int nBufXSize, int nBufYSize,
|
|
GDALDataType eBufType,
|
|
int nBandCount, int *panBandMap,
|
|
GSpacing nPixelSpace, GSpacing nLineSpace,
|
|
GSpacing nBandSpace,
|
|
GDALRasterIOExtraArg* psExtraArg )
|
|
|
|
{
|
|
const char* pszInterleave;
|
|
|
|
/* The default GDALDataset::IRasterIO() implementation would go to */
|
|
/* BlockBasedRasterIO if the dataset is interleaved. However if the */
|
|
/* access pattern is compatible with DirectIO() we don't want to go */
|
|
/* BlockBasedRasterIO, but rather used our optimized path in RawRasterBand::IRasterIO() */
|
|
if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
|
|
(pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
|
|
EQUAL(pszInterleave, "PIXEL"))
|
|
{
|
|
int iBandIndex;
|
|
for(iBandIndex = 0; iBandIndex < nBandCount; iBandIndex ++ )
|
|
{
|
|
RawRasterBand* poBand = (RawRasterBand*) GetRasterBand(panBandMap[iBandIndex]);
|
|
if( !poBand->CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if( iBandIndex == nBandCount )
|
|
{
|
|
|
|
GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
|
|
void *pProgressDataGlobal = psExtraArg->pProgressData;
|
|
|
|
CPLErr eErr = CE_None;
|
|
for( iBandIndex = 0;
|
|
iBandIndex < nBandCount && eErr == CE_None;
|
|
iBandIndex++ )
|
|
{
|
|
GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
|
|
GByte *pabyBandData;
|
|
|
|
if (poBand == NULL)
|
|
{
|
|
eErr = CE_Failure;
|
|
break;
|
|
}
|
|
|
|
pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
|
|
|
|
psExtraArg->pfnProgress = GDALScaledProgress;
|
|
psExtraArg->pProgressData =
|
|
GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
|
|
1.0 * (iBandIndex + 1) / nBandCount,
|
|
pfnProgressGlobal,
|
|
pProgressDataGlobal );
|
|
|
|
eErr = poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
|
|
(void *) pabyBandData, nBufXSize, nBufYSize,
|
|
eBufType, nPixelSpace, nLineSpace, psExtraArg );
|
|
|
|
GDALDestroyScaledProgress( psExtraArg->pProgressData );
|
|
}
|
|
|
|
psExtraArg->pfnProgress = pfnProgressGlobal;
|
|
psExtraArg->pProgressData = pProgressDataGlobal;
|
|
|
|
return eErr;
|
|
}
|
|
}
|
|
|
|
return GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
|
|
pData, nBufXSize, nBufYSize, eBufType,
|
|
nBandCount, panBandMap,
|
|
nPixelSpace, nLineSpace, nBandSpace,
|
|
psExtraArg);
|
|
}
|