Skip to content

Commit

Permalink
Merge pull request #231 from homann/memcpy_malloc_fixes
Browse files Browse the repository at this point in the history
Memcpy malloc fixes, should remove some out of mem crashes. Downside, it is still slow... Also fixed a warning about missing copy ctor.
  • Loading branch information
homann committed Sep 13, 2012
2 parents 24a047d + e2e2792 commit d11fd92
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 14 deletions.
11 changes: 8 additions & 3 deletions src/core/qgsrasterdataprovider.cpp
Expand Up @@ -64,7 +64,7 @@ void QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle
return;

// Allocate memory for not projected source data
int mySize = dataTypeSize( bandNo ) / 8;
size_t mySize = dataTypeSize( bandNo ) / 8;
void *mySrcData = malloc( mySize * myProjector.srcRows() * myProjector.srcCols() );

time.restart();
Expand Down Expand Up @@ -101,6 +101,11 @@ void * QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle const & exten

// TODO: replace VSIMalloc, it is GDAL function
void * data = VSIMalloc( dataTypeSize( bandNo ) * width * height );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate data memory of % bytes" ).arg( dataTypeSize( bandNo ) * width * height ) );
return 0;
}
readBlock( bandNo, extent, width, height, data );

return data;
Expand Down Expand Up @@ -260,9 +265,9 @@ QString QgsRasterDataProvider::lastErrorFormat()
QByteArray QgsRasterDataProvider::noValueBytes( int theBandNo )
{
int type = dataType( theBandNo );
int size = dataTypeSize( theBandNo ) / 8;
size_t size = dataTypeSize( theBandNo ) / 8;
QByteArray ba;
ba.resize( size );
ba.resize(( int )size );
char * data = ba.data();
double noval = mNoDataValue[theBandNo-1];
unsigned char uc;
Expand Down
20 changes: 14 additions & 6 deletions src/core/qgsrasterprojector.cpp
Expand Up @@ -67,6 +67,7 @@ QgsRasterProjector::QgsRasterProjector()
}

QgsRasterProjector::QgsRasterProjector( const QgsRasterProjector &projector )
: QgsRasterInterface( 0 )
{
mSrcCRS = projector.mSrcCRS;
mDestCRS = projector.mDestCRS;
Expand Down Expand Up @@ -194,7 +195,7 @@ void QgsRasterProjector::calc()
}
// What is the maximum reasonable size of transformatio matrix?
// TODO: consider better when to break - ratio
if ( mCPRows * mCPCols > 0.0625 * mDestRows * mDestCols )
if ( mCPRows * mCPCols > 0.25 * mDestRows * mDestCols )
{
QgsDebugMsg( "Too large CP matrix" );
mApproximate = false;
Expand Down Expand Up @@ -679,13 +680,20 @@ void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent,

if ( !inputData ) return 0;

int pixelSize = mInput->typeSize( mInput->dataType( bandNo ) ) / 8;
size_t pixelSize = mInput->typeSize( mInput->dataType( bandNo ) ) / 8;

int inputSize = pixelSize * srcCols() * srcRows();
size_t inputSize = pixelSize * srcCols() * srcRows();

int outputSize = width * height * pixelSize;
size_t outputSize = width * height * pixelSize;
void * outputData = malloc( outputSize );

// Check for allcoation error
if ( ! outputData )
{
QgsDebugMsg( QString( "Couldn't malloc %1 bytes!" ).arg( outputSize ) );
free( inputData );
return 0;
}
// TODO: fill by transparent

int srcRow, srcCol;
Expand All @@ -694,8 +702,8 @@ void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent,
for ( int j = 0; j < width; ++j )
{
srcRowCol( i, j, &srcRow, &srcCol );
int srcIndex = pixelSize * ( srcRow * mSrcCols + srcCol );
int destIndex = pixelSize * ( i * width + j );
size_t srcIndex = pixelSize * ( srcRow * mSrcCols + srcCol );
size_t destIndex = pixelSize * ( i * width + j );

if ( srcIndex >= inputSize || destIndex >= outputSize ) continue; // should not happen

Expand Down
28 changes: 27 additions & 1 deletion src/core/raster/qgsmultibandcolorrenderer.cpp
Expand Up @@ -195,7 +195,17 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
bandData[*bandIt] = mInput->block( *bandIt, extent, width, height );
if ( !bandData[*bandIt] ) return 0;
if ( !bandData[*bandIt] )
{
// We should free the alloced mem from block().
QgsDebugMsg("No input band" );
bandIt--;
for ( ; bandIt != bands.constBegin(); bandIt-- )
{
VSIFree( bandData[*bandIt] );
}
return 0;
}
}

if ( mRedBand > 0 )
Expand All @@ -216,6 +226,17 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
}

QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
VSIFree( bandData[*bandIt] );
}
return 0;
}

QRgb* imageScanLine = 0;
int currentRasterPos = 0;
int redVal = 0;
Expand Down Expand Up @@ -334,6 +355,11 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
}

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
19 changes: 19 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Expand Up @@ -103,6 +103,12 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e

QgsRasterInterface::DataType rasterType = ( QgsRasterInterface::DataType )mInput->dataType( mBandNumber );
void* rasterData = mInput->block( bandNo, extent, width, height );
if ( ! rasterData )
{
QgsDebugMsg("No raster data!" );
return 0;
}

double currentOpacity = mOpacity;

//rendering is faster without considering user-defined transparency
Expand All @@ -120,6 +126,13 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
}

QRgb* imageScanLine = 0;
int val = 0;
int currentRasterPos = 0;
Expand Down Expand Up @@ -174,7 +187,13 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
}

VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
17 changes: 17 additions & 0 deletions src/core/raster/qgssinglebandcolordatarenderer.cpp
Expand Up @@ -62,9 +62,21 @@ void * QgsSingleBandColorDataRenderer::readBlock( int bandNo, QgsRectangle cons
bool hasTransparency = usesTransparency();

void* rasterData = mInput->block( bandNo, extent, width, height );
if ( ! rasterData )
{
QgsDebugMsg("No raster data!" );
return 0;
}

currentRasterPos = 0;
QImage img( width, height, QImage::Format_ARGB32 );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
}

uchar* scanLine = 0;
for ( int i = 0; i < height; ++i )
{
Expand All @@ -91,6 +103,11 @@ void * QgsSingleBandColorDataRenderer::readBlock( int bandNo, QgsRectangle cons
VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
17 changes: 17 additions & 0 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Expand Up @@ -89,6 +89,11 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
QgsRasterInterface::DataType rasterType = ( QgsRasterInterface::DataType )mInput->dataType( mBand );

void* rasterData = mInput->block( mBand, extent, width, height );
if ( ! rasterData )
{
QgsDebugMsg("No raster data!" );
return 0;
}

int red, green, blue;
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
Expand All @@ -107,6 +112,13 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
}

QRgb* imageScanLine = 0;
double val = 0;

Expand Down Expand Up @@ -156,6 +168,11 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
6 changes: 5 additions & 1 deletion src/providers/gdal/qgsgdalprovider.cpp
Expand Up @@ -520,7 +520,11 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,

// Allocate temporary block
char *tmpBlock = ( char * )malloc( dataSize * tmpWidth * tmpHeight );

if ( ! tmpBlock )
{
QgsDebugMsg( QString( "Coudn't allocate temporary buffer of %1 bytes" ).arg( dataSize * tmpWidth * tmpHeight ) );
return;
}
GDALRasterBandH gdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType type = ( GDALDataType )mGdalDataType[theBandNo-1];
CPLErrorReset();
Expand Down
5 changes: 5 additions & 0 deletions src/providers/wcs/qgswcsprovider.cpp
Expand Up @@ -537,6 +537,11 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
QgsDebugMsg( QString( "pixelSize = %1" ).arg( pixelSize ) );
int size = width * height * pixelSize;
void * tmpData = malloc( size );
if ( ! tmpData )
{
QgsDebugMsg( QString( "Couldn't allocate memory of %1 bytes" ).arg( size ) );
return;
}
GDALRasterIO( gdalBand, GF_Read, 0, 0, width, height, tmpData, width, height, ( GDALDataType ) mGdalDataType[bandNo-1], 0, 0 );
for ( int i = 0; i < pixelHeight; i++ )
{
Expand Down
10 changes: 7 additions & 3 deletions src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -959,16 +959,20 @@ void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
return;
}
QgsDebugMsg( QString( "image height = %1 bytesPerLine = %2" ).arg( image->height() ) . arg( image->bytesPerLine() ) ) ;
int myExpectedSize = pixelWidth * pixelHeight * 4;
int myImageSize = image->height() * image->bytesPerLine();
size_t myExpectedSize = pixelWidth * pixelHeight * 4;
size_t myImageSize = image->height() * image->bytesPerLine();
if ( myExpectedSize != myImageSize ) // should not happen
{
QgsMessageLog::logMessage( tr( "unexpected image size" ), tr( "WMS" ) );
return;
}

uchar * ptr = image->bits() ;
memcpy( block, ptr, myExpectedSize );
if ( ptr )
{
// If image is too large, ptr can be NULL
memcpy( block, ptr, myExpectedSize );
}
// do not delete the image, it is handled by draw()
//delete image;
}
Expand Down

0 comments on commit d11fd92

Please sign in to comment.