int makeGeotiff (struct deminfo *d0, char *outpath,int nodata) { GDALAllRegister (); GDALDataType band_type = GDT_Float32; int bands = 1; int dsn_xsize = (d0->highx - d0->lowx + 1); int dsn_ysize = (d0->highy - d0->lowy + 1); char **papszCreateOptions = NULL; papszCreateOptions = CSLSetNameValue (papszCreateOptions, "PROFILE", "GeoTIFF"); //papszCreateOptions = CSLSetNameValue( papszCreateOptions, "TFW", "YES" ); //papszCreateOptions = CSLSetNameValue (papszCreateOptions, "INTERLEAVE", "PIXEL"); //papszCreateOptions = CSLSetNameValue (papszCreateOptions, "TILED", "YES"); //papszCreateOptions = CSLSetNameValue (papszCreateOptions, "COMPRESS", "LZW"); GDALDriverH hDriver = GDALGetDriverByName ("GTiff"); GDALDatasetH hDsnDS = GDALCreate (hDriver, outpath, dsn_xsize, dsn_ysize, bands, band_type, papszCreateOptions); double dsnGeoTransform[6]; dsnGeoTransform[0] = d0->W; dsnGeoTransform[1] = (d0->E - d0->W) / dsn_xsize; dsnGeoTransform[2] = 0; dsnGeoTransform[3] = d0->N; dsnGeoTransform[4] = 0; dsnGeoTransform[5] = -1.0 * (d0->N - d0->S) / dsn_ysize; GDALSetGeoTransform (hDsnDS, dsnGeoTransform); char pszSRS_WKT[1024] = "GEOGCS[\"JGD2000\", DATUM[\"Japanese Geodetic Datum 2000\", SPHEROID[\"GRS 1980\", 6378137.0, 298.257222101, AUTHORITY[\"EPSG\",\"7019\"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],AUTHORITY[\"EPSG\",\"6612\"]], PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], UNIT[\"degree\", 0.017453292519943295], AXIS[\"Geodetic longitude\", EAST], AXIS[\"Geodetic latitude\", NORTH], AUTHORITY[\"EPSG\",\"4612\"]]"; GDALSetProjection (hDsnDS, pszSRS_WKT); GDALRasterBandH t_band = GDALGetRasterBand (hDsnDS, 1); if(nodata==1){ GDALSetRasterNoDataValue (t_band, -9999); } GDALRasterIO (t_band, GF_Write, 0, 0, dsn_xsize, dsn_ysize, d0->alti, dsn_xsize, dsn_ysize, band_type, 0, 0); CSLDestroy (papszCreateOptions); GDALClose (hDsnDS); return 0; }
void writeGeoTiffF(char * fileName, float * result, int nRow, int nCol, double xMin, double yMax, double cellSize) { GDALAllRegister(); OGRRegisterAll(); GDALDatasetH hDstDS; GDALDriverH hDriver; GDALRasterBandH hBand; double adfGeoTransform[6]; char *papszOptions[] = {"COMPRESS=LZW",NULL}; const char *pszFormat="GTiff"; if(NULL == (hDriver = GDALGetDriverByName(pszFormat))) { printf("ERROR: hDriver is null cannot output using GDAL\n"); exit(1); } hDstDS = GDALCreate(hDriver, fileName, nCol, nRow, 1, GDT_Float32, papszOptions); adfGeoTransform[0] = xMin; adfGeoTransform[1] = cellSize; adfGeoTransform[2] = 0; adfGeoTransform[3] = yMax; adfGeoTransform[4] = 0; adfGeoTransform[5] = -cellSize; GDALSetGeoTransform(hDstDS,adfGeoTransform); hBand=GDALGetRasterBand(hDstDS,1); GDALSetRasterNoDataValue(hBand,-1); GDALRasterIO(hBand, GF_Write, 0, 0, nCol, nRow, result, nCol, nRow, GDT_Float32, 0, 0 ); GDALClose(hDstDS); return; }
int QgsRasterCalculator::processCalculation( QProgressDialog* p ) { //prepare search string / tree QString errorString; QgsRasterCalcNode* calcNode = QgsRasterCalcNode::parseRasterCalcString( mFormulaString, errorString ); if ( !calcNode ) { //error return static_cast<int>( ParserError ); } QMap< QString, QgsRasterBlock* > inputBlocks; QVector<QgsRasterCalculatorEntry>::const_iterator it = mRasterEntries.constBegin(); for ( ; it != mRasterEntries.constEnd(); ++it ) { if ( !it->raster ) // no raster layer in entry { delete calcNode; qDeleteAll( inputBlocks ); return static_cast< int >( InputLayerError ); } QgsRasterBlock* block = nullptr; // if crs transform needed if ( it->raster->crs() != mOutputCrs ) { QgsRasterProjector proj; proj.setCRS( it->raster->crs(), mOutputCrs ); proj.setInput( it->raster->dataProvider() ); proj.setPrecision( QgsRasterProjector::Exact ); block = proj.block( it->bandNumber, mOutputRectangle, mNumOutputColumns, mNumOutputRows ); } else { block = it->raster->dataProvider()->block( it->bandNumber, mOutputRectangle, mNumOutputColumns, mNumOutputRows ); } if ( block->isEmpty() ) { delete block; delete calcNode; qDeleteAll( inputBlocks ); return static_cast<int>( MemoryError ); } inputBlocks.insert( it->ref, block ); } //open output dataset for writing GDALDriverH outputDriver = openOutputDriver(); if ( !outputDriver ) { return static_cast< int >( CreateOutputError ); } GDALDatasetH outputDataset = openOutputFile( outputDriver ); GDALSetProjection( outputDataset, mOutputCrs.toWkt().toLocal8Bit().data() ); GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset, 1 ); float outputNodataValue = -FLT_MAX; GDALSetRasterNoDataValue( outputRasterBand, outputNodataValue ); if ( p ) { p->setMaximum( mNumOutputRows ); } QgsRasterMatrix resultMatrix; resultMatrix.setNodataValue( outputNodataValue ); //read / write line by line for ( int i = 0; i < mNumOutputRows; ++i ) { if ( p ) { p->setValue( i ); } if ( p && p->wasCanceled() ) { break; } if ( calcNode->calculate( inputBlocks, resultMatrix, i ) ) { bool resultIsNumber = resultMatrix.isNumber(); float* calcData = new float[mNumOutputColumns]; for ( int j = 0; j < mNumOutputColumns; ++j ) { calcData[j] = ( float )( resultIsNumber ? resultMatrix.number() : resultMatrix.data()[j] ); } //write scanline to the dataset if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, mNumOutputColumns, 1, calcData, mNumOutputColumns, 1, GDT_Float32, 0, 0 ) != CE_None ) { qWarning( "RasterIO error!" ); } delete[] calcData; } } if ( p ) { p->setValue( mNumOutputRows ); } //close datasets and release memory delete calcNode; qDeleteAll( inputBlocks ); inputBlocks.clear(); if ( p && p->wasCanceled() ) { //delete the dataset without closing (because it is faster) GDALDeleteDataset( outputDriver, TO8F( mOutputFile ) ); return static_cast< int >( Cancelled ); } GDALClose( outputDataset ); return static_cast< int >( Success ); }
QgsRasterCalculator::Result QgsRasterCalculator::processCalculation( QgsFeedback *feedback ) { mLastError.clear(); //prepare search string / tree std::unique_ptr< QgsRasterCalcNode > calcNode( QgsRasterCalcNode::parseRasterCalcString( mFormulaString, mLastError ) ); if ( !calcNode ) { //error return ParserError; } // Check input layers and bands for ( const auto &entry : qgis::as_const( mRasterEntries ) ) { if ( !entry.raster ) // no raster layer in entry { mLastError = QObject::tr( "No raster layer for entry %1" ).arg( entry.ref ); return InputLayerError; } if ( entry.bandNumber <= 0 || entry.bandNumber > entry.raster->bandCount() ) { mLastError = QObject::tr( "Band number %1 is not valid for entry %2" ).arg( entry.bandNumber ).arg( entry.ref ); return BandError; } } #ifdef HAVE_OPENCL // Check for matrix nodes, GPU implementation does not support them QList<const QgsRasterCalcNode *> nodeList; if ( QgsOpenClUtils::enabled() && QgsOpenClUtils::available() && calcNode->findNodes( QgsRasterCalcNode::Type::tMatrix ).isEmpty() ) return processCalculationGPU( std::move( calcNode ), feedback ); #endif //open output dataset for writing GDALDriverH outputDriver = openOutputDriver(); if ( !outputDriver ) { mLastError = QObject::tr( "Could not obtain driver for %1" ).arg( mOutputFormat ); return CreateOutputError; } gdal::dataset_unique_ptr outputDataset( openOutputFile( outputDriver ) ); if ( !outputDataset ) { mLastError = QObject::tr( "Could not create output %1" ).arg( mOutputFile ); return CreateOutputError; } GDALSetProjection( outputDataset.get(), mOutputCrs.toWkt().toLocal8Bit().data() ); GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 ); float outputNodataValue = -FLT_MAX; GDALSetRasterNoDataValue( outputRasterBand, outputNodataValue ); // Check if we need to read the raster as a whole (which is memory inefficient // and not interruptable by the user) by checking if any raster matrix nodes are // in the expression bool requiresMatrix = ! calcNode->findNodes( QgsRasterCalcNode::Type::tMatrix ).isEmpty(); // Take the fast route (process one line at a time) if we can if ( ! requiresMatrix ) { // Map of raster names -> blocks std::map<QString, std::unique_ptr<QgsRasterBlock>> inputBlocks; std::map<QString, QgsRasterCalculatorEntry> uniqueRasterEntries; for ( const auto &r : calcNode->findNodes( QgsRasterCalcNode::Type::tRasterRef ) ) { QString layerRef( r->toString().remove( 0, 1 ) ); layerRef.chop( 1 ); if ( ! inputBlocks.count( layerRef ) ) { for ( const auto &ref : mRasterEntries ) { if ( ref.ref == layerRef ) { uniqueRasterEntries[layerRef] = ref; inputBlocks[layerRef ] = qgis::make_unique<QgsRasterBlock>(); } } } } //read / write line by line QMap<QString, QgsRasterBlock * > _rasterData; // Cast to float std::vector<float> castedResult; castedResult.reserve( static_cast<size_t>( mNumOutputColumns ) ); auto rowHeight = mOutputRectangle.height() / mNumOutputRows; for ( size_t row = 0; row < static_cast<size_t>( mNumOutputRows ); ++row ) { if ( feedback ) { feedback->setProgress( 100.0 * static_cast< double >( row ) / mNumOutputRows ); } if ( feedback && feedback->isCanceled() ) { break; } // Calculates the rect for a single row read QgsRectangle rect( mOutputRectangle ); rect.setYMaximum( rect.yMaximum() - rowHeight * row ); rect.setYMinimum( rect.yMaximum() - rowHeight ); // Read rows into input blocks for ( auto &layerRef : inputBlocks ) { QgsRasterCalculatorEntry ref = uniqueRasterEntries[layerRef.first]; if ( uniqueRasterEntries[layerRef.first].raster->crs() != mOutputCrs ) { QgsRasterProjector proj; proj.setCrs( ref.raster->crs(), mOutputCrs ); proj.setInput( ref.raster->dataProvider() ); proj.setPrecision( QgsRasterProjector::Exact ); layerRef.second.reset( proj.block( ref.bandNumber, rect, mNumOutputColumns, 1 ) ); } else { inputBlocks[layerRef.first].reset( ref.raster->dataProvider()->block( ref.bandNumber, rect, mNumOutputColumns, 1 ) ); } } QgsRasterMatrix resultMatrix; resultMatrix.setNodataValue( outputNodataValue ); _rasterData.clear(); for ( const auto &layerRef : inputBlocks ) { _rasterData.insert( layerRef.first, inputBlocks[layerRef.first].get() ); } if ( calcNode->calculate( _rasterData, resultMatrix, 0 ) ) { // write scanline to the dataset for ( size_t i = 0; i < static_cast<size_t>( mNumOutputColumns ); i++ ) { castedResult[i] = static_cast<float>( resultMatrix.data()[i] ); } if ( GDALRasterIO( outputRasterBand, GF_Write, 0, row, mNumOutputColumns, 1, castedResult.data(), mNumOutputColumns, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( QStringLiteral( "RasterIO error!" ) ); } } } if ( feedback ) { feedback->setProgress( 100.0 ); } } else // Original code (memory inefficient route) { QMap< QString, QgsRasterBlock * > inputBlocks; QVector<QgsRasterCalculatorEntry>::const_iterator it = mRasterEntries.constBegin(); for ( ; it != mRasterEntries.constEnd(); ++it ) { std::unique_ptr< QgsRasterBlock > block; // if crs transform needed if ( it->raster->crs() != mOutputCrs ) { QgsRasterProjector proj; proj.setCrs( it->raster->crs(), mOutputCrs ); proj.setInput( it->raster->dataProvider() ); proj.setPrecision( QgsRasterProjector::Exact ); QgsRasterBlockFeedback *rasterBlockFeedback = new QgsRasterBlockFeedback(); QObject::connect( feedback, &QgsFeedback::canceled, rasterBlockFeedback, &QgsRasterBlockFeedback::cancel ); block.reset( proj.block( it->bandNumber, mOutputRectangle, mNumOutputColumns, mNumOutputRows, rasterBlockFeedback ) ); if ( rasterBlockFeedback->isCanceled() ) { qDeleteAll( inputBlocks ); return Canceled; } } else { block.reset( it->raster->dataProvider()->block( it->bandNumber, mOutputRectangle, mNumOutputColumns, mNumOutputRows ) ); } if ( block->isEmpty() ) { mLastError = QObject::tr( "Could not allocate required memory for %1" ).arg( it->ref ); qDeleteAll( inputBlocks ); return MemoryError; } inputBlocks.insert( it->ref, block.release() ); } QgsRasterMatrix resultMatrix; resultMatrix.setNodataValue( outputNodataValue ); //read / write line by line for ( int i = 0; i < mNumOutputRows; ++i ) { if ( feedback ) { feedback->setProgress( 100.0 * static_cast< double >( i ) / mNumOutputRows ); } if ( feedback && feedback->isCanceled() ) { break; } if ( calcNode->calculate( inputBlocks, resultMatrix, i ) ) { bool resultIsNumber = resultMatrix.isNumber(); float *calcData = new float[mNumOutputColumns]; for ( int j = 0; j < mNumOutputColumns; ++j ) { calcData[j] = ( float )( resultIsNumber ? resultMatrix.number() : resultMatrix.data()[j] ); } //write scanline to the dataset if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, mNumOutputColumns, 1, calcData, mNumOutputColumns, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( QStringLiteral( "RasterIO error!" ) ); } delete[] calcData; } } if ( feedback ) { feedback->setProgress( 100.0 ); } //close datasets and release memory calcNode.reset(); qDeleteAll( inputBlocks ); inputBlocks.clear(); } if ( feedback && feedback->isCanceled() ) { //delete the dataset without closing (because it is faster) gdal::fast_delete_and_close( outputDataset, outputDriver, mOutputFile ); return Canceled; } return Success; }
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; }
/* actual raster band export * returns 0 on success * -1 on raster data read/write error * */ int export_band(GDALDatasetH hMEMDS, int band, const char *name, const char *mapset, struct Cell_head *cellhead, RASTER_MAP_TYPE maptype, double nodataval, int suppress_main_colortable) { struct Colors sGrassColors; GDALColorTableH hCT; int iColor; int bHaveMinMax; double dfCellMin; double dfCellMax; struct FPRange sRange; int fd; int cols = cellhead->cols; int rows = cellhead->rows; int ret = 0; char value[200]; /* Open GRASS raster */ fd = Rast_open_old(name, mapset); /* Get raster band */ GDALRasterBandH hBand = GDALGetRasterBand(hMEMDS, band); if (hBand == NULL) { G_warning(_("Unable to get raster band")); return -1; } /* Get min/max values. */ if (Rast_read_fp_range(name, mapset, &sRange) == -1) { bHaveMinMax = FALSE; } else { bHaveMinMax = TRUE; Rast_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax); } sprintf(value, "GRASS GIS %s", GRASS_VERSION_NUMBER); GDALSetMetadataItem(hBand, "Generated_with", value, NULL); /* use default color rules if no color rules are given */ if (Rast_read_colors(name, mapset, &sGrassColors) >= 0) { int maxcolor, i; CELL min, max; char key[200]; int rcount; Rast_get_c_color_range(&min, &max, &sGrassColors); if (bHaveMinMax) { if (max < dfCellMax) { maxcolor = max; } else { maxcolor = (int)ceil(dfCellMax); } if (maxcolor > GRASS_MAX_COLORS) { maxcolor = GRASS_MAX_COLORS; G_warning("Too many values, color table cut to %d entries", maxcolor); } } else { if (max < GRASS_MAX_COLORS) { maxcolor = max; } else { maxcolor = GRASS_MAX_COLORS; G_warning("Too many values, color table set to %d entries", maxcolor); } } rcount = Rast_colors_count(&sGrassColors); G_debug(3, "dfCellMin: %f, dfCellMax: %f, maxcolor: %d", dfCellMin, dfCellMax, maxcolor); if (!suppress_main_colortable) { hCT = GDALCreateColorTable(GPI_RGB); for (iColor = 0; iColor <= maxcolor; iColor++) { int nRed, nGreen, nBlue; GDALColorEntry sColor; if (Rast_get_c_color(&iColor, &nRed, &nGreen, &nBlue, &sGrassColors)) { sColor.c1 = nRed; sColor.c2 = nGreen; sColor.c3 = nBlue; sColor.c4 = 255; G_debug(3, "Rast_get_c_color: Y, rcount %d, nRed %d, nGreen %d, nBlue %d", rcount, nRed, nGreen, nBlue); GDALSetColorEntry(hCT, iColor, &sColor); } else { sColor.c1 = 0; sColor.c2 = 0; sColor.c3 = 0; sColor.c4 = 0; G_debug(3, "Rast_get_c_color: N, rcount %d, nRed %d, nGreen %d, nBlue %d", rcount, nRed, nGreen, nBlue); GDALSetColorEntry(hCT, iColor, &sColor); } } GDALSetRasterColorTable(hBand, hCT); } if (rcount > 0) { /* Create metadata entries for color table rules */ sprintf(value, "%d", rcount); GDALSetMetadataItem(hBand, "COLOR_TABLE_RULES_COUNT", value, NULL); } /* Add the rules in reverse order */ /* This can cause a GDAL warning with many rules, something like * Warning 1: Lost metadata writing to GeoTIFF ... too large to fit in tag. */ for (i = rcount - 1; i >= 0; i--) { DCELL val1, val2; unsigned char r1, g1, b1, r2, g2, b2; Rast_get_fp_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, &sGrassColors, i); sprintf(key, "COLOR_TABLE_RULE_RGB_%d", rcount - i - 1); sprintf(value, "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1, r2, g2, b2); GDALSetMetadataItem(hBand, key, value, NULL); } } /* Create GRASS raster buffer */ void *bufer = Rast_allocate_buf(maptype); if (bufer == NULL) { G_warning(_("Unable to allocate buffer for reading raster map")); return -1; } /* the following routine must be kept identical to exact_checks */ /* Copy data form GRASS raster to GDAL raster */ int row, col; int n_nulls = 0; /* Better use selected GDAL datatype instead of * the best match with GRASS raster map types ? */ if (maptype == FCELL_TYPE) { /* Source datatype understandable by GDAL */ GDALDataType datatype = GDT_Float32; FCELL fnullval = (FCELL) nodataval; G_debug(1, "FCELL nodata val: %f", fnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_f_null_value(&((FCELL *) bufer)[col])) { ((FCELL *) bufer)[col] = fnullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } else if (maptype == DCELL_TYPE) { GDALDataType datatype = GDT_Float64; DCELL dnullval = (DCELL) nodataval; G_debug(1, "DCELL nodata val: %f", dnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_d_null_value(&((DCELL *) bufer)[col])) { ((DCELL *) bufer)[col] = dnullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } else { GDALDataType datatype = GDT_Int32; CELL inullval = (CELL) nodataval; G_debug(1, "CELL nodata val: %d", inullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_c_null_value(&((CELL *) bufer)[col])) { ((CELL *) bufer)[col] = inullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } Rast_close(fd); G_free(bufer); return ret; }
int main (int argc, const char *argv[]) { GDALDriverH hDriver; double adfGeoTransform[6]; GDALDatasetH in_Dataset; GDALDatasetH out_Dataset; double *data_scan_line; char *out_scan_line; int nBlockXSize, nBlockYSize; int bGotMin, bGotMax; int bands; int xsize; double lower_fiddle, upper_fiddle; double adfMinMax[2]; /* These are hard coded for now - need to figure out a better way to handle this.. */ double palette_in[256] = { 0.0, 1.00011, 1.9999649999999998, 3.000075, 3.9999299999999995, 5.00004, 5.999895, 7.000005, 8.000115, 8.99997, 10.00008, 10.999935, 12.000044999999998, 12.9999, 14.00001, 15.00012, 15.999975, 17.000085000000002, 17.99994, 19.00005, 19.999905000000002, 21.000014999999998, 22.000125, 22.99998, 24.000089999999997, 24.999945, 26.000055, 26.99991, 28.00002, 28.999875000000003, 29.999985, 31.000094999999998, 31.99995, 33.00006, 33.999915, 35.000024999999994, 35.99988, 36.999990000000004, 38.0001, 38.999955, 40.000065, 40.99992, 42.000029999999995, 42.999885, 43.999995000000006, 45.000105, 45.99996, 47.00007, 47.999925000000005, 49.000035, 49.99989, 51.0, 52.00011, 52.999965, 54.000075, 54.99993, 56.00004, 56.999895, 58.000004999999994, 59.000115, 59.99997, 61.000080000000004, 61.999935, 63.000045, 63.9999, 65.00001, 66.00012, 66.999975, 68.000085, 68.99994, 70.00004999999999, 70.999905, 72.000015, 73.000125, 73.99998000000001, 75.00009, 75.999945, 77.00005499999999, 77.99991, 79.00002, 79.99987499999999, 80.99998500000001, 82.000095, 82.99995, 84.00005999999999, 84.999915, 86.00002500000001, 86.99987999999999, 87.99999000000001, 89.0001, 89.999955, 91.00006499999999, 91.99992, 93.00003, 93.99988499999999, 94.999995, 96.000105, 96.99996, 98.00007, 98.999925, 100.000035, 100.99989, 102.0, 103.00011, 103.999965, 105.000075, 105.99993, 107.00004, 107.999895, 109.000005, 110.00011500000001, 110.99997, 112.00008, 112.99993500000001, 114.000045, 114.9999, 116.00000999999999, 117.00012, 117.999975, 119.000085, 119.99994, 121.00005, 121.999905, 123.00001499999999, 124.000125, 124.99998000000001, 126.00009, 126.999945, 128.000055, 128.99991, 130.00002, 130.999875, 131.99998499999998, 133.000095, 133.99995, 135.00006, 135.999915, 137.00002500000002, 137.99988, 138.99999, 140.00009999999997, 140.999955, 142.000065, 142.99991999999997, 144.00003, 144.999885, 145.99999499999998, 147.000105, 147.99996000000002, 149.00007, 149.999925, 151.00003500000003, 151.99989, 153.0, 154.00010999999998, 154.999965, 156.000075, 156.99992999999998, 158.00004, 158.999895, 160.000005, 161.000115, 161.99997000000002, 163.00008, 163.999935, 165.000045, 165.9999, 167.00001, 168.00011999999998, 168.999975, 170.000085, 170.99993999999998, 172.00005000000002, 172.999905, 174.000015, 175.000125, 175.99998000000002, 177.00009, 177.999945, 179.00005499999997, 179.99991, 181.00002, 181.999875, 182.999985, 184.00009500000002, 184.99994999999998, 186.00006, 186.99991500000002, 188.000025, 188.99988, 189.99999, 191.0001, 191.999955, 193.00006499999998, 193.99992, 195.00003, 195.99988499999998, 196.999995, 198.00010500000002, 198.99996, 200.00007, 200.99992500000002, 202.000035, 202.99989, 204.0, 205.00011, 205.999965, 207.00007499999998, 207.99993, 209.00004, 209.99989499999998, 211.00000500000002, 212.000115, 212.99997, 214.00008, 214.999935, 216.000045, 216.9999, 218.00001, 219.00012, 219.999975, 221.00008499999998, 221.99994, 223.00005000000002, 223.99990499999998, 225.00001500000002, 226.000125, 226.99998, 228.00009, 228.999945, 230.000055, 230.99991, 232.00001999999998, 232.999875, 233.999985, 235.000095, 235.99995, 237.00006, 237.999915, 239.000025, 239.99988, 240.99999, 242.0001, 242.999955, 244.000065, 244.99992, 246.00002999999998, 246.999885, 247.999995, 249.000105, 249.99996000000002, 251.00007, 251.999925, 253.000035, 253.99989, 255.0 }; double palette_out[256] = { 0.0, 0.042075, 0.08415, 0.126225, 0.169065, 0.21216, 0.255765, 0.29988, 0.345015, 0.390915, 0.437835, 0.48602999999999996, 0.5352450000000001, 0.58599, 0.63801, 0.69156, 0.7468950000000001, 0.804015, 0.8629199999999999, 0.9238649999999999, 0.98685, 1.05213, 1.119705, 1.18983, 1.26225, 1.337475, 1.415505, 1.49634, 1.580235, 1.6674449999999998, 1.75746, 1.851045, 1.9482, 2.04867, 2.152965, 2.2608300000000003, 2.3727750000000003, 2.4885450000000002, 2.6083950000000002, 2.73258, 2.8611000000000004, 2.993955, 3.1313999999999997, 3.27369, 3.42057, 3.572295, 3.72912, 3.891045, 4.05807, 4.23045, 4.408440000000001, 4.591785, 4.780995, 4.975815, 5.1765, 5.38305, 5.595975, 5.8150200000000005, 6.040185, 6.27198, 6.510405, 6.755205, 7.007145, 7.265715, 7.53117, 7.8040199999999995, 8.084010000000001, 8.37114, 8.66592, 8.968095, 9.27792, 9.59565, 9.92103, 10.25457, 10.596015, 10.945875, 11.30415, 11.670585, 12.04569, 12.429465, 12.82191, 13.223279999999999, 13.63383, 14.053305, 14.48196, 14.919794999999999, 15.36732, 15.82428, 16.29093, 16.767270000000003, 17.253555, 17.749785, 18.256215, 18.925845, 19.456245000000003, 19.99863, 20.552745, 21.11859, 21.696165, 22.285725, 22.887014999999998, 23.500035, 24.125295, 24.762285, 25.411260000000002, 26.071965, 26.74491, 27.42984, 28.12701, 28.835910000000002, 29.55705, 30.29043, 31.035795, 31.7934, 32.56299, 33.345075, 34.139145, 34.94571, 35.764514999999996, 36.595305, 37.438845, 38.294625, 39.162645, 40.04316, 40.935915, 41.84142, 42.759165, 43.68966, 44.632394999999995, 45.58788, 46.55586, 47.536335, 48.529560000000004, 49.535535, 50.554005000000004, 51.58497, 52.62894, 53.68566, 54.75513, 55.837095, 56.932064999999994, 58.040040000000005, 59.160765, 60.294239999999995, 61.44072, 62.59995000000001, 63.772439999999996, 64.95768000000001, 66.15592500000001, 67.36743, 68.591685, 69.82919999999999, 71.07972, 72.343245, 73.620285, 74.910075, 76.21337999999999, 77.52968999999999, 78.85926, 80.20209, 81.55843499999999, 82.927785, 84.31065, 85.66419, 87.10264500000001, 88.611225, 90.18712500000001, 91.82779500000001, 93.52992, 95.291205, 97.108845, 98.979525, 100.90095, 102.87006, 104.884305, 106.94037, 109.03596, 111.16827, 113.33424000000001, 115.531065, 117.756195, 120.00657, 122.27964, 124.572345, 126.88213499999999, 129.20595, 131.54124, 133.8852, 136.23477, 138.58714500000002, 140.939775, 143.289855, 145.63458, 147.97089, 150.296235, 152.60781, 154.902555, 157.17817499999998, 159.431355, 161.65929, 163.859685, 166.02948, 168.165615, 170.26554, 172.32645, 174.34554, 176.320005, 178.24704, 180.292905, 182.130945, 183.953685, 185.76138, 187.554285, 189.33291, 191.09751, 192.84834, 194.58591, 196.310475, 198.02229, 199.72161, 201.4092, 203.084805, 204.74944499999998, 206.402865, 208.04557499999999, 209.67808499999998, 211.30065, 212.913525, 214.516965, 216.11148, 217.69758000000002, 219.27501, 220.84479, 222.406665, 223.9614, 225.50924999999998, 227.05047000000002, 228.585315, 230.114295, 231.63766500000003, 233.15568000000002, 234.66885000000002, 236.17743, 237.681675, 239.18184, 240.67869, 242.172225, 243.66295499999998, 245.15088, 246.636765, 248.12061000000003, 249.602925, 251.083965, 252.56424, 254.04375, 255.0 }; GDALAllRegister (); /* ussage.. */ if (argc != 3) ussage (); /* Set cache to something reasonable.. - 1/2 gig */ CPLSetConfigOption ("GDAL_CACHEMAX", "512"); /* open datasets.. */ in_Dataset = GDAL_open_read (argv[1]); out_Dataset = make_me_a_sandwitch (&in_Dataset, argv[2]); /* Basic info on source dataset.. */ GDALGetBlockSize (GDALGetRasterBand (in_Dataset, 1), &nBlockXSize, &nBlockYSize); printf ("Block=%dx%d Type=%s, ColorInterp=%s\n", nBlockXSize, nBlockYSize, GDALGetDataTypeName (GDALGetRasterDataType (GDALGetRasterBand (in_Dataset, 1))), GDALGetColorInterpretationName (GDALGetRasterColorInterpretation (GDALGetRasterBand (in_Dataset, 1)))); /* Loop though bands, scaling the data.. */ xsize = GDALGetRasterXSize (in_Dataset); data_scan_line = (double *) CPLMalloc (sizeof (double) * xsize); out_scan_line = (char *) CPLMalloc (sizeof (char) * xsize); for (bands = 1; bands <= GDALGetRasterCount (in_Dataset); bands++) { int x; double min = 9999999.0, max = 0.0; /* probibly a better way to set these.. */ double dmin, dmax, middle; GDALRasterBandH data_band, out_band; int y_index = 0; data_band = GDALGetRasterBand (in_Dataset, bands); out_band = GDALGetRasterBand (out_Dataset, bands); /* Set nodata for that band */ GDALSetRasterNoDataValue (out_band, 0.0); /*Find Min,Max, required for scaling */ for (y_index = 0; y_index < GDALGetRasterYSize (in_Dataset); y_index++) { /* Read data.. */ GDALRasterIO (data_band, GF_Read, 0, y_index, xsize, 1, data_scan_line, xsize, 1, GDT_Float64, 0, 0); for (x = 0; x < xsize; x++) { if (data_scan_line[x] < MAX_MODIS && data_scan_line[x] > MIN_VALUE) { if (data_scan_line[x] > max) max = data_scan_line[x]; else if (data_scan_line[x] < min) min = data_scan_line[x]; } } } dmax = (double) max; dmin = (double) min; printf ("Info: For Band %d -> Min=%g,Max=%g\n", bands, dmin, dmax); for (y_index = 0; y_index < GDALGetRasterYSize (in_Dataset); y_index++) { double scaled; /* Read data.. */ GDALRasterIO (data_band, GF_Read, 0, y_index, xsize, 1, data_scan_line, xsize, 1, GDT_Float64, 0, 0); /* scale each .. */ for (x = 0; x < xsize; x++) { out_scan_line[x] = scale (palette_in, palette_out, data_scan_line[x], dmin, dmax); } /* now write out band.. */ GDALRasterIO (out_band, GF_Write, 0, y_index, xsize, 1, out_scan_line, xsize, 1, GDT_Byte, 0, 0); } } /* close file, and we are done. */ GDALClose (out_Dataset); }
// Slot called when the menu item is triggered // If you created more menu items / toolbar buttons in initiGui, you should // create a separate handler for each action - this single run() method will // not be enough void Heatmap::run() { HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings ); //check that dialog found a suitable vector layer if ( !d.inputVectorLayer() ) { mQGisIface->messageBar()->pushMessage( tr( "Layer not found" ), tr( "The heatmap plugin requires at least one point vector layer" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() ); return; } if ( d.exec() != QDialog::Accepted ) { return; } QgsVectorLayer* inputLayer = d.inputVectorLayer(); // Get the required data from the dialog QgsRectangle myBBox = d.bbox(); int columns = d.columns(); int rows = d.rows(); double cellsize = d.cellSizeX(); // or d.cellSizeY(); both have the same value mDecay = d.decayRatio(); KernelShape kernelShape = d.kernelShape(); OutputValues valueType = d.outputValues(); //is input layer multipoint? bool isMultiPoint = inputLayer->wkbType() == Qgis::WKBMultiPoint || inputLayer->wkbType() == Qgis::WKBMultiPoint25D; // Getting the rasterdataset in place GDALAllRegister(); GDALDriverH myDriver = GDALGetDriverByName( d.outputFormat().toUtf8() ); if ( !myDriver ) { mQGisIface->messageBar()->pushMessage( tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ), QgsMessageBar::WARNING, mQGisIface->messageTimeout() ); return; } double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize }; GDALDatasetH emptyDataset = GDALCreate( myDriver, d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, nullptr ); GDALSetGeoTransform( emptyDataset, geoTransform ); // Set the projection on the raster destination to match the input layer GDALSetProjection( emptyDataset, inputLayer->crs().toWkt().toLocal8Bit().data() ); GDALRasterBandH poBand = GDALGetRasterBand( emptyDataset, 1 ); GDALSetRasterNoDataValue( poBand, NO_DATA ); float* line = ( float * ) CPLMalloc( sizeof( float ) * columns ); for ( int i = 0; i < columns ; i++ ) { line[i] = NO_DATA; } // Write the empty raster for ( int i = 0; i < rows ; i++ ) { if ( GDALRasterIO( poBand, GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } } CPLFree( line ); //close the dataset GDALClose( emptyDataset ); // open the raster in GA_Update mode GDALDatasetH heatmapDS = GDALOpen( TO8F( d.outputFilename() ), GA_Update ); if ( !heatmapDS ) { mQGisIface->messageBar()->pushMessage( tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ), QgsMessageBar::WARNING ); return; } poBand = GDALGetRasterBand( heatmapDS, 1 ); QgsAttributeList myAttrList; int rField = 0; int wField = 0; // Handle different radius options double radius; double radiusToMapUnits = 1; int myBuffer = 0; if ( d.variableRadius() ) { rField = d.radiusField(); myAttrList.append( rField ); QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) ); // If not using map units, then calculate a conversion factor to convert the radii to map units if ( d.radiusUnit() == HeatmapGui::LayerUnits ) { radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() ); } } else { radius = d.radius(); // radius returned by d.radius() is already in map units myBuffer = bufferSize( radius, cellsize ); } if ( d.weighted() ) { wField = d.weightField(); myAttrList.append( wField ); } // This might have attributes or mightnot have attibutes at all // based on the variableRadius() and weighted() QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) ); int totalFeatures = inputLayer->featureCount(); int counter = 0; QProgressDialog p( tr( "Rendering heatmap..." ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() ); p.setWindowTitle( tr( "QGIS" ) ); p.setWindowModality( Qt::ApplicationModal ); p.show(); QgsFeature myFeature; while ( fit.nextFeature( myFeature ) ) { counter++; p.setValue( counter ); QApplication::processEvents(); if ( p.wasCanceled() ) { mQGisIface->messageBar()->pushMessage( tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() ); break; } const QgsGeometry* featureGeometry = myFeature.constGeometry(); if ( !featureGeometry ) { continue; } // convert the geometry to multipoint QgsMultiPoint multiPoints; if ( !isMultiPoint ) { QgsPoint myPoint = featureGeometry->asPoint(); // avoiding any empty points or out of extent points if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() ) || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) ) { continue; } multiPoints << myPoint; } else { multiPoints = featureGeometry->asMultiPoint(); } // If radius is variable then fetch it and calculate new pixel buffer size if ( d.variableRadius() ) { radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits; myBuffer = bufferSize( radius, cellsize ); } int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate double weight = 1.0; if ( d.weighted() ) { weight = myFeature.attribute( wField ).toDouble(); } //loop through all points in multipoint for ( QgsMultiPoint::const_iterator pointIt = multiPoints.constBegin(); pointIt != multiPoints.constEnd(); ++pointIt ) { // avoiding any empty points or out of extent points if ((( *pointIt ).x() < myBBox.xMinimum() ) || (( *pointIt ).y() < myBBox.yMinimum() ) || (( *pointIt ).x() > myBBox.xMaximum() ) || (( *pointIt ).y() > myBBox.yMaximum() ) ) { continue; } // calculate the pixel position unsigned int xPosition, yPosition; xPosition = ((( *pointIt ).x() - myBBox.xMinimum() ) / cellsize ) - myBuffer; yPosition = ((( *pointIt ).y() - myBBox.yMinimum() ) / cellsize ) - myBuffer; // get the data float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize ); if ( GDALRasterIO( poBand, GF_Read, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } for ( int xp = 0; xp <= myBuffer; xp++ ) { for ( int yp = 0; yp <= myBuffer; yp++ ) { double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) ); // is pixel outside search bandwidth of feature? if ( distance > myBuffer ) { continue; } double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape, valueType ); // clearing anamolies along the axes if ( xp == 0 && yp == 0 ) { pixelValue /= 4; } else if ( xp == 0 || yp == 0 ) { pixelValue /= 2; } int pos[4]; pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp ); pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp ); pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp ); pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp ); for ( int p = 0; p < 4; p++ ) { if ( dataBuffer[ pos[p] ] == NO_DATA ) { dataBuffer[ pos[p] ] = 0; } dataBuffer[ pos[p] ] += pixelValue; } } } if ( GDALRasterIO( poBand, GF_Write, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } CPLFree( dataBuffer ); } } // Finally close the dataset GDALClose(( GDALDatasetH ) heatmapDS ); // Open the file in QGIS window if requested if ( d.addToCanvas() ) { mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() ); } }
void CUtils::calculateByteGeoTIFFStatistics(GDALDatasetH hDataset, int userBandNumber, byte flNoDataValueAsBackground, byte NoDataValue) { fputs("\nCalculate statistics...\n", stderr); GDALRasterBandH hBand = GDALGetRasterBand(hDataset, 1); int cols = GDALGetRasterBandXSize(hBand); int rows = GDALGetRasterBandYSize(hBand); int bands = GDALGetRasterCount(hDataset); byte * pbuf = NULL; pbuf = (byte *)CPLMalloc(sizeof(byte)*cols); byte min = 0, max = 0, mean = 0; double stddev = 0; double summ = 0; int count = 0; for(int band=1; band<=bands; band++) { if(userBandNumber != -1) fprintf(stderr, "Band %d...\n", userBandNumber); else fprintf(stderr, "Band %d...\n", band); hBand = GDALGetRasterBand(hDataset, band); if(flNoDataValueAsBackground) NoDataValue = getFloatNoDataValueAsBackground(hBand); min = max = mean = stddev = summ = 0; count = 0; bool flFirst = true; int pr = CUtils::progress_ln_ex(stderr, 0, 0, START_PROGRESS); for(int i=0; i<rows; i++) { GDALRasterIO(hBand, GF_Read, 0, i, cols, 1, pbuf, cols, 1, GDT_Byte, 0, 0 ); for(int j=0; j<cols; j++) if(pbuf[j]!=NoDataValue) { if(flFirst) { mean = pbuf[j]; min = max = mean; flFirst = false; } else { mean += pbuf[j]; if( min > pbuf[j] ) min = pbuf[j]; if( max < pbuf[j] ) max = pbuf[j]; } count++; } pr = CUtils::progress_ln_ex(stderr, i, rows, pr); } CUtils::progress_ln_ex(stderr, 0, 0, END_PROGRESS); double dmean = 0; if(count > 0) dmean = mean / (double)count; pr = CUtils::progress_ln_ex(stderr, 0, 0, START_PROGRESS); for(int i=0; i<rows; i++) { GDALRasterIO(hBand, GF_Read, 0, i, cols, 1, pbuf, cols, 1, GDT_Byte, 0, 0 ); for(int j=0; j<cols; j++) if(pbuf[j]!=NoDataValue) summ += ((double)pbuf[j]-dmean)*((double)pbuf[j]-dmean); pr = CUtils::progress_ln_ex(stderr, i, rows, pr); } CUtils::progress_ln_ex(stderr, 0, 0, END_PROGRESS); summ = 0; stddev = 0; if((count-1)>0) { summ /= (double)(count-1); if(summ!=0) stddev = sqrt(summ); } GDALSetRasterStatistics(hBand, min, max, mean, stddev); GDALSetRasterNoDataValue(hBand, NoDataValue); } CPLFree(pbuf); }
int main( int argc, char ** argv ) { GDALDriverH hDriver; const char *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff"; int bFormatExplicitlySet = FALSE; char **papszLayers = NULL; const char *pszBurnAttribute = NULL; double dfIncreaseBurnValue = 0.0; double dfMultiplyBurnValue = 1.0; const char *pszWHERE = NULL, *pszSQL = NULL; GDALDataType eOutputType = GDT_Float64; char **papszCreateOptions = NULL; GUInt32 nXSize = 0, nYSize = 0; double dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0; int bIsXExtentSet = FALSE, bIsYExtentSet = FALSE; GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower; void *pOptions = NULL; char *pszOutputSRS = NULL; int bQuiet = FALSE; GDALProgressFunc pfnProgress = GDALTermProgress; int i; OGRGeometry *poSpatialFilter = NULL; int bClipSrc = FALSE; OGRGeometry *poClipSrc = NULL; const char *pszClipSrcDS = NULL; const char *pszClipSrcSQL = NULL; const char *pszClipSrcLayer = NULL; const char *pszClipSrcWhere = NULL; int bNoDataSet = FALSE; double dfNoDataValue = 0; /* Check strict compilation and runtime library version as we use C++ API */ if (! GDAL_CHECK_VERSION(argv[0])) exit(1); GDALAllRegister(); OGRRegisterAll(); argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 ); if( argc < 1 ) exit( -argc ); /* -------------------------------------------------------------------- */ /* Parse arguments. */ /* -------------------------------------------------------------------- */ for( i = 1; i < argc; i++ ) { if( EQUAL(argv[i], "--utility_version") ) { printf("%s was compiled against GDAL %s and is running against GDAL %s\n", argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); return 0; } else if( EQUAL(argv[i],"--help") ) Usage(); else if( EQUAL(argv[i],"-of") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszFormat = argv[++i]; bFormatExplicitlySet = TRUE; } else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") ) { bQuiet = TRUE; pfnProgress = GDALDummyProgress; } else if( EQUAL(argv[i],"-ot") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); int iType; for( iType = 1; iType < GDT_TypeCount; iType++ ) { if( GDALGetDataTypeName((GDALDataType)iType) != NULL && EQUAL(GDALGetDataTypeName((GDALDataType)iType), argv[i+1]) ) { eOutputType = (GDALDataType) iType; } } if( eOutputType == GDT_Unknown ) { Usage(CPLSPrintf("Unknown output pixel type: %s.", argv[i + 1] )); } i++; } else if( EQUAL(argv[i],"-txe") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); dfXMin = CPLAtof(argv[++i]); dfXMax = CPLAtof(argv[++i]); bIsXExtentSet = TRUE; } else if( EQUAL(argv[i],"-tye") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); dfYMin = CPLAtof(argv[++i]); dfYMax = CPLAtof(argv[++i]); bIsYExtentSet = TRUE; } else if( EQUAL(argv[i],"-outsize") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); nXSize = atoi(argv[++i]); nYSize = atoi(argv[++i]); } else if( EQUAL(argv[i],"-co") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] ); } else if( EQUAL(argv[i],"-zfield") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszBurnAttribute = argv[++i]; } else if( EQUAL(argv[i],"-z_increase") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); dfIncreaseBurnValue = CPLAtof(argv[++i]); } else if( EQUAL(argv[i],"-z_multiply") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); dfMultiplyBurnValue = CPLAtof(argv[++i]); } else if( EQUAL(argv[i],"-where") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszWHERE = argv[++i]; } else if( EQUAL(argv[i],"-l") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); papszLayers = CSLAddString( papszLayers, argv[++i] ); } else if( EQUAL(argv[i],"-sql") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszSQL = argv[++i]; } else if( EQUAL(argv[i],"-spat") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4); OGRLinearRing oRing; oRing.addPoint( CPLAtof(argv[i+1]), CPLAtof(argv[i+2]) ); oRing.addPoint( CPLAtof(argv[i+1]), CPLAtof(argv[i+4]) ); oRing.addPoint( CPLAtof(argv[i+3]), CPLAtof(argv[i+4]) ); oRing.addPoint( CPLAtof(argv[i+3]), CPLAtof(argv[i+2]) ); oRing.addPoint( CPLAtof(argv[i+1]), CPLAtof(argv[i+2]) ); poSpatialFilter = new OGRPolygon(); ((OGRPolygon *) poSpatialFilter)->addRing( &oRing ); i += 4; } else if ( EQUAL(argv[i],"-clipsrc") ) { if (i + 1 >= argc) Usage(CPLSPrintf("%s option requires 1 or 4 arguments", argv[i])); bClipSrc = TRUE; errno = 0; const double unused = strtod( argv[i + 1], NULL ); // XXX: is it a number or not? if ( errno != 0 && argv[i + 2] != NULL && argv[i + 3] != NULL && argv[i + 4] != NULL) { OGRLinearRing oRing; oRing.addPoint( CPLAtof(argv[i + 1]), CPLAtof(argv[i + 2]) ); oRing.addPoint( CPLAtof(argv[i + 1]), CPLAtof(argv[i + 4]) ); oRing.addPoint( CPLAtof(argv[i + 3]), CPLAtof(argv[i + 4]) ); oRing.addPoint( CPLAtof(argv[i + 3]), CPLAtof(argv[i + 2]) ); oRing.addPoint( CPLAtof(argv[i + 1]), CPLAtof(argv[i + 2]) ); poClipSrc = new OGRPolygon(); ((OGRPolygon *) poClipSrc)->addRing( &oRing ); i += 4; (void)unused; } else if (EQUALN(argv[i + 1], "POLYGON", 7) || EQUALN(argv[i + 1], "MULTIPOLYGON", 12)) { OGRGeometryFactory::createFromWkt(&argv[i + 1], NULL, &poClipSrc); if ( poClipSrc == NULL ) { Usage("Invalid geometry. " "Must be a valid POLYGON or MULTIPOLYGON WKT."); } i++; } else if (EQUAL(argv[i + 1], "spat_extent") ) { i++; } else { pszClipSrcDS = argv[i + 1]; i++; } } else if ( EQUAL(argv[i], "-clipsrcsql") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszClipSrcSQL = argv[i + 1]; i++; } else if ( EQUAL(argv[i], "-clipsrclayer") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszClipSrcLayer = argv[i + 1]; i++; } else if ( EQUAL(argv[i], "-clipsrcwhere") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszClipSrcWhere = argv[i + 1]; i++; } else if( EQUAL(argv[i],"-a_srs") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); OGRSpatialReference oOutputSRS; if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE ) { fprintf( stderr, "Failed to process SRS definition: %s\n", argv[i+1] ); GDALDestroyDriverManager(); exit( 1 ); } oOutputSRS.exportToWkt( &pszOutputSRS ); i++; } else if( EQUAL(argv[i],"-a") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char* pszAlgorithm = argv[++i]; if ( ParseAlgorithmAndOptions( pszAlgorithm, &eAlgorithm, &pOptions ) != CE_None ) { fprintf( stderr, "Failed to process algorithm name and parameters.\n" ); exit( 1 ); } char **papszParms = CSLTokenizeString2( pszAlgorithm, ":", FALSE ); const char* pszNoDataValue = CSLFetchNameValue( papszParms, "nodata" ); if( pszNoDataValue != NULL ) { bNoDataSet = TRUE; dfNoDataValue = CPLAtofM(pszNoDataValue); } CSLDestroy(papszParms); } else if( argv[i][0] == '-' ) { Usage(CPLSPrintf("Unknown option name '%s'", argv[i])); } else if( pszSource == NULL ) { pszSource = argv[i]; } else if( pszDest == NULL ) { pszDest = argv[i]; } else { Usage("Too many command options."); } } if( pszSource == NULL ) { Usage("Source datasource is not specified."); } if( pszDest == NULL ) { Usage("Target dataset is not specified."); } if( pszSQL == NULL && papszLayers == NULL ) { Usage("Neither -sql nor -l are specified."); } if ( bClipSrc && pszClipSrcDS != NULL ) { poClipSrc = LoadGeometry( pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere ); if ( poClipSrc == NULL ) { Usage("Cannot load source clip geometry."); } } else if ( bClipSrc && poClipSrc == NULL && !poSpatialFilter ) { Usage("-clipsrc must be used with -spat option or \n" "a bounding box, WKT string or datasource must be " "specified."); } if ( poSpatialFilter ) { if ( poClipSrc ) { OGRGeometry *poTemp = poSpatialFilter->Intersection( poClipSrc ); if ( poTemp ) { OGRGeometryFactory::destroyGeometry( poSpatialFilter ); poSpatialFilter = poTemp; } OGRGeometryFactory::destroyGeometry( poClipSrc ); poClipSrc = NULL; } } else { if ( poClipSrc ) { poSpatialFilter = poClipSrc; poClipSrc = NULL; } } /* -------------------------------------------------------------------- */ /* Find the output driver. */ /* -------------------------------------------------------------------- */ hDriver = GDALGetDriverByName( pszFormat ); if( hDriver == NULL ) { int iDr; fprintf( stderr, "FAILURE: Output driver `%s' not recognised.\n", pszFormat ); fprintf( stderr, "The following format drivers are configured and support output:\n" ); for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ ) { GDALDriverH hDriver = GDALGetDriver(iDr); if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL && ( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) ) { fprintf( stderr, " %s: %s\n", GDALGetDriverShortName( hDriver ), GDALGetDriverLongName( hDriver ) ); } } printf( "\n" ); Usage(); } /* -------------------------------------------------------------------- */ /* Open input datasource. */ /* -------------------------------------------------------------------- */ OGRDataSourceH hSrcDS; hSrcDS = OGROpen( pszSource, FALSE, NULL ); if( hSrcDS == NULL ) { fprintf( stderr, "Unable to open input datasource \"%s\".\n", pszSource ); fprintf( stderr, "%s\n", CPLGetLastErrorMsg() ); exit( 3 ); } /* -------------------------------------------------------------------- */ /* Create target raster file. */ /* -------------------------------------------------------------------- */ GDALDatasetH hDstDS; int nLayerCount = CSLCount(papszLayers); int nBands = nLayerCount; if ( pszSQL ) nBands++; // FIXME if ( nXSize == 0 ) nXSize = 256; if ( nYSize == 0 ) nYSize = 256; if (!bQuiet && !bFormatExplicitlySet) CheckExtensionConsistency(pszDest, pszFormat); hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands, eOutputType, papszCreateOptions ); if ( hDstDS == NULL ) { fprintf( stderr, "Unable to create target dataset \"%s\".\n", pszDest ); fprintf( stderr, "%s\n", CPLGetLastErrorMsg() ); exit( 3 ); } if( bNoDataSet ) { for( i = 1; i <= nBands; i++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i ); GDALSetRasterNoDataValue( hBand, dfNoDataValue ); } } /* -------------------------------------------------------------------- */ /* If algorithm was not specified assigh default one. */ /* -------------------------------------------------------------------- */ if ( !pOptions ) ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions ); /* -------------------------------------------------------------------- */ /* Process SQL request. */ /* -------------------------------------------------------------------- */ if( pszSQL != NULL ) { OGRLayerH hLayer; hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL, (OGRGeometryH)poSpatialFilter, NULL ); if( hLayer != NULL ) { // Custom layer will be rasterized in the first band. ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, 1, bIsXExtentSet, bIsYExtentSet, dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute, dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions, bQuiet, pfnProgress ); } } /* -------------------------------------------------------------------- */ /* Process each layer. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nLayerCount; i++ ) { OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i]); if( hLayer == NULL ) { fprintf( stderr, "Unable to find layer \"%s\", skipping.\n", papszLayers[i] ); continue; } if( pszWHERE ) { if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE ) break; } if ( poSpatialFilter != NULL ) OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)poSpatialFilter ); // Fetch the first meaningful SRS definition if ( !pszOutputSRS ) { OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer ); if ( hSRS ) OSRExportToWkt( hSRS, &pszOutputSRS ); } ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, i + 1 + nBands - nLayerCount, bIsXExtentSet, bIsYExtentSet, dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute, dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions, bQuiet, pfnProgress ); } /* -------------------------------------------------------------------- */ /* Apply geotransformation matrix. */ /* -------------------------------------------------------------------- */ double adfGeoTransform[6]; adfGeoTransform[0] = dfXMin; adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = dfYMin; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize; GDALSetGeoTransform( hDstDS, adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Apply SRS definition if set. */ /* -------------------------------------------------------------------- */ if ( pszOutputSRS ) { GDALSetProjection( hDstDS, pszOutputSRS ); CPLFree( pszOutputSRS ); } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ OGR_DS_Destroy( hSrcDS ); GDALClose( hDstDS ); OGRGeometryFactory::destroyGeometry( poSpatialFilter ); CPLFree( pOptions ); CSLDestroy( papszCreateOptions ); CSLDestroy( argv ); CSLDestroy( papszLayers ); OGRCleanupAll(); GDALDestroyDriverManager(); 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; }
int main (int argc, const char *argv[]) { GDALDriverH hDriver; double adfGeoTransform[6]; GDALDatasetH in_Dataset; GDALDatasetH mask_Dataset; GDALDatasetH out_Dataset; GDALRasterBandH mask_band; char *mask_scan_line, *data_scan_line; int nBlockXSize, nBlockYSize; int bGotMin, bGotMax; int bands; int xsize; double adfMinMax[2]; GDALAllRegister (); /* Set cache to something reasonable.. - 1/2 gig */ CPLSetConfigOption ("GDAL_CACHEMAX", "512"); /* open datasets.. */ in_Dataset = GDAL_open_read (argv[1]); mask_Dataset = GDAL_open_read (argv[2]); out_Dataset = make_me_a_sandwitch (&in_Dataset, argv[3]); mask_band = GDALGetRasterBand (mask_Dataset, 1); /* Basic info on source dataset.. */ GDALGetBlockSize (GDALGetRasterBand (in_Dataset, 1), &nBlockXSize, &nBlockYSize); printf ("Block=%dx%d Type=%s, ColorInterp=%s\n", nBlockXSize, nBlockYSize, GDALGetDataTypeName (GDALGetRasterDataType (GDALGetRasterBand (in_Dataset, 1))), GDALGetColorInterpretationName (GDALGetRasterColorInterpretation (GDALGetRasterBand (in_Dataset, 1)))); /* Loop though bands, wiping values with mask values of 0.. */ xsize = GDALGetRasterXSize (in_Dataset); mask_scan_line = (char *) CPLMalloc (sizeof (char) * xsize); data_scan_line = (char *) CPLMalloc (sizeof (char) * xsize); for (bands = 1; bands <= GDALGetRasterCount (in_Dataset); bands++) { int x; GDALRasterBandH data_band, out_band; int y_index = 0; data_band = GDALGetRasterBand (in_Dataset, bands); out_band = GDALGetRasterBand (out_Dataset, bands); for (y_index = 0; y_index < GDALGetRasterYSize (in_Dataset); y_index++) { /* Read data.. */ GDALRasterIO (data_band, GF_Read, 0, y_index, xsize, 1, data_scan_line, xsize, 1, GDT_Byte, 0, 0); /* Read mask.. */ GDALRasterIO (mask_band, GF_Read, 0, y_index, xsize, 1, mask_scan_line, xsize, 1, GDT_Byte, 0, 0); GDALSetRasterNoDataValue (out_band, 0.0); for (x = 0; x < xsize; x++) { /* if mask is set to 0, then mask off... */ if (mask_scan_line[x] == 0) data_scan_line[x] = 0; /* if mask is not zero, and data is zero, then unmask.. */ if (mask_scan_line[x] != 0 && data_scan_line[x] == 0) data_scan_line[x] = 1; } /* now write out band.. */ GDALRasterIO (out_band, GF_Write, 0, y_index, xsize, 1, data_scan_line, xsize, 1, GDT_Byte, 0, 0); } } GDALClose (out_Dataset); }
void QgsImageWarper::warp( const QString& input, const QString& output, double& xOffset, double& yOffset, ResamplingMethod resampling, bool useZeroAsTrans, const QString& compression ) { // Open input file GDALAllRegister(); GDALDatasetH hSrcDS = GDALOpen( QFile::encodeName( input ).constData(), GA_ReadOnly ); // Setup warp options. GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions(); psWarpOptions->hSrcDS = hSrcDS; psWarpOptions->nBandCount = GDALGetRasterCount( hSrcDS ); psWarpOptions->panSrcBands = ( int * ) CPLMalloc( sizeof( int ) * psWarpOptions->nBandCount ); psWarpOptions->panDstBands = ( int * ) CPLMalloc( sizeof( int ) * psWarpOptions->nBandCount ); for ( int i = 0; i < psWarpOptions->nBandCount; ++i ) { psWarpOptions->panSrcBands[i] = i + 1; psWarpOptions->panDstBands[i] = i + 1; } psWarpOptions->pfnProgress = GDALTermProgress; psWarpOptions->pfnTransformer = &QgsImageWarper::transform; psWarpOptions->eResampleAlg = GDALResampleAlg( resampling ); // check the bounds for the warped raster // order: upper right, lower right, lower left (y points down) double x[] = { GDALGetRasterXSize( hSrcDS ), GDALGetRasterXSize( hSrcDS ), 0 }; double y[] = { 0, GDALGetRasterYSize( hSrcDS ), GDALGetRasterYSize( hSrcDS ) }; int s[] = { 0, 0, 0 }; TransformParameters tParam = { mAngle, 0, 0 }; transform( &tParam, FALSE, 3, x, y, NULL, s ); double minX = 0, minY = 0, maxX = 0, maxY = 0; for ( int i = 0; i < 3; ++i ) { minX = minX < x[i] ? minX : x[i]; minY = minY < y[i] ? minY : y[i]; maxX = maxX > x[i] ? maxX : x[i]; maxY = maxY > y[i] ? maxY : y[i]; } int newXSize = int( maxX - minX ) + 1; int newYSize = int( maxY - minY ) + 1; xOffset = -minX; yOffset = -minY; tParam.x0 = xOffset; tParam.y0 = yOffset; psWarpOptions->pTransformerArg = &tParam; // create the output file GDALDriverH driver = GDALGetDriverByName( "GTiff" ); char **papszOptions = NULL; papszOptions = CSLSetNameValue( papszOptions, "INIT_DEST", "NO_DATA" ); papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", compression.toAscii() ); GDALDatasetH hDstDS = GDALCreate( driver, QFile::encodeName( output ).constData(), newXSize, newYSize, GDALGetRasterCount( hSrcDS ), GDALGetRasterDataType( GDALGetRasterBand( hSrcDS, 1 ) ), papszOptions ); for ( int i = 0; i < GDALGetRasterCount( hSrcDS ); ++i ) { GDALRasterBandH hSrcBand = GDALGetRasterBand( hSrcDS, i + 1 ); GDALRasterBandH hDstBand = GDALGetRasterBand( hDstDS, i + 1 ); GDALColorTableH cTable = GDALGetRasterColorTable( hSrcBand ); GDALSetRasterColorInterpretation( hDstBand, GDALGetRasterColorInterpretation( hSrcBand ) ); if ( cTable ) { GDALSetRasterColorTable( hDstBand, cTable ); } double noData = GDALGetRasterNoDataValue( hSrcBand, NULL ); if ( noData == -1e10 && useZeroAsTrans ) { GDALSetRasterNoDataValue( hDstBand, 0 ); } else { GDALSetRasterNoDataValue( hDstBand, noData ); } } psWarpOptions->hDstDS = hDstDS; // Initialize and execute the warp operation. GDALWarpOperation oOperation; oOperation.Initialize( psWarpOptions ); oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ); GDALDestroyWarpOptions( psWarpOptions ); GDALClose( hSrcDS ); GDALClose( hDstDS ); }
int QgsRasterCalculator::processCalculation( QProgressDialog* p ) { //prepare search string / tree QString errorString; QgsRasterCalcNode* calcNode = QgsRasterCalcNode::parseRasterCalcString( mFormulaString, errorString ); if ( !calcNode ) { //error } double targetGeoTransform[6]; outputGeoTransform( targetGeoTransform ); //open all input rasters for reading QMap< QString, GDALRasterBandH > mInputRasterBands; //raster references and corresponding scanline data QMap< QString, QgsRasterMatrix* > inputScanLineData; //stores raster references and corresponding scanline data QVector< GDALDatasetH > mInputDatasets; //raster references and corresponding dataset QVector<QgsRasterCalculatorEntry>::const_iterator it = mRasterEntries.constBegin(); for ( ; it != mRasterEntries.constEnd(); ++it ) { if ( !it->raster ) // no raster layer in entry { return 2; } GDALDatasetH inputDataset = GDALOpen( it->raster->source().toLocal8Bit().data(), GA_ReadOnly ); if ( inputDataset == NULL ) { return 2; } //check if the input dataset is south up or rotated. If yes, use GDALAutoCreateWarpedVRT to create a north up raster double inputGeoTransform[6]; if ( GDALGetGeoTransform( inputDataset, inputGeoTransform ) == CE_None && ( inputGeoTransform[1] < 0.0 || inputGeoTransform[2] != 0.0 || inputGeoTransform[4] != 0.0 || inputGeoTransform[5] > 0.0 ) ) { GDALDatasetH vDataset = GDALAutoCreateWarpedVRT( inputDataset, NULL, NULL, GRA_NearestNeighbour, 0.2, NULL ); mInputDatasets.push_back( vDataset ); mInputDatasets.push_back( inputDataset ); inputDataset = vDataset; } else { mInputDatasets.push_back( inputDataset ); } GDALRasterBandH inputRasterBand = GDALGetRasterBand( inputDataset, it->bandNumber ); if ( inputRasterBand == NULL ) { return 2; } int nodataSuccess; double nodataValue = GDALGetRasterNoDataValue( inputRasterBand, &nodataSuccess ); mInputRasterBands.insert( it->ref, inputRasterBand ); inputScanLineData.insert( it->ref, new QgsRasterMatrix( mNumOutputColumns, 1, new float[mNumOutputColumns], nodataValue ) ); } //open output dataset for writing GDALDriverH outputDriver = openOutputDriver(); if ( outputDriver == NULL ) { return 1; } GDALDatasetH outputDataset = openOutputFile( outputDriver ); GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset, 1 ); float outputNodataValue = -FLT_MAX; GDALSetRasterNoDataValue( outputRasterBand, outputNodataValue ); float* resultScanLine = ( float * ) CPLMalloc( sizeof( float ) * mNumOutputColumns ); if ( p ) { p->setMaximum( mNumOutputRows ); } QgsRasterMatrix resultMatrix; //read / write line by line for ( int i = 0; i < mNumOutputRows; ++i ) { if ( p ) { p->setValue( i ); } if ( p && p->wasCanceled() ) { break; } //fill buffers QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin(); for ( ; bufferIt != inputScanLineData.end(); ++bufferIt ) { double sourceTransformation[6]; GDALRasterBandH sourceRasterBand = mInputRasterBands[bufferIt.key()]; GDALGetGeoTransform( GDALGetBandDataset( sourceRasterBand ), sourceTransformation ); //the function readRasterPart calls GDALRasterIO (and ev. does some conversion if raster transformations are not the same) readRasterPart( targetGeoTransform, 0, i, mNumOutputColumns, 1, sourceTransformation, sourceRasterBand, bufferIt.value()->data() ); } if ( calcNode->calculate( inputScanLineData, resultMatrix ) ) { bool resultIsNumber = resultMatrix.isNumber(); float* calcData; if ( resultIsNumber ) //scalar result. Insert number for every pixel { calcData = new float[mNumOutputColumns]; for ( int j = 0; j < mNumOutputColumns; ++j ) { calcData[j] = resultMatrix.number(); } } else //result is real matrix { calcData = resultMatrix.data(); } //replace all matrix nodata values with output nodatas for ( int j = 0; j < mNumOutputColumns; ++j ) { if ( calcData[j] == resultMatrix.nodataValue() ) { calcData[j] = outputNodataValue; } } //write scanline to the dataset if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, mNumOutputColumns, 1, calcData, mNumOutputColumns, 1, GDT_Float32, 0, 0 ) != CE_None ) { qWarning( "RasterIO error!" ); } if ( resultIsNumber ) { delete[] calcData; } } } if ( p ) { p->setValue( mNumOutputRows ); } //close datasets and release memory delete calcNode; QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin(); for ( ; bufferIt != inputScanLineData.end(); ++bufferIt ) { delete bufferIt.value(); } inputScanLineData.clear(); QVector< GDALDatasetH >::iterator datasetIt = mInputDatasets.begin(); for ( ; datasetIt != mInputDatasets.end(); ++ datasetIt ) { GDALClose( *datasetIt ); } if ( p && p->wasCanceled() ) { //delete the dataset without closing (because it is faster) GDALDeleteDataset( outputDriver, mOutputFile.toLocal8Bit().data() ); return 3; } GDALClose( outputDataset ); CPLFree( resultScanLine ); return 0; }
bool QgsImageWarper::createDestinationDataset( const QString &outputName, GDALDatasetH hSrcDS, GDALDatasetH &hDstDS, uint resX, uint resY, double *adfGeoTransform, bool useZeroAsTrans, const QString& compression, const QString &projection ) { // create the output file GDALDriverH driver = GDALGetDriverByName( "GTiff" ); if ( !driver ) { return false; } char **papszOptions = NULL; papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", compression.toAscii() ); hDstDS = GDALCreate( driver, QFile::encodeName( outputName ).constData(), resX, resY, GDALGetRasterCount( hSrcDS ), GDALGetRasterDataType( GDALGetRasterBand( hSrcDS, 1 ) ), papszOptions ); if ( !hDstDS ) { return false; } if ( CE_None != GDALSetGeoTransform( hDstDS, adfGeoTransform ) ) { return false; } if ( !projection.isEmpty() ) { OGRSpatialReference oTargetSRS; if ( projection.startsWith( "EPSG", Qt::CaseInsensitive ) ) { QString epsg = projection.mid( projection.indexOf( ":" ) + 1 ); oTargetSRS.importFromEPSG( epsg.toInt() ); } else { oTargetSRS.importFromProj4( projection.toLatin1().data() ); } char *wkt = NULL; OGRErr err = oTargetSRS.exportToWkt( &wkt ); if ( err != CE_None || GDALSetProjection( hDstDS, wkt ) != CE_None ) { OGRFree( wkt ); return false; } OGRFree( wkt ); } for ( int i = 0; i < GDALGetRasterCount( hSrcDS ); ++i ) { GDALRasterBandH hSrcBand = GDALGetRasterBand( hSrcDS, i + 1 ); GDALRasterBandH hDstBand = GDALGetRasterBand( hDstDS, i + 1 ); GDALColorTableH cTable = GDALGetRasterColorTable( hSrcBand ); GDALSetRasterColorInterpretation( hDstBand, GDALGetRasterColorInterpretation( hSrcBand ) ); if ( cTable ) { GDALSetRasterColorTable( hDstBand, cTable ); } int success; double noData = GDALGetRasterNoDataValue( hSrcBand, &success ); if ( success ) { GDALSetRasterNoDataValue( hDstBand, noData ); } else if ( useZeroAsTrans ) { GDALSetRasterNoDataValue( hDstBand, 0 ); } } return true; }
void Dust::MakeGrid(WindNinjaInputs &input, AsciiGrid<double> &grid) { /*------------------------------------------*/ /* Open grid as a GDAL dataset */ /*------------------------------------------*/ int nXSize = grid.get_nCols(); int nYSize = grid.get_nRows(); GDALDriverH hDriver = GDALGetDriverByName( "MEM" ); GDALDatasetH hMemDS = GDALCreate(hDriver, "", nXSize, nYSize, 1, GDT_Float64, NULL); double *padfScanline; padfScanline = new double[nXSize]; double adfGeoTransform[6]; adfGeoTransform[0] = grid.get_xllCorner(); adfGeoTransform[1] = grid.get_cellSize(); adfGeoTransform[2] = 0; adfGeoTransform[3] = grid.get_yllCorner()+(grid.get_nRows()*grid.get_cellSize()); adfGeoTransform[4] = 0; adfGeoTransform[5] = -grid.get_cellSize(); char* pszDstWKT = (char*)grid.prjString.c_str(); GDALSetProjection(hMemDS, pszDstWKT); GDALSetGeoTransform(hMemDS, adfGeoTransform); GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, 1 ); GDALSetRasterNoDataValue(hBand, -9999.0); for(int i=nYSize-1; i>=0; i--) { for(int j=0; j<nXSize; j++) { padfScanline[j] = grid.get_cellValue(nYSize-1-i, j); } GDALRasterIO(hBand, GF_Write, 0, i, nXSize, 1, padfScanline, nXSize, 1, GDT_Float64, 0, 0); } /*------------------------------------------*/ /* Get the geometry info */ /*------------------------------------------*/ OGRDataSourceH hOGRDS = 0; hOGRDS = OGROpen(input.dustFilename.c_str(), FALSE, 0); if(hOGRDS == NULL) { throw std::runtime_error("Could not open the fire perimeter file '" + input.dustFilename + "' for reading."); } OGRLayer *poLayer; OGRFeature *poFeature; OGRGeometry *poGeo; poLayer = (OGRLayer*)OGR_DS_GetLayer(hOGRDS, 0); poLayer->ResetReading(); poFeature = poLayer->GetNextFeature(); poGeo = poFeature->GetGeometryRef(); OGRGeometryH hPolygon = (OGRGeometryH) poGeo; /* -------------------------------------------------------------------- */ /* Check for same CRS in fire perimeter and DEM files */ /* -------------------------------------------------------------------- */ char *pszSrcWKT; OGRSpatialReference *poSrcSRS, oDstSRS; poSrcSRS = poLayer->GetSpatialRef(); //shapefile CRS poSrcSRS->exportToWkt( &pszSrcWKT ); //printf("CRS of DEM is:\n %s\n", pszDstWKT); //printf("WKT CRS of .shp is:\n %s\n", pszSrcWKT); oDstSRS.importFromWkt( &pszDstWKT ); char *pszDstProj4, *pszSrcProj4; oDstSRS.exportToProj4( &pszDstProj4 ); poSrcSRS->exportToProj4( &pszSrcProj4 ); //printf("proj4 of .shp is:\n %s\n", pszSrcProj4); //printf("proj4 of dem is:\n %s\n", pszDstProj4); /* -------------------------------------------------------------------- */ /* If the CRSs are not equal, convert shapefile CRS to DEM CRS */ /* -------------------------------------------------------------------- */ GDALTransformerFunc pfnTransformer = NULL; if( !EQUAL( pszSrcProj4, pszDstProj4 ) ){ //tranform shp CRS to DEM CRS poGeo->transformTo(&oDstSRS); } /* -------------------------------------------------------------------- */ /* Rasterize the shapefile */ /* -------------------------------------------------------------------- */ int nTargetBand = 1; double BurnValue = 1.0; CPLErr eErr; eErr = GDALRasterizeGeometries(hMemDS, 1, &nTargetBand, 1, &hPolygon, pfnTransformer, NULL, &BurnValue, NULL, NULL, NULL); if(eErr != CE_None) { throw std::runtime_error("Error in GDALRasterizeGeometies in Dust:MakeGrid()."); } GDAL2AsciiGrid((GDALDataset*)hMemDS, 1, grid); /* -------------------------------------------------------------------- */ /* clean up */ /* -------------------------------------------------------------------- */ if( hMemDS != NULL ){ GDALClose( hMemDS ); hMemDS = NULL; } OGR_DS_Destroy(hOGRDS); }
int msSaveImageGDAL( mapObj *map, imageObj *image, char *filename ) { int bFileIsTemporary = MS_FALSE; GDALDatasetH hMemDS, hOutputDS; GDALDriverH hMemDriver, hOutputDriver; int nBands = 1; int iLine; GByte *pabyAlphaLine = NULL; char **papszOptions = NULL; outputFormatObj *format = image->format; rasterBufferObj rb; GDALDataType eDataType = GDT_Byte; int bUseXmp = MS_FALSE; msGDALInitialize(); memset(&rb,0,sizeof(rasterBufferObj)); #ifdef USE_EXEMPI if( map != NULL ) { bUseXmp = msXmpPresent(map); } #endif /* -------------------------------------------------------------------- */ /* Identify the proposed output driver. */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_GDAL ); hOutputDriver = GDALGetDriverByName( format->driver+5 ); if( hOutputDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find %s driver.", "msSaveImageGDAL()", format->driver+5 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* We will need to write the output to a temporary file and */ /* then stream to stdout if no filename is passed. If the */ /* driver supports virtualio then we hold the temporary file in */ /* memory, otherwise we try to put it in a reasonable temporary */ /* file location. */ /* -------------------------------------------------------------------- */ if( filename == NULL ) { const char *pszExtension = format->extension; if( pszExtension == NULL ) pszExtension = "img.tmp"; if( bUseXmp == MS_FALSE && GDALGetMetadataItem( hOutputDriver, GDAL_DCAP_VIRTUALIO, NULL ) != NULL ) { CleanVSIDir( "/vsimem/msout" ); filename = msTmpFile(map, NULL, "/vsimem/msout/", pszExtension ); } if( filename == NULL && map != NULL) filename = msTmpFile(map, map->mappath,NULL,pszExtension); else if( filename == NULL ) { filename = msTmpFile(map, NULL, NULL, pszExtension ); } bFileIsTemporary = MS_TRUE; } /* -------------------------------------------------------------------- */ /* Establish the characteristics of our memory, and final */ /* dataset. */ /* -------------------------------------------------------------------- */ if( format->imagemode == MS_IMAGEMODE_RGB ) { nBands = 3; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); format->vtable->getRasterBufferHandle(image,&rb); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { pabyAlphaLine = (GByte *) calloc(image->width,1); if (pabyAlphaLine == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", image->width); return MS_FAILURE; } nBands = 4; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); format->vtable->getRasterBufferHandle(image,&rb); } else if( format->imagemode == MS_IMAGEMODE_INT16 ) { nBands = format->bands; eDataType = GDT_Int16; } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { nBands = format->bands; eDataType = GDT_Float32; } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { nBands = format->bands; eDataType = GDT_Byte; } else { #ifdef USE_GD assert( format->imagemode == MS_IMAGEMODE_PC256 && format->renderer == MS_RENDER_WITH_GD ); #else { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "GD not compiled in. This is a bug.", "msSaveImageGDAL()"); return MS_FAILURE; } #endif } /* -------------------------------------------------------------------- */ /* Create a memory dataset which we can use as a source for a */ /* CreateCopy(). */ /* -------------------------------------------------------------------- */ hMemDriver = GDALGetDriverByName( "MEM" ); if( hMemDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find MEM driver.", "msSaveImageGDAL()" ); return MS_FAILURE; } hMemDS = GDALCreate( hMemDriver, "msSaveImageGDAL_temp", image->width, image->height, nBands, eDataType, NULL ); if( hMemDS == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create MEM dataset.", "msSaveImageGDAL()" ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy the gd image into the memory dataset. */ /* -------------------------------------------------------------------- */ for( iLine = 0; iLine < image->height; iLine++ ) { int iBand; for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); if( format->imagemode == MS_IMAGEMODE_INT16 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_16bit + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Int16, 2, 0 ); } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_float + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Float32, 4, 0 ); } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_byte + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Byte, 1, 0 ); } #ifdef USE_GD else if(format->renderer == MS_RENDER_WITH_GD) { gdImagePtr img = (gdImagePtr)image->img.plugin; GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, img->pixels[iLine], image->width, 1, GDT_Byte, 0, 0 ); } #endif else { GByte *pabyData; unsigned char *pixptr = NULL; assert( rb.type == MS_BUFFER_BYTE_RGBA ); switch(iBand) { case 0: pixptr = rb.data.rgba.r; break; case 1: pixptr = rb.data.rgba.g; break; case 2: pixptr = rb.data.rgba.b; break; case 3: pixptr = rb.data.rgba.a; break; } assert(pixptr); if( pixptr == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Missing RGB or A buffer.\n", "msSaveImageGDAL()" ); return MS_FAILURE; } pabyData = (GByte *)(pixptr + iLine*rb.data.rgba.row_step); if( rb.data.rgba.a == NULL || iBand == 3 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyData, image->width, 1, GDT_Byte, rb.data.rgba.pixel_step, 0 ); } else { /* We need to un-pre-multiple RGB by alpha. */ GByte *pabyUPM = (GByte*) malloc(image->width); GByte *pabyAlpha= (GByte *)(rb.data.rgba.a + iLine*rb.data.rgba.row_step); int i; for( i = 0; i < image->width; i++ ) { int alpha = pabyAlpha[i*rb.data.rgba.pixel_step]; if( alpha == 0 ) pabyUPM[i] = 0; else { int result = (pabyData[i*rb.data.rgba.pixel_step] * 255) / alpha; if( result > 255 ) result = 255; pabyUPM[i] = result; } } GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyUPM, image->width, 1, GDT_Byte, 1, 0 ); free( pabyUPM ); } } } } if( pabyAlphaLine != NULL ) free( pabyAlphaLine ); /* -------------------------------------------------------------------- */ /* Attach the palette if appropriate. */ /* -------------------------------------------------------------------- */ #ifdef USE_GD if( format->renderer == MS_RENDER_WITH_GD ) { GDALColorEntry sEntry; int iColor; GDALColorTableH hCT; gdImagePtr img = (gdImagePtr)image->img.plugin; hCT = GDALCreateColorTable( GPI_RGB ); for( iColor = 0; iColor < img->colorsTotal; iColor++ ) { sEntry.c1 = img->red[iColor]; sEntry.c2 = img->green[iColor]; sEntry.c3 = img->blue[iColor]; if( iColor == gdImageGetTransparent( img ) ) sEntry.c4 = 0; else if( iColor == 0 && gdImageGetTransparent( img ) == -1 && format->transparent ) sEntry.c4 = 0; else sEntry.c4 = 255; GDALSetColorEntry( hCT, iColor, &sEntry ); } GDALSetRasterColorTable( GDALGetRasterBand( hMemDS, 1 ), hCT ); GDALDestroyColorTable( hCT ); } else #endif if( format->imagemode == MS_IMAGEMODE_RGB ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 4 ), GCI_AlphaBand ); } /* -------------------------------------------------------------------- */ /* Assign the projection and coordinate system to the memory */ /* dataset. */ /* -------------------------------------------------------------------- */ if( map != NULL ) { char *pszWKT; GDALSetGeoTransform( hMemDS, map->gt.geotransform ); pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { GDALSetProjection( hMemDS, pszWKT ); msFree( pszWKT ); } } /* -------------------------------------------------------------------- */ /* Possibly assign a nodata value. */ /* -------------------------------------------------------------------- */ if( msGetOutputFormatOption(format,"NULLVALUE",NULL) != NULL ) { int iBand; const char *nullvalue = msGetOutputFormatOption(format, "NULLVALUE",NULL); for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); GDALSetRasterNoDataValue( hBand, atof(nullvalue) ); } } /* -------------------------------------------------------------------- */ /* Try to save resolution in the output file. */ /* -------------------------------------------------------------------- */ if( image->resolution > 0 ) { char res[30]; sprintf( res, "%lf", image->resolution ); GDALSetMetadataItem( hMemDS, "TIFFTAG_XRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_YRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_RESOLUTIONUNIT", "2", NULL ); } /* -------------------------------------------------------------------- */ /* Create a disk image in the selected output format from the */ /* memory image. */ /* -------------------------------------------------------------------- */ papszOptions = (char**)calloc(sizeof(char *),(format->numformatoptions+1)); if (papszOptions == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", (unsigned int)(sizeof(char *)*(format->numformatoptions+1))); return MS_FAILURE; } memcpy( papszOptions, format->formatoptions, sizeof(char *) * format->numformatoptions ); hOutputDS = GDALCreateCopy( hOutputDriver, filename, hMemDS, FALSE, papszOptions, NULL, NULL ); free( papszOptions ); if( hOutputDS == NULL ) { GDALClose( hMemDS ); msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create output %s file.\n%s", "msSaveImageGDAL()", format->driver+5, CPLGetLastErrorMsg() ); return MS_FAILURE; } /* closing the memory DS also frees all associated resources. */ GDALClose( hMemDS ); GDALClose( hOutputDS ); msReleaseLock( TLOCK_GDAL ); /* -------------------------------------------------------------------- */ /* Are we writing license info into the image? */ /* If so, add it to the temp file on disk now. */ /* -------------------------------------------------------------------- */ #ifdef USE_EXEMPI if ( bUseXmp == MS_TRUE ) { if( msXmpWrite(map, filename) == MS_FAILURE ) { /* Something bad happened. */ msSetError( MS_MISCERR, "XMP write to %s failed.\n", "msSaveImageGDAL()", filename); return MS_FAILURE; } } #endif /* -------------------------------------------------------------------- */ /* Is this supposed to be a temporary file? If so, stream to */ /* stdout and delete the file. */ /* -------------------------------------------------------------------- */ if( bFileIsTemporary ) { FILE *fp; unsigned char block[4000]; int bytes_read; if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; /* We aren't sure how far back GDAL exports the VSI*L API, so we only use it if we suspect we need it. But we do need it if holding temporary file in memory. */ fp = VSIFOpenL( filename, "rb" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open %s for streaming to stdout.", "msSaveImageGDAL()", filename ); return MS_FAILURE; } while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 ) msIO_fwrite( block, 1, bytes_read, stdout ); VSIFCloseL( fp ); VSIUnlink( filename ); CleanVSIDir( "/vsimem/msout" ); free( filename ); } return MS_SUCCESS; }
static GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers, OGRSpatialReferenceH hSRS, int bGotBounds, OGREnvelope sEnvelop, GDALDriverH hDriver, const char* pszDest, int nXSize, int nYSize, double dfXRes, double dfYRes, int bTargetAlignedPixels, int nBandCount, GDALDataType eOutputType, char** papszCreationOptions, std::vector<double> adfInitVals, int bNoDataSet, double dfNoData) { int bFirstLayer = TRUE; char* pszWKT = NULL; GDALDatasetH hDstDS = NULL; unsigned int i; for( i = 0; i < ahLayers.size(); i++ ) { OGRLayerH hLayer = ahLayers[i]; if (!bGotBounds) { OGREnvelope sLayerEnvelop; if (OGR_L_GetExtent(hLayer, &sLayerEnvelop, TRUE) != OGRERR_NONE) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot get layer extent"); return NULL; } /* Voluntarily increase the extent by a half-pixel size to avoid */ /* missing points on the border */ if (!bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0) { sLayerEnvelop.MinX -= dfXRes / 2; sLayerEnvelop.MaxX += dfXRes / 2; sLayerEnvelop.MinY -= dfYRes / 2; sLayerEnvelop.MaxY += dfYRes / 2; } if (bFirstLayer) { sEnvelop.MinX = sLayerEnvelop.MinX; sEnvelop.MinY = sLayerEnvelop.MinY; sEnvelop.MaxX = sLayerEnvelop.MaxX; sEnvelop.MaxY = sLayerEnvelop.MaxY; if (hSRS == NULL) hSRS = OGR_L_GetSpatialRef(hLayer); bFirstLayer = FALSE; } else { sEnvelop.MinX = MIN(sEnvelop.MinX, sLayerEnvelop.MinX); sEnvelop.MinY = MIN(sEnvelop.MinY, sLayerEnvelop.MinY); sEnvelop.MaxX = MAX(sEnvelop.MaxX, sLayerEnvelop.MaxX); sEnvelop.MaxY = MAX(sEnvelop.MaxY, sLayerEnvelop.MaxY); } } else { if (bFirstLayer) { if (hSRS == NULL) hSRS = OGR_L_GetSpatialRef(hLayer); bFirstLayer = FALSE; } } } if (dfXRes == 0 && dfYRes == 0) { dfXRes = (sEnvelop.MaxX - sEnvelop.MinX) / nXSize; dfYRes = (sEnvelop.MaxY - sEnvelop.MinY) / nYSize; } else if (bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0) { sEnvelop.MinX = floor(sEnvelop.MinX / dfXRes) * dfXRes; sEnvelop.MaxX = ceil(sEnvelop.MaxX / dfXRes) * dfXRes; sEnvelop.MinY = floor(sEnvelop.MinY / dfYRes) * dfYRes; sEnvelop.MaxY = ceil(sEnvelop.MaxY / dfYRes) * dfYRes; } double adfProjection[6]; adfProjection[0] = sEnvelop.MinX; adfProjection[1] = dfXRes; adfProjection[2] = 0; adfProjection[3] = sEnvelop.MaxY; adfProjection[4] = 0; adfProjection[5] = -dfYRes; if (nXSize == 0 && nYSize == 0) { nXSize = (int)(0.5 + (sEnvelop.MaxX - sEnvelop.MinX) / dfXRes); nYSize = (int)(0.5 + (sEnvelop.MaxY - sEnvelop.MinY) / dfYRes); } hDstDS = GDALCreate(hDriver, pszDest, nXSize, nYSize, nBandCount, eOutputType, papszCreationOptions); if (hDstDS == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s", pszDest); return NULL; } GDALSetGeoTransform(hDstDS, adfProjection); if (hSRS) OSRExportToWkt(hSRS, &pszWKT); if (pszWKT) GDALSetProjection(hDstDS, pszWKT); CPLFree(pszWKT); int iBand; /*if( nBandCount == 3 || nBandCount == 4 ) { for(iBand = 0; iBand < nBandCount; iBand++) { GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1); GDALSetRasterColorInterpretation(hBand, (GDALColorInterp)(GCI_RedBand + iBand)); } }*/ if (bNoDataSet) { for(iBand = 0; iBand < nBandCount; iBand++) { GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1); GDALSetRasterNoDataValue(hBand, dfNoData); } } if (adfInitVals.size() != 0) { for(iBand = 0; iBand < MIN(nBandCount,(int)adfInitVals.size()); iBand++) { GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1); GDALFillRaster(hBand, adfInitVals[iBand], 0); } } return hDstDS; }
/* Matlab Gateway routine */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int nXYSize; double adfGeoTransform[6] = {0,1,0,0,0,1}, adfDstGeoTransform[6]; char *pszSRS_WKT = NULL; char **papszWarpOptions = NULL; GDALDatasetH hSrcDS, hDstDS; GDALDriverH hDriver; GDALRasterBandH hBand; GDALColorTableH hColorTable = NULL; OGRSpatialReference oSrcSRS, oDstSRS; GDALResampleAlg interpMethod = GRA_NearestNeighbour; GDALTransformerFunc pfnTransformer = NULL; CPLErr eErr; GDAL_GCP *pasGCPs = NULL; static int runed_once = FALSE; /* It will be set to true if reaches end of main */ const int *dim_array; int nx, ny, i, j, m, n, c, nBands, registration = 1; int n_dims, typeCLASS, nBytes; char *pszSrcSRS = NULL, *pszSrcWKT = NULL; char *pszDstSRS = NULL, *pszDstWKT = NULL; void *in_data; mxArray *mx_ptr; unsigned char *tmpByte, *outByte; unsigned short int *tmpUI16, *outUI16; short int *tmpI16, *outI16; int *tmpI32, *outI32; int nPixels=0, nLines=0, nForceWidth=0, nForceHeight=0; int nGCPCount = 0, nOrder = 0; unsigned int *tmpUI32, *outUI32; float *tmpF32, *outF32; double *tmpF64, *outF64, *ptr_d; double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0, dfResX=0, dfResY=0; double adfExtent[4]; double dfXRes=0.0, dfYRes=0.0; double dfWarpMemoryLimit = 0.0; double *pdfDstNodata = NULL; char **papszMetadataOptions = NULL; char *tmp, *txt; if (nrhs == 2 && mxIsStruct(prhs[1])) { mx_ptr = mxGetField(prhs[1], 0, "ULx"); if (mx_ptr == NULL) mexErrMsgTxt("GDALWARP 'ULx' field not provided"); ptr_d = mxGetPr(mx_ptr); adfGeoTransform[0] = *ptr_d; mx_ptr = mxGetField(prhs[1], 0, "Xinc"); if (mx_ptr == NULL) mexErrMsgTxt("GDALWARP 'Xinc' field not provided"); ptr_d = mxGetPr(mx_ptr); adfGeoTransform[1] = *ptr_d; mx_ptr = mxGetField(prhs[1], 0, "ULy"); if (mx_ptr == NULL) mexErrMsgTxt("GDALWARP 'ULy' field not provided"); ptr_d = mxGetPr(mx_ptr); adfGeoTransform[3] = *ptr_d; mx_ptr = mxGetField(prhs[1], 0, "Yinc"); if (mx_ptr == NULL) mexErrMsgTxt("GDALWARP 'Yinc' field not provided"); ptr_d = mxGetPr(mx_ptr); adfGeoTransform[5] = -*ptr_d; /* -------- See for resolution requests ------------ */ mx_ptr = mxGetField(prhs[1], 0, "t_size"); if (mx_ptr != NULL) { ptr_d = mxGetPr(mx_ptr); if (mxGetN(mx_ptr) == 2) { nForceWidth = (int)ptr_d[0]; nForceHeight = (int)ptr_d[1]; } else if (mxGetN(mx_ptr) == 1) { /* pick max(nrow,ncol) */ if (mxGetM(prhs[0]) > getNK(prhs[0],1)) nForceHeight = mxGetM(prhs[0]); else nForceWidth = getNK(prhs[0], 1); } else { nForceHeight = mxGetM(prhs[0]); nForceWidth = getNK(prhs[0], 1); } } mx_ptr = mxGetField(prhs[1], 0, "t_res"); if (mx_ptr != NULL) { ptr_d = mxGetPr(mx_ptr); if (mxGetN(mx_ptr) == 2) { dfXRes = ptr_d[0]; dfYRes = ptr_d[1]; } else if (mxGetN(mx_ptr) == 1) { dfXRes = dfYRes = ptr_d[0]; } } /* -------------------------------------------------- */ /* -------- Change Warping cache size? ------------ */ mx_ptr = mxGetField(prhs[1], 0, "wm"); if (mx_ptr != NULL) { ptr_d = mxGetPr(mx_ptr); dfWarpMemoryLimit = *ptr_d * 1024 * 1024; } /* -------------------------------------------------- */ /* -------- Have a nodata value order? -------------- */ mx_ptr = mxGetField(prhs[1], 0, "nodata"); if (mx_ptr != NULL) { pdfDstNodata = mxGetPr(mx_ptr); } /* -------------------------------------------------- */ /* -------- See for projection stuff ---------------- */ mx_ptr = mxGetField(prhs[1], 0, "SrcProjSRS"); if (mx_ptr != NULL) pszSrcSRS = (char *)mxArrayToString(mx_ptr); mx_ptr = mxGetField(prhs[1], 0, "SrcProjWKT"); if (mx_ptr != NULL) pszSrcWKT = (char *)mxArrayToString(mx_ptr); mx_ptr = mxGetField(prhs[1], 0, "DstProjSRS"); if (mx_ptr != NULL) pszDstSRS = (char *)mxArrayToString(mx_ptr); mx_ptr = mxGetField(prhs[1], 0, "DstProjWKT"); if (mx_ptr != NULL) pszDstWKT = (char *)mxArrayToString(mx_ptr); /* -------------------------------------------------- */ /* -------- Do we have GCPs? ----------------------- */ mx_ptr = mxGetField(prhs[1], 0, "gcp"); if (mx_ptr != NULL) { nGCPCount = mxGetM(mx_ptr); if (mxGetN(mx_ptr) != 4) mexErrMsgTxt("GDALWARP: GCPs must be a Mx4 array"); ptr_d = mxGetPr(mx_ptr); pasGCPs = (GDAL_GCP *) mxCalloc( nGCPCount, sizeof(GDAL_GCP) ); GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 ); for (i = 0; i < nGCPCount; i++) { pasGCPs[i].dfGCPPixel = ptr_d[i]; pasGCPs[i].dfGCPLine = ptr_d[i+nGCPCount]; pasGCPs[i].dfGCPX = ptr_d[i+2*nGCPCount]; pasGCPs[i].dfGCPY = ptr_d[i+3*nGCPCount]; pasGCPs[i].dfGCPZ = 0; } } /* ---- Have we an order request? --- */ mx_ptr = mxGetField(prhs[1], 0, "order"); if (mx_ptr != NULL) { ptr_d = mxGetPr(mx_ptr); nOrder = (int)*ptr_d; if (nOrder != -1 || nOrder != 0 || nOrder != 1 || nOrder != 2 || nOrder != 3) nOrder = 0; } /* -------------------------------------------------- */ mx_ptr = mxGetField(prhs[1], 0, "ResampleAlg"); if (mx_ptr != NULL) { txt = (char *)mxArrayToString(mx_ptr); if (!strcmp(txt,"nearest")) interpMethod = GRA_NearestNeighbour; else if (!strcmp(txt,"bilinear")) interpMethod = GRA_Bilinear; else if (!strcmp(txt,"cubic") || !strcmp(txt,"bicubic")) interpMethod = GRA_Cubic; else if (!strcmp(txt,"spline")) interpMethod = GRA_CubicSpline; } /* If grid limits were in grid registration, convert them to pixel reg */ mx_ptr = mxGetField(prhs[1], 0, "Reg"); if (mx_ptr != NULL) { ptr_d = mxGetPr(mx_ptr); registration = (int)ptr_d[0]; } if (registration == 0) { adfGeoTransform[0] -= adfGeoTransform[1]/2.; adfGeoTransform[3] -= adfGeoTransform[5]/2.; } } else { mexPrintf("Usage: B = gdalwarp_mex(IMG,HDR_STRUCT)\n\n"); mexPrintf("\tIMG -> is a Mx2 or Mx3 array with an grid/image data to reproject\n"); mexPrintf("\tHDR_STRUCT -> is a structure with the following fields:\n"); mexPrintf("\t\t'ULx' X coordinate of the uper left corner\n"); mexPrintf("\t\t'ULy' Y coordinate of the uper left corner\n"); mexPrintf("\t\t'Xinc' distance between columns in target grid/image coordinates\n"); mexPrintf("\t\t'Yinc' distance between rows in target grid/image coordinates\n"); mexPrintf("\t\t'SrcProjSRS', 'SrcProjWKT' -> Source projection string\n"); mexPrintf("\t\t'DstProjSRS', 'DstProjWKT' -> Target projection string\n"); mexPrintf("\t\t\tSRS stands for a string of the type used by proj4\n"); mexPrintf("\t\t\tWKT stands for a string on the 'Well Known Text' format\n\n"); mexPrintf("\t\t\tIf one of the Src or Dst fields is absent a GEOGRAPHIC WGS84 is assumed\n"); mexPrintf("\nOPTIONS\n"); mexPrintf("\t\t'gcp' a [Mx4] array with Ground Control Points\n"); mexPrintf("\t\t't_size' a [width height] vector to set output file size in pixels\n"); mexPrintf("\t\t't_res' a [xres yres] vector to set output file resolution (in target georeferenced units)\n"); mexPrintf("\t\t'wm' amount of memory (in megabytes) that the warp API is allowed to use for caching\n"); mexPrintf("\t\t'nodata' Set nodata values for output bands.\n"); mexPrintf("\t\t'ResampleAlg' To set up the algorithm used during warp operation. Options are: \n"); mexPrintf("\t\t\t'nearest' Use nearest neighbour resampling (default, fastest algorithm, worst interpolation quality).\n"); mexPrintf("\t\t\t'bilinear' Use bilinear resampling.\n"); mexPrintf("\t\t\t'cubic' Use cubic resampling.\n"); mexPrintf("\t\t\t'spline' Use cubic spline resampling.\n\n"); if (!runed_once) /* Do next call only at first time this MEX is loaded */ GDALAllRegister(); mexPrintf( "The following format drivers are configured and support Create() method:\n" ); for( i = 0; i < GDALGetDriverCount(); i++ ) { hDriver = GDALGetDriver(i); if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL) mexPrintf("%s: %s\n", GDALGetDriverShortName(hDriver), GDALGetDriverLongName(hDriver)); } return; } n_dims = mxGetNumberOfDimensions(prhs[0]); dim_array=mxGetDimensions(prhs[0]); ny = dim_array[0]; nx = dim_array[1]; nBands = dim_array[2]; if (n_dims == 2) /* Otherwise it would stay undefined */ nBands = 1; /* Find out in which data type was given the input array */ if (mxIsUint8(prhs[0])) { typeCLASS = GDT_Byte; nBytes = 1; outByte = (unsigned char *)mxMalloc (nx*ny * sizeof(unsigned char)); } else if (mxIsUint16(prhs[0])) { typeCLASS = GDT_UInt16; nBytes = 2; outUI16 = (unsigned short int *)mxMalloc (nx*ny * sizeof(short int)); } else if (mxIsInt16(prhs[0])) { typeCLASS = GDT_Int16; nBytes = 2; outI16 = (short int *)mxMalloc (nx*ny * sizeof(short int)); } else if (mxIsInt32(prhs[0])) { typeCLASS = GDT_Int32; nBytes = 4; outI32 = (int *)mxMalloc (nx*ny * sizeof(int)); } else if (mxIsUint32(prhs[0])) { typeCLASS = GDT_UInt32; nBytes = 4; outUI32 = (unsigned int *)mxMalloc (nx*ny * sizeof(int)); } else if (mxIsSingle(prhs[0])) { typeCLASS = GDT_Float32; nBytes = 4; outF32 = (float *)mxMalloc (nx*ny * sizeof(float)); } else if (mxIsDouble(prhs[0])) { typeCLASS = GDT_Float64; nBytes = 8; outF64 = (double *)mxMalloc (nx*ny * sizeof(double)); } else mexErrMsgTxt("GDALWARP Unknown input data class!"); in_data = (void *)mxGetData(prhs[0]); if (!runed_once) /* Do next call only at first time this MEX is loaded */ GDALAllRegister(); hDriver = GDALGetDriverByName( "MEM" ); hSrcDS = GDALCreate( hDriver, "mem", nx, ny, nBands, (GDALDataType)typeCLASS, NULL ); if (hSrcDS == NULL) { mexPrintf ("GDALOpen failed - %d\n%s\n", CPLGetLastErrorNo(), CPLGetLastErrorMsg()); return; } GDALSetGeoTransform( hSrcDS, adfGeoTransform ); /* ---------- Set the Source projection ---------------------------- */ /* If it was not provided assume it is Geog WGS84 */ if (pszSrcSRS == NULL && pszSrcWKT == NULL) oSrcSRS.SetWellKnownGeogCS( "WGS84" ); else if (pszSrcWKT != NULL) oSrcSRS.importFromWkt( &pszSrcWKT ); else { if( oSrcSRS.SetFromUserInput( pszSrcSRS ) != OGRERR_NONE ) mexErrMsgTxt("GDAL_WARP_MEX: Translating source SRS failed."); } if (pszSrcWKT == NULL) oSrcSRS.exportToWkt( &pszSrcWKT ); GDALSetProjection( hSrcDS, pszSrcWKT ); //pszSrcWKT = (char *)GDALGetProjectionRef( hSrcDS ); CPLAssert( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0 ); /* ------------------------------------------------------------------ */ /* -------------- Copy input data into the hSrcDS dataset ----------- */ for (i = 1; i <= nBands; i++) { hBand = GDALGetRasterBand( hSrcDS, i ); nXYSize = (i-1)*nx*ny; switch( typeCLASS ) { case GDT_Byte: tmpByte = (unsigned char *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outByte[c++] = tmpByte[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outByte, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; case GDT_UInt16: tmpUI16 = (unsigned short int *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outUI16[c++] = tmpUI16[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outUI16, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; case GDT_Int16: tmpI16 = (short int *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outI16[c++] = tmpI16[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outI16, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; case GDT_UInt32: tmpUI32 = (unsigned int *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outUI32[c++] = tmpUI32[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outUI32, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; case GDT_Int32: tmpI32 = (int *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outI32[c++] = tmpI32[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outI32, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; case GDT_Float32: tmpF32 = (float *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outF32[c++] = tmpF32[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outF32, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; case GDT_Float64: tmpF64 = (double *)in_data; for (m = ny-1, c = 0; m >= 0; m--) for (n = 0; n < nx; n++) outF64[c++] = tmpF64[m + n*ny + nXYSize]; GDALRasterIO( hBand, GF_Write, 0, 0, nx, ny,outF64, nx, ny, (GDALDataType)typeCLASS, 0, 0 ); break; } } /* ---------- Set up the Target coordinate system ------------------- */ /* If it was not provided assume it is Geog WGS84 */ CPLErrorReset(); if (pszDstSRS == NULL && pszDstWKT == NULL) oDstSRS.SetWellKnownGeogCS( "WGS84" ); else if (pszDstWKT != NULL) oDstSRS.importFromWkt( &pszDstWKT ); else { if( oDstSRS.SetFromUserInput( pszDstSRS ) != OGRERR_NONE ) mexErrMsgTxt("GDAL_WARP_MEX: Translating target SRS failed."); } if (pszDstWKT == NULL) oDstSRS.exportToWkt( &pszDstWKT ); /* ------------------------------------------------------------------ */ if ( nGCPCount != 0 ) { if (GDALSetGCPs(hSrcDS, nGCPCount, pasGCPs, "") != CE_None) mexPrintf("GDALWARP WARNING: writing GCPs failed.\n"); } /* Create a transformer that maps from source pixel/line coordinates to destination georeferenced coordinates (not destination pixel line) We do that by omitting the destination dataset handle (setting it to NULL). */ void *hTransformArg; hTransformArg = GDALCreateGenImgProjTransformer(hSrcDS, pszSrcWKT, NULL, pszDstWKT, nGCPCount == 0 ? FALSE : TRUE, 0, nOrder); if( hTransformArg == NULL ) mexErrMsgTxt("GDALTRANSFORM: Generating transformer failed."); GDALTransformerInfo *psInfo = (GDALTransformerInfo*)hTransformArg; /* -------------------------------------------------------------------------- */ /* Get approximate output georeferenced bounds and resolution for file /* -------------------------------------------------------------------------- */ if (GDALSuggestedWarpOutput2(hSrcDS, GDALGenImgProjTransform, hTransformArg, adfDstGeoTransform, &nPixels, &nLines, adfExtent, 0) != CE_None ) { GDALClose(hSrcDS); mexErrMsgTxt("GDALWARP: GDALSuggestedWarpOutput2 failed."); } if (CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", NULL ) == NULL) { double MinX = adfExtent[0]; double MaxX = adfExtent[2]; double MaxY = adfExtent[3]; double MinY = adfExtent[1]; int bSuccess = TRUE; /* Check that the the edges of the target image are in the validity area */ /* of the target projection */ #define N_STEPS 20 for (i = 0; i <= N_STEPS && bSuccess; i++) { for (j = 0; j <= N_STEPS && bSuccess; j++) { double dfRatioI = i * 1.0 / N_STEPS; double dfRatioJ = j * 1.0 / N_STEPS; double expected_x = (1 - dfRatioI) * MinX + dfRatioI * MaxX; double expected_y = (1 - dfRatioJ) * MinY + dfRatioJ * MaxY; double x = expected_x; double y = expected_y; double z = 0; /* Target SRS coordinates to source image pixel coordinates */ if (!psInfo->pfnTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess) bSuccess = FALSE; /* Source image pixel coordinates to target SRS coordinates */ if (!psInfo->pfnTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess) bSuccess = FALSE; if (fabs(x - expected_x) > (MaxX - MinX) / nPixels || fabs(y - expected_y) > (MaxY - MinY) / nLines) bSuccess = FALSE; } } /* If not, retry with CHECK_WITH_INVERT_PROJ=TRUE that forces ogrct.cpp */ /* to check the consistency of each requested projection result with the */ /* invert projection */ if (!bSuccess) { CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" ); CPLDebug("WARP", "Recompute out extent with CHECK_WITH_INVERT_PROJ=TRUE"); if (GDALSuggestedWarpOutput2(hSrcDS, GDALGenImgProjTransform, hTransformArg, adfDstGeoTransform, &nPixels, &nLines, adfExtent, 0) != CE_None ) { GDALClose(hSrcDS); mexErrMsgTxt("GDALWARO: GDALSuggestedWarpOutput2 failed."); } } } /* -------------------------------------------------------------------- */ /* Expand the working bounds to include this region, ensure the */ /* working resolution is no more than this resolution. */ /* -------------------------------------------------------------------- */ if( dfMaxX == 0.0 && dfMinX == 0.0 ) { dfMinX = adfExtent[0]; dfMaxX = adfExtent[2]; dfMaxY = adfExtent[3]; dfMinY = adfExtent[1]; dfResX = adfDstGeoTransform[1]; dfResY = ABS(adfDstGeoTransform[5]); } else { dfMinX = MIN(dfMinX,adfExtent[0]); dfMaxX = MAX(dfMaxX,adfExtent[2]); dfMaxY = MAX(dfMaxY,adfExtent[3]); dfMinY = MIN(dfMinY,adfExtent[1]); dfResX = MIN(dfResX,adfDstGeoTransform[1]); dfResY = MIN(dfResY,ABS(adfDstGeoTransform[5])); } GDALDestroyGenImgProjTransformer( hTransformArg ); /* -------------------------------------------------------------------- */ /* Turn the suggested region into a geotransform and suggested */ /* number of pixels and lines. */ /* -------------------------------------------------------------------- */ adfDstGeoTransform[0] = dfMinX; adfDstGeoTransform[1] = dfResX; adfDstGeoTransform[2] = 0.0; adfDstGeoTransform[3] = dfMaxY; adfDstGeoTransform[4] = 0.0; adfDstGeoTransform[5] = -1 * dfResY; nPixels = (int) ((dfMaxX - dfMinX) / dfResX + 0.5); nLines = (int) ((dfMaxY - dfMinY) / dfResY + 0.5); /* -------------------------------------------------------------------- */ /* Did the user override some parameters? */ /* -------------------------------------------------------------------- */ if( dfXRes != 0.0 && dfYRes != 0.0 ) { dfMinX = adfDstGeoTransform[0]; dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels; dfMaxY = adfDstGeoTransform[3]; dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines; nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes); nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes); adfDstGeoTransform[0] = dfMinX; adfDstGeoTransform[3] = dfMaxY; adfDstGeoTransform[1] = dfXRes; adfDstGeoTransform[5] = -dfYRes; } else if( nForceWidth != 0 && nForceHeight != 0 ) { dfXRes = (dfMaxX - dfMinX) / nForceWidth; dfYRes = (dfMaxY - dfMinY) / nForceHeight; adfDstGeoTransform[0] = dfMinX; adfDstGeoTransform[3] = dfMaxY; adfDstGeoTransform[1] = dfXRes; adfDstGeoTransform[5] = -dfYRes; nPixels = nForceWidth; nLines = nForceHeight; } else if( nForceWidth != 0) { dfXRes = (dfMaxX - dfMinX) / nForceWidth; dfYRes = dfXRes; adfDstGeoTransform[0] = dfMinX; adfDstGeoTransform[3] = dfMaxY; adfDstGeoTransform[1] = dfXRes; adfDstGeoTransform[5] = -dfYRes; nPixels = nForceWidth; nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes); } else if( nForceHeight != 0) { dfYRes = (dfMaxY - dfMinY) / nForceHeight; dfXRes = dfYRes; adfDstGeoTransform[0] = dfMinX; adfDstGeoTransform[3] = dfMaxY; adfDstGeoTransform[1] = dfXRes; adfDstGeoTransform[5] = -dfYRes; nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes); nLines = nForceHeight; } /* --------------------- Create the output --------------------------- */ hDstDS = GDALCreate( hDriver, "mem", nPixels, nLines, GDALGetRasterCount(hSrcDS), (GDALDataType)typeCLASS, NULL ); CPLAssert( hDstDS != NULL ); /* -------------- Write out the projection definition ---------------- */ GDALSetProjection( hDstDS, pszDstWKT ); GDALSetGeoTransform( hDstDS, adfDstGeoTransform ); /* --------------------- Setup warp options -------------------------- */ GDALWarpOptions *psWO = GDALCreateWarpOptions(); psWO->hSrcDS = hSrcDS; psWO->hDstDS = hDstDS; psWO->nBandCount = nBands; psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount * sizeof(int) ); psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount * sizeof(int) ); for( i = 0; i < nBands; i++ ) { psWO->panSrcBands[i] = i+1; psWO->panDstBands[i] = i+1; } if( dfWarpMemoryLimit != 0.0 ) psWO->dfWarpMemoryLimit = dfWarpMemoryLimit; /* --------------------- Setup the Resampling Algo ------------------- */ psWO->eResampleAlg = interpMethod; /* --------------------- Setup NODATA options ------------------------ */ papszWarpOptions = CSLSetNameValue(papszWarpOptions, "INIT_DEST", "NO_DATA" ); if ( pdfDstNodata == NULL && (typeCLASS == GDT_Float32 || typeCLASS == GDT_Float64) ) { pdfDstNodata = (double *) mxCalloc((size_t)1, sizeof(double)); *pdfDstNodata = mxGetNaN(); } else if (pdfDstNodata != NULL) { #define CLAMP(val,type,minval,maxval) \ do { if (val < minval) { val = minval; } \ else if (val > maxval) { val = maxval; } \ else if (val != (type)val) { val = (type)(val + 0.5); } } \ while(0) switch( typeCLASS ) { case GDT_Byte: CLAMP(pdfDstNodata[0], GByte, 0.0, 255.0); break; case GDT_UInt16: CLAMP(pdfDstNodata[0], GInt16, -32768.0, 32767.0); break; case GDT_Int16: CLAMP(pdfDstNodata[0], GUInt16, 0.0, 65535.0); break; case GDT_UInt32: CLAMP(pdfDstNodata[0], GInt32, -2147483648.0, 2147483647.0); break; case GDT_Int32: CLAMP(pdfDstNodata[0], GUInt32, 0.0, 4294967295.0); break; default: break; } } psWO->papszWarpOptions = CSLDuplicate(papszWarpOptions); if (pdfDstNodata != NULL) { psWO->padfDstNoDataReal = (double *) CPLMalloc(psWO->nBandCount*sizeof(double)); psWO->padfDstNoDataImag = (double *) CPLMalloc(psWO->nBandCount*sizeof(double)); for (i = 0; i < nBands; i++) { psWO->padfDstNoDataReal[i] = pdfDstNodata[0]; psWO->padfDstNoDataImag[i] = 0.0; GDALSetRasterNoDataValue( GDALGetRasterBand(hDstDS, i+1), pdfDstNodata[0]); } } /* ------------ Establish reprojection transformer ------------------- */ psWO->pTransformerArg = GDALCreateGenImgProjTransformer( hSrcDS, GDALGetProjectionRef(hSrcDS), hDstDS, GDALGetProjectionRef(hDstDS), nGCPCount == 0 ? FALSE : TRUE, 0.0, nOrder ); psWO->pfnTransformer = GDALGenImgProjTransform; /* ----------- Initialize and execute the warp operation ------------- */ GDALWarpOperation oOperation; oOperation.Initialize( psWO ); eErr = oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ); CPLAssert( eErr == CE_None ); GDALDestroyGenImgProjTransformer( psWO->pTransformerArg ); GDALDestroyWarpOptions( psWO ); GDALClose( hSrcDS ); /* ------------ Free memory used to fill the hSrcDS dataset ---------- */ switch( typeCLASS ) { case GDT_Byte: mxFree((void *)outByte); break; case GDT_UInt16: mxFree((void *)outUI16); break; case GDT_Int16: mxFree((void *)outI16); break; case GDT_UInt32: mxFree((void *)outUI32); break; case GDT_Int32: mxFree((void *)outI32); break; case GDT_Float32: mxFree((void *)outF32); break; case GDT_Float64: mxFree((void *)outF64); break; } int out_dims[3]; out_dims[0] = nLines; out_dims[1] = nPixels; out_dims[2] = nBands; plhs[0] = mxCreateNumericArray (n_dims,out_dims,mxGetClassID(prhs[0]), mxREAL); tmp = (char *)mxCalloc(nPixels * nLines, nBytes); /* ------ Allocate memory to be used in filling the hDstDS dataset ---- */ switch( typeCLASS ) { case GDT_Byte: outByte = (unsigned char *)mxGetData(plhs[0]); break; case GDT_UInt16: outUI16 = (unsigned short int *)mxGetData(plhs[0]); break; case GDT_Int16: outI16 = (short int *)mxGetData(plhs[0]); break; case GDT_UInt32: outUI32 = (unsigned int *)mxGetData(plhs[0]); break; case GDT_Int32: outI32 = (int *)mxGetData(plhs[0]); break; case GDT_Float32: outF32 = (float *)mxGetData(plhs[0]); break; case GDT_Float64: outF64 = (double *)mxGetData(plhs[0]); break; } /* ----------- Copy the output hSrcDS dataset data into plhs ---------- */ for (i = 1; i <= nBands; i++) { hBand = GDALGetRasterBand( hDstDS, i ); GDALRasterIO( hBand, GF_Read, 0, 0, nPixels, nLines, tmp, nPixels, nLines, (GDALDataType)typeCLASS, 0, 0 ); nXYSize = (i-1) * nPixels * nLines; switch( typeCLASS ) { case GDT_Byte: for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outByte[m + n*nLines + nXYSize] = tmp[c++]; break; case GDT_UInt16: tmpUI16 = (GUInt16 *) tmp; for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outUI16[m + n*nLines + nXYSize] = tmpUI16[c++]; break; case GDT_Int16: tmpI16 = (GInt16 *) tmp; for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outI16[m + n*nLines + nXYSize] = tmpI16[c++]; break; case GDT_UInt32: tmpUI32 = (GUInt32 *) tmp; for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outUI32[m + n*nLines + nXYSize] = tmpUI32[c++]; break; case GDT_Int32: tmpI32 = (GInt32 *) tmp; for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outI32[m + n*nLines + nXYSize] = tmpI32[c++]; break; case GDT_Float32: tmpF32 = (float *) tmp; for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outF32[m + n*nLines + nXYSize] = tmpF32[c++]; break; case GDT_Float64: tmpF64 = (double *) tmp; for (m = nLines-1, c = 0; m >= 0; m--) for (n = 0; n < nPixels; n++) outF64[m + n*nLines + nXYSize] = tmpF64[c++]; break; } } mxFree(tmp); if (nGCPCount) { GDALDeinitGCPs( nGCPCount, pasGCPs ); /* makes this mex crash in the next call - Is it still true??? */ mxFree((void *) pasGCPs ); } if (nlhs == 2) plhs[1] = populate_metadata_struct (hDstDS, 1); runed_once = TRUE; /* Signals that next call won't need to call GDALAllRegister() again */ /*GDALDestroyDriverManager(); OGRFree(pszDstWKT);*/ GDALClose( hDstDS ); CSLDestroy( papszWarpOptions ); if (pszDstWKT && strlen(pszDstWKT) > 1 ) OGRFree(pszDstWKT); if (pszSrcWKT && strlen(pszSrcWKT) > 1 ) OGRFree(pszSrcWKT); }