int QgsRelief::processRaster( QgsFeedback *feedback ) { //open input file int xSize, ySize; GDALDatasetH inputDataset = openInputFile( xSize, ySize ); if ( !inputDataset ) { return 1; //opening of input file failed } //output driver GDALDriverH outputDriver = openOutputDriver(); if ( !outputDriver ) { return 2; } GDALDatasetH outputDataset = openOutputFile( inputDataset, outputDriver ); if ( !outputDataset ) { return 3; //create operation on output file failed } //initialize dependency filters with cell sizes mHillshadeFilter285->setCellSizeX( mCellSizeX ); mHillshadeFilter285->setCellSizeY( mCellSizeY ); mHillshadeFilter285->setZFactor( mZFactor ); mHillshadeFilter300->setCellSizeX( mCellSizeX ); mHillshadeFilter300->setCellSizeY( mCellSizeY ); mHillshadeFilter300->setZFactor( mZFactor ); mHillshadeFilter315->setCellSizeX( mCellSizeX ); mHillshadeFilter315->setCellSizeY( mCellSizeY ); mHillshadeFilter315->setZFactor( mZFactor ); mSlopeFilter->setCellSizeX( mCellSizeX ); mSlopeFilter->setCellSizeY( mCellSizeY ); mSlopeFilter->setZFactor( mZFactor ); mAspectFilter->setCellSizeX( mCellSizeX ); mAspectFilter->setCellSizeY( mCellSizeY ); mAspectFilter->setZFactor( mZFactor ); //open first raster band for reading (operation is only for single band raster) GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset, 1 ); if ( !rasterBand ) { GDALClose( inputDataset ); GDALClose( outputDataset ); return 4; } mInputNodataValue = GDALGetRasterNoDataValue( rasterBand, nullptr ); mSlopeFilter->setInputNodataValue( mInputNodataValue ); mAspectFilter->setInputNodataValue( mInputNodataValue ); mHillshadeFilter285->setInputNodataValue( mInputNodataValue ); mHillshadeFilter300->setInputNodataValue( mInputNodataValue ); mHillshadeFilter315->setInputNodataValue( mInputNodataValue ); GDALRasterBandH outputRedBand = GDALGetRasterBand( outputDataset, 1 ); GDALRasterBandH outputGreenBand = GDALGetRasterBand( outputDataset, 2 ); GDALRasterBandH outputBlueBand = GDALGetRasterBand( outputDataset, 3 ); if ( !outputRedBand || !outputGreenBand || !outputBlueBand ) { GDALClose( inputDataset ); GDALClose( outputDataset ); return 5; } //try to set -9999 as nodata value GDALSetRasterNoDataValue( outputRedBand, -9999 ); GDALSetRasterNoDataValue( outputGreenBand, -9999 ); GDALSetRasterNoDataValue( outputBlueBand, -9999 ); mOutputNodataValue = GDALGetRasterNoDataValue( outputRedBand, nullptr ); mSlopeFilter->setOutputNodataValue( mOutputNodataValue ); mAspectFilter->setOutputNodataValue( mOutputNodataValue ); mHillshadeFilter285->setOutputNodataValue( mOutputNodataValue ); mHillshadeFilter300->setOutputNodataValue( mOutputNodataValue ); mHillshadeFilter315->setOutputNodataValue( mOutputNodataValue ); if ( ySize < 3 ) //we require at least three rows (should be true for most datasets) { GDALClose( inputDataset ); GDALClose( outputDataset ); return 6; } //keep only three scanlines in memory at a time float *scanLine1 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); float *scanLine2 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); float *scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); unsigned char *resultRedLine = ( unsigned char * ) CPLMalloc( sizeof( unsigned char ) * xSize ); unsigned char *resultGreenLine = ( unsigned char * ) CPLMalloc( sizeof( unsigned char ) * xSize ); unsigned char *resultBlueLine = ( unsigned char * ) CPLMalloc( sizeof( unsigned char ) * xSize ); bool resultOk; //values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values for ( int i = 0; i < ySize; ++i ) { if ( feedback ) { feedback->setProgress( 100.0 * i / static_cast< double >( ySize ) ); } if ( feedback && feedback->isCanceled() ) { break; } if ( i == 0 ) { //fill scanline 1 with (input) nodata for the values above the first row and feed scanline2 with the first row for ( int a = 0; a < xSize; ++a ) { scanLine1[a] = mInputNodataValue; } if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, scanLine2, xSize, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } } else { //normally fetch only scanLine3 and release scanline 1 if we move forward one row CPLFree( scanLine1 ); scanLine1 = scanLine2; scanLine2 = scanLine3; scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); } if ( i == ySize - 1 ) //fill the row below the bottom with nodata values { for ( int a = 0; a < xSize; ++a ) { scanLine3[a] = mInputNodataValue; } } else { if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, scanLine3, xSize, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } } for ( int j = 0; j < xSize; ++j ) { if ( j == 0 ) { resultOk = processNineCellWindow( &mInputNodataValue, &scanLine1[j], &scanLine1[j + 1], &mInputNodataValue, &scanLine2[j], \ &scanLine2[j + 1], &mInputNodataValue, &scanLine3[j], &scanLine3[j + 1], \ &resultRedLine[j], &resultGreenLine[j], &resultBlueLine[j] ); } else if ( j == xSize - 1 ) { resultOk = processNineCellWindow( &scanLine1[j - 1], &scanLine1[j], &mInputNodataValue, &scanLine2[j - 1], &scanLine2[j], \ &mInputNodataValue, &scanLine3[j - 1], &scanLine3[j], &mInputNodataValue, \ &resultRedLine[j], &resultGreenLine[j], &resultBlueLine[j] ); } else { resultOk = processNineCellWindow( &scanLine1[j - 1], &scanLine1[j], &scanLine1[j + 1], &scanLine2[j - 1], &scanLine2[j], \ &scanLine2[j + 1], &scanLine3[j - 1], &scanLine3[j], &scanLine3[j + 1], \ &resultRedLine[j], &resultGreenLine[j], &resultBlueLine[j] ); } if ( !resultOk ) { resultRedLine[j] = mOutputNodataValue; resultGreenLine[j] = mOutputNodataValue; resultBlueLine[j] = mOutputNodataValue; } } if ( GDALRasterIO( outputRedBand, GF_Write, 0, i, xSize, 1, resultRedLine, xSize, 1, GDT_Byte, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } if ( GDALRasterIO( outputGreenBand, GF_Write, 0, i, xSize, 1, resultGreenLine, xSize, 1, GDT_Byte, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } if ( GDALRasterIO( outputBlueBand, GF_Write, 0, i, xSize, 1, resultBlueLine, xSize, 1, GDT_Byte, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } } if ( feedback ) { feedback->setProgress( 100 ); } CPLFree( resultRedLine ); CPLFree( resultBlueLine ); CPLFree( resultGreenLine ); CPLFree( scanLine1 ); CPLFree( scanLine2 ); CPLFree( scanLine3 ); GDALClose( inputDataset ); if ( feedback && feedback->isCanceled() ) { //delete the dataset without closing (because it is faster) GDALDeleteDataset( outputDriver, mOutputFile.toUtf8().constData() ); return 7; } GDALClose( outputDataset ); return 0; }
int QgsNineCellFilter::processRaster( QProgressDialog* p ) { GDALAllRegister(); //open input file int xSize, ySize; GDALDatasetH inputDataset = openInputFile( xSize, ySize ); if ( inputDataset == NULL ) { return 1; //opening of input file failed } //output driver GDALDriverH outputDriver = openOutputDriver(); if ( outputDriver == 0 ) { return 2; } GDALDatasetH outputDataset = openOutputFile( inputDataset, outputDriver ); if ( outputDataset == NULL ) { return 3; //create operation on output file failed } //open first raster band for reading (operation is only for single band raster) GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset, 1 ); if ( rasterBand == NULL ) { GDALClose( inputDataset ); GDALClose( outputDataset ); return 4; } mInputNodataValue = GDALGetRasterNoDataValue( rasterBand, NULL ); GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset, 1 ); if ( outputRasterBand == NULL ) { GDALClose( inputDataset ); GDALClose( outputDataset ); return 5; } //try to set -9999 as nodata value GDALSetRasterNoDataValue( outputRasterBand, -9999 ); mOutputNodataValue = GDALGetRasterNoDataValue( outputRasterBand, NULL ); if ( ySize < 3 ) //we require at least three rows (should be true for most datasets) { GDALClose( inputDataset ); GDALClose( outputDataset ); return 6; } //keep only three scanlines in memory at a time float* scanLine1 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); float* scanLine2 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); float* scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); float* resultLine = ( float * ) CPLMalloc( sizeof( float ) * xSize ); if ( p ) { p->setMaximum( ySize ); } //values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values for ( int i = 0; i < ySize; ++i ) { if ( p ) { p->setValue( i ); } if ( p && p->wasCanceled() ) { break; } if ( i == 0 ) { //fill scanline 1 with (input) nodata for the values above the first row and feed scanline2 with the first row for ( int a = 0; a < xSize; ++a ) { scanLine1[a] = mInputNodataValue; } GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, scanLine2, xSize, 1, GDT_Float32, 0, 0 ); } else { //normally fetch only scanLine3 and release scanline 1 if we move forward one row CPLFree( scanLine1 ); scanLine1 = scanLine2; scanLine2 = scanLine3; scanLine3 = ( float * ) CPLMalloc( sizeof( float ) * xSize ); } if ( i == ySize - 1 ) //fill the row below the bottom with nodata values { for ( int a = 0; a < xSize; ++a ) { scanLine3[a] = mInputNodataValue; } } else { GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, scanLine3, xSize, 1, GDT_Float32, 0, 0 ); } for ( int j = 0; j < xSize; ++j ) { if ( j == 0 ) { resultLine[j] = processNineCellWindow( &mInputNodataValue, &scanLine1[j], &scanLine1[j+1], &mInputNodataValue, &scanLine2[j], \ &scanLine2[j+1], &mInputNodataValue, &scanLine3[j], &scanLine3[j+1] ); } else if ( j == xSize - 1 ) { resultLine[j] = processNineCellWindow( &scanLine1[j-1], &scanLine1[j], &mInputNodataValue, &scanLine2[j-1], &scanLine2[j], \ &mInputNodataValue, &scanLine3[j-1], &scanLine3[j], &mInputNodataValue ); } else { resultLine[j] = processNineCellWindow( &scanLine1[j-1], &scanLine1[j], &scanLine1[j+1], &scanLine2[j-1], &scanLine2[j], \ &scanLine2[j+1], &scanLine3[j-1], &scanLine3[j], &scanLine3[j+1] ); } } GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ); } if ( p ) { p->setValue( ySize ); } CPLFree( resultLine ); CPLFree( scanLine1 ); CPLFree( scanLine2 ); CPLFree( scanLine3 ); GDALClose( inputDataset ); if ( p && p->wasCanceled() ) { //delete the dataset without closing (because it is faster) GDALDeleteDataset( outputDriver, mOutputFile.toLocal8Bit().data() ); return 7; } GDALClose( outputDataset ); return 0; }