int gv_raster_rasterize_shapes( GvRaster *raster, int shape_count, GvShape **shapes, double dfBurnValue, int bFillShort ) { GDALDataType eType; int nYChunkSize, nScanlineBytes; unsigned char *pabyChunkBuf; int iY; GvRasterChangeInfo change_info; /* -------------------------------------------------------------------- */ /* Establish a chunksize to operate on. The larger the chunk */ /* size the less times we need to make a pass through all the */ /* shapes. */ /* -------------------------------------------------------------------- */ if( raster->gdal_type == GDT_Byte ) eType = GDT_Byte; else eType = GDT_Float32; nScanlineBytes = raster->width * (GDALGetDataTypeSize(eType)/8); nYChunkSize = 10000000 / nScanlineBytes; if( nYChunkSize > raster->height ) nYChunkSize = raster->height; pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes); if( pabyChunkBuf == NULL ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to allocate rasterization buffer." ); return FALSE; } /* ==================================================================== */ /* Loop over image in designated chunks. */ /* ==================================================================== */ for( iY = 0; iY < raster->height; iY += nYChunkSize ) { int nThisYChunkSize; int iShape; nThisYChunkSize = nYChunkSize; if( nThisYChunkSize + iY > raster->height ) nThisYChunkSize = raster->height - iY; GDALRasterIO( raster->gdal_band, GF_Read, 0, iY, raster->width, nThisYChunkSize, pabyChunkBuf, raster->width, nThisYChunkSize, eType, 0, 0 ); for( iShape = 0; iShape < shape_count; iShape++ ) { if (bFillShort < 2 ) gv_rasterize_one_shape( pabyChunkBuf, iY, nThisYChunkSize, eType, raster, shapes[iShape], dfBurnValue, bFillShort ); else gv_rasterize_new_one_shape( pabyChunkBuf, iY, nThisYChunkSize, eType, raster, shapes[iShape], dfBurnValue, bFillShort - 2 ); } GDALRasterIO( raster->gdal_band, GF_Write, 0, iY, raster->width, nThisYChunkSize, pabyChunkBuf, raster->width, nThisYChunkSize, eType, 0, 0 ); } VSIFree( pabyChunkBuf ); /* -------------------------------------------------------------------- */ /* Invalidate the raster to force a reload. */ /* -------------------------------------------------------------------- */ change_info.change_type = GV_CHANGE_REPLACE; change_info.x_off = 0; change_info.y_off = 0; change_info.width = raster->width; change_info.height = raster->height; gv_data_changed( GV_DATA(raster), &change_info ); return TRUE; }
CPLErr GDALRasterizeGeometries( GDALDatasetH hDS, int nBandCount, int *panBandList, int nGeomCount, OGRGeometryH *pahGeometries, GDALTransformerFunc pfnTransformer, void *pTransformArg, double *padfGeomBurnValue, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg ) { GDALDataType eType; int nYChunkSize, nScanlineBytes; unsigned char *pabyChunkBuf; int iY; GDALDataset *poDS = (GDALDataset *) hDS; if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; /* -------------------------------------------------------------------- */ /* Do some rudimentary arg checking. */ /* -------------------------------------------------------------------- */ if( nBandCount == 0 || nGeomCount == 0 ) return CE_None; // prototype band. GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] ); if (poBand == NULL) return CE_Failure; int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE ); const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" ); GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue; if( pszOpt ) { if( EQUAL(pszOpt,"Z")) eBurnValueSource = GBV_Z; /*else if( EQUAL(pszOpt,"M")) eBurnValueSource = GBV_M;*/ } /* -------------------------------------------------------------------- */ /* If we have no transformer, assume the geometries are in file */ /* georeferenced coordinates, and create a transformer to */ /* convert that to pixel/line coordinates. */ /* */ /* We really just need to apply an affine transform, but for */ /* simplicity we use the more general GenImgProjTransformer. */ /* -------------------------------------------------------------------- */ int bNeedToFreeTransformer = FALSE; if( pfnTransformer == NULL ) { bNeedToFreeTransformer = TRUE; pTransformArg = GDALCreateGenImgProjTransformer( NULL, NULL, hDS, NULL, FALSE, 0.0, 0); pfnTransformer = GDALGenImgProjTransform; } /* -------------------------------------------------------------------- */ /* Establish a chunksize to operate on. The larger the chunk */ /* size the less times we need to make a pass through all the */ /* shapes. */ /* -------------------------------------------------------------------- */ if( poBand->GetRasterDataType() == GDT_Byte ) eType = GDT_Byte; else eType = GDT_Float32; nScanlineBytes = nBandCount * poDS->GetRasterXSize() * (GDALGetDataTypeSize(eType)/8); nYChunkSize = 10000000 / nScanlineBytes; if( nYChunkSize > poDS->GetRasterYSize() ) nYChunkSize = poDS->GetRasterYSize(); pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes); if( pabyChunkBuf == NULL ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to allocate rasterization buffer." ); return CE_Failure; } /* ==================================================================== */ /* Loop over image in designated chunks. */ /* ==================================================================== */ CPLErr eErr = CE_None; pfnProgress( 0.0, NULL, pProgressArg ); for( iY = 0; iY < poDS->GetRasterYSize() && eErr == CE_None; iY += nYChunkSize ) { int nThisYChunkSize; int iShape; nThisYChunkSize = nYChunkSize; if( nThisYChunkSize + iY > poDS->GetRasterYSize() ) nThisYChunkSize = poDS->GetRasterYSize() - iY; eErr = poDS->RasterIO(GF_Read, 0, iY, poDS->GetRasterXSize(), nThisYChunkSize, pabyChunkBuf,poDS->GetRasterXSize(),nThisYChunkSize, eType, nBandCount, panBandList, 0, 0, 0 ); if( eErr != CE_None ) break; for( iShape = 0; iShape < nGeomCount; iShape++ ) { gv_rasterize_one_shape( pabyChunkBuf, iY, poDS->GetRasterXSize(), nThisYChunkSize, nBandCount, eType, bAllTouched, (OGRGeometry *) pahGeometries[iShape], padfGeomBurnValue + iShape*nBandCount, eBurnValueSource, pfnTransformer, pTransformArg ); } eErr = poDS->RasterIO( GF_Write, 0, iY, poDS->GetRasterXSize(), nThisYChunkSize, pabyChunkBuf, poDS->GetRasterXSize(), nThisYChunkSize, eType, nBandCount, panBandList, 0, 0, 0 ); if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()), "", pProgressArg ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); eErr = CE_Failure; } } /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ VSIFree( pabyChunkBuf ); if( bNeedToFreeTransformer ) GDALDestroyTransformer( pTransformArg ); return eErr; }
CPLErr GDALRasterizeLayers( GDALDatasetH hDS, int nBandCount, int *panBandList, int nLayerCount, OGRLayerH *pahLayers, GDALTransformerFunc pfnTransformer, void *pTransformArg, double *padfLayerBurnValues, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg ) { GDALDataType eType; unsigned char *pabyChunkBuf; GDALDataset *poDS = (GDALDataset *) hDS; if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; /* -------------------------------------------------------------------- */ /* Do some rudimentary arg checking. */ /* -------------------------------------------------------------------- */ if( nBandCount == 0 || nLayerCount == 0 ) return CE_None; // prototype band. GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] ); if (poBand == NULL) return CE_Failure; int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE ); const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" ); GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue; if( pszOpt ) { if( EQUAL(pszOpt,"Z")) eBurnValueSource = GBV_Z; /*else if( EQUAL(pszOpt,"M")) eBurnValueSource = GBV_M;*/ } /* -------------------------------------------------------------------- */ /* Establish a chunksize to operate on. The larger the chunk */ /* size the less times we need to make a pass through all the */ /* shapes. */ /* -------------------------------------------------------------------- */ int nYChunkSize, nScanlineBytes; const char *pszYChunkSize = CSLFetchNameValue( papszOptions, "CHUNKYSIZE" ); if( poBand->GetRasterDataType() == GDT_Byte ) eType = GDT_Byte; else eType = GDT_Float32; nScanlineBytes = nBandCount * poDS->GetRasterXSize() * (GDALGetDataTypeSize(eType)/8); if ( pszYChunkSize && (nYChunkSize = atoi(pszYChunkSize)) ) ; else nYChunkSize = GDALGetCacheMax() / nScanlineBytes; if( nYChunkSize < 1 ) nYChunkSize = 1; if( nYChunkSize > poDS->GetRasterYSize() ) nYChunkSize = poDS->GetRasterYSize(); pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes); if( pabyChunkBuf == NULL ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to allocate rasterization buffer." ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Read the image once for all layers if user requested to render */ /* the whole raster in single chunk. */ /* -------------------------------------------------------------------- */ if ( nYChunkSize == poDS->GetRasterYSize() ) { if ( poDS->RasterIO( GF_Read, 0, 0, poDS->GetRasterXSize(), nYChunkSize, pabyChunkBuf, poDS->GetRasterXSize(), nYChunkSize, eType, nBandCount, panBandList, 0, 0, 0 ) != CE_None ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to read buffer." ); CPLFree( pabyChunkBuf ); return CE_Failure; } } /* ==================================================================== */ /* Read the specified layers transfoming and rasterizing */ /* geometries. */ /* ==================================================================== */ CPLErr eErr = CE_None; int iLayer; const char *pszBurnAttribute = CSLFetchNameValue( papszOptions, "ATTRIBUTE" ); pfnProgress( 0.0, NULL, pProgressArg ); for( iLayer = 0; iLayer < nLayerCount; iLayer++ ) { int iBurnField = -1; double *padfBurnValues = NULL; OGRLayer *poLayer = (OGRLayer *) pahLayers[iLayer]; if ( !poLayer ) { CPLError( CE_Warning, CPLE_AppDefined, "Layer element number %d is NULL, skipping.\n", iLayer ); continue; } /* -------------------------------------------------------------------- */ /* If the layer does not contain any features just skip it. */ /* Do not force the feature count, so if driver doesn't know */ /* exact number of features, go down the normal way. */ /* -------------------------------------------------------------------- */ if ( poLayer->GetFeatureCount(FALSE) == 0 ) continue; if ( pszBurnAttribute ) { iBurnField = poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute ); if ( iBurnField == -1 ) { CPLError( CE_Warning, CPLE_AppDefined, "Failed to find field %s on layer %s, skipping.\n", pszBurnAttribute, poLayer->GetLayerDefn()->GetName() ); continue; } } else padfBurnValues = padfLayerBurnValues + iLayer * nBandCount; /* -------------------------------------------------------------------- */ /* If we have no transformer, create the one from input file */ /* projection. Note that each layer can be georefernced */ /* separately. */ /* -------------------------------------------------------------------- */ int bNeedToFreeTransformer = FALSE; if( pfnTransformer == NULL ) { char *pszProjection = NULL; bNeedToFreeTransformer = TRUE; OGRSpatialReference *poSRS = poLayer->GetSpatialRef(); if ( !poSRS ) { CPLError( CE_Warning, CPLE_AppDefined, "Failed to fetch spatial reference on layer %s " "to build transformer, assuming matching coordinate systems.\n", poLayer->GetLayerDefn()->GetName() ); } else poSRS->exportToWkt( &pszProjection ); pTransformArg = GDALCreateGenImgProjTransformer( NULL, pszProjection, hDS, NULL, FALSE, 0.0, 0 ); pfnTransformer = GDALGenImgProjTransform; CPLFree( pszProjection ); } OGRFeature *poFeat; poLayer->ResetReading(); /* -------------------------------------------------------------------- */ /* Loop over image in designated chunks. */ /* -------------------------------------------------------------------- */ int iY; for( iY = 0; iY < poDS->GetRasterYSize() && eErr == CE_None; iY += nYChunkSize ) { int nThisYChunkSize; nThisYChunkSize = nYChunkSize; if( nThisYChunkSize + iY > poDS->GetRasterYSize() ) nThisYChunkSize = poDS->GetRasterYSize() - iY; // Only re-read image if not a single chunk is being rendered if ( nYChunkSize < poDS->GetRasterYSize() ) { eErr = poDS->RasterIO( GF_Read, 0, iY, poDS->GetRasterXSize(), nThisYChunkSize, pabyChunkBuf, poDS->GetRasterXSize(), nThisYChunkSize, eType, nBandCount, panBandList, 0, 0, 0 ); if( eErr != CE_None ) break; } double *padfAttrValues = (double *) VSIMalloc(sizeof(double) * nBandCount); while( (poFeat = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeom = poFeat->GetGeometryRef(); if ( pszBurnAttribute ) { int iBand; double dfAttrValue; dfAttrValue = poFeat->GetFieldAsDouble( iBurnField ); for (iBand = 0 ; iBand < nBandCount ; iBand++) padfAttrValues[iBand] = dfAttrValue; padfBurnValues = padfAttrValues; } gv_rasterize_one_shape( pabyChunkBuf, iY, poDS->GetRasterXSize(), nThisYChunkSize, nBandCount, eType, bAllTouched, poGeom, padfBurnValues, eBurnValueSource, pfnTransformer, pTransformArg ); delete poFeat; } VSIFree( padfAttrValues ); // Only write image if not a single chunk is being rendered if ( nYChunkSize < poDS->GetRasterYSize() ) { eErr = poDS->RasterIO( GF_Write, 0, iY, poDS->GetRasterXSize(), nThisYChunkSize, pabyChunkBuf, poDS->GetRasterXSize(), nThisYChunkSize, eType, nBandCount, panBandList, 0, 0, 0 ); } poLayer->ResetReading(); if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()), "", pProgressArg) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); eErr = CE_Failure; } } if ( bNeedToFreeTransformer ) { GDALDestroyTransformer( pTransformArg ); pTransformArg = NULL; pfnTransformer = NULL; } } /* -------------------------------------------------------------------- */ /* Write out the image once for all layers if user requested */ /* to render the whole raster in single chunk. */ /* -------------------------------------------------------------------- */ if ( nYChunkSize == poDS->GetRasterYSize() ) { poDS->RasterIO( GF_Write, 0, 0, poDS->GetRasterXSize(), nYChunkSize, pabyChunkBuf, poDS->GetRasterXSize(), nYChunkSize, eType, nBandCount, panBandList, 0, 0, 0 ); } /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ VSIFree( pabyChunkBuf ); return eErr; }
CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType, int nPixelSpace, int nLineSpace, int nLayerCount, OGRLayerH *pahLayers, const char *pszDstProjection, double *padfDstGeoTransform, GDALTransformerFunc pfnTransformer, void *pTransformArg, double dfBurnValue, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg ) { /* -------------------------------------------------------------------- */ /* If pixel and line spaceing are defaulted assign reasonable */ /* value assuming a packed buffer. */ /* -------------------------------------------------------------------- */ if( nPixelSpace == 0 ) nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8; if( nLineSpace == 0 ) nLineSpace = nPixelSpace * nBufXSize; if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; /* -------------------------------------------------------------------- */ /* Do some rudimentary arg checking. */ /* -------------------------------------------------------------------- */ if( nLayerCount == 0 ) return CE_None; int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE ); const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" ); GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue; if( pszOpt ) { if( EQUAL(pszOpt,"Z")) eBurnValueSource = GBV_Z; /*else if( EQUAL(pszOpt,"M")) eBurnValueSource = GBV_M;*/ } /* ==================================================================== */ /* Read thes pecified layers transfoming and rasterizing */ /* geometries. */ /* ==================================================================== */ CPLErr eErr = CE_None; int iLayer; const char *pszBurnAttribute = CSLFetchNameValue( papszOptions, "ATTRIBUTE" ); pfnProgress( 0.0, NULL, pProgressArg ); for( iLayer = 0; iLayer < nLayerCount; iLayer++ ) { int iBurnField = -1; OGRLayer *poLayer = (OGRLayer *) pahLayers[iLayer]; if ( !poLayer ) { CPLError( CE_Warning, CPLE_AppDefined, "Layer element number %d is NULL, skipping.\n", iLayer ); continue; } /* -------------------------------------------------------------------- */ /* If the layer does not contain any features just skip it. */ /* Do not force the feature count, so if driver doesn't know */ /* exact number of features, go down the normal way. */ /* -------------------------------------------------------------------- */ if ( poLayer->GetFeatureCount(FALSE) == 0 ) continue; if ( pszBurnAttribute ) { iBurnField = poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute ); if ( iBurnField == -1 ) { CPLError( CE_Warning, CPLE_AppDefined, "Failed to find field %s on layer %s, skipping.\n", pszBurnAttribute, poLayer->GetLayerDefn()->GetName() ); continue; } } /* -------------------------------------------------------------------- */ /* If we have no transformer, create the one from input file */ /* projection. Note that each layer can be georefernced */ /* separately. */ /* -------------------------------------------------------------------- */ int bNeedToFreeTransformer = FALSE; if( pfnTransformer == NULL ) { char *pszProjection = NULL; bNeedToFreeTransformer = TRUE; OGRSpatialReference *poSRS = poLayer->GetSpatialRef(); if ( !poSRS ) { CPLError( CE_Warning, CPLE_AppDefined, "Failed to fetch spatial reference on layer %s " "to build transformer, assuming matching coordinate systems.\n", poLayer->GetLayerDefn()->GetName() ); } else poSRS->exportToWkt( &pszProjection ); pTransformArg = GDALCreateGenImgProjTransformer3( pszProjection, NULL, pszDstProjection, padfDstGeoTransform ); pfnTransformer = GDALGenImgProjTransform; CPLFree( pszProjection ); } OGRFeature *poFeat; poLayer->ResetReading(); while( (poFeat = poLayer->GetNextFeature()) != NULL ) { OGRGeometry *poGeom = poFeat->GetGeometryRef(); if ( pszBurnAttribute ) dfBurnValue = poFeat->GetFieldAsDouble( iBurnField ); gv_rasterize_one_shape( (unsigned char *) pData, 0, nBufXSize, nBufYSize, 1, eBufType, bAllTouched, poGeom, &dfBurnValue, eBurnValueSource, pfnTransformer, pTransformArg ); delete poFeat; } poLayer->ResetReading(); if( !pfnProgress(1, "", pProgressArg) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); eErr = CE_Failure; } if ( bNeedToFreeTransformer ) { GDALDestroyTransformer( pTransformArg ); pTransformArg = NULL; pfnTransformer = NULL; } } return eErr; }