How can I reliably set the NoData value of a raster?

4091
4
08-20-2012 12:37 PM
EricWeber
New Contributor III
I want to clip a raster and retain the NoData value from the source raster in the clipped raster. In the method below, I follow these steps:

(1) use map algebra to clip the source raster to the new extent
(2) use IRasterProps to set the pixel type and NoData value to be the same as the source raster
(3) use ISaveAs to save the new raster dataset

The source raster I've been testing with is a 16-bit signed integer raster with a NoData value of -32768. Setting the pixel type works correctly, but the NoData value always ends up being 32767.

I have also tried using the geoprocessing clip method (http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/How_to_clip_a_raster_da...), but I still end up with 32767.

(Other specifics in my testing that may or may not be relevant: input raster is GRID, output is file geodatabase)

        public static IRaster ClipRaster(IRaster2 sourceRaster, IEnvelope extent, IWorkspace workspace, string rasterName, string rasterFormat)
        {
            //map algebra method for clipping
            //NoData value is not set properly (always ends up as largest positive integer supported by pixel type)

            //clip
            SetRasterAnalysisEnvCellSize(sourceRaster, true);
            SetRasterAnalysisEnvExtent(extent, sourceRaster, true);
            IMapAlgebraOp mapAlgebraOp = new RasterMapAlgebraOpClass();
            string rasterSymbol = "source";
            mapAlgebraOp.BindRaster((IGeoDataset)sourceRaster, rasterSymbol);
            IGeoDataset tempClipRaster = mapAlgebraOp.Execute("[" + rasterSymbol + "]");
         
            //set pixel type and nodata value to match input raster and save
            IRasterProps propsClip = tempClipRaster as IRasterProps;
            IRasterProps propsSource = sourceRaster as IRasterProps;
            propsClip.PixelType = propsSource.PixelType;
            propsClip.NoDataValue = propsSource.NoDataValue; // this doesn't stick
            IRasterDataset3 clipOutput = ((ISaveAs2)tempClipRaster).SaveAs(rasterName, workspace, rasterFormat) as IRasterDataset3;
            
            //delete the temporary dataset created by the map algebra op
            if (((IDataset)((IRaster2)tempClipRaster).RasterDataset).CanDelete())
                ((IDataset)((IRaster2)tempClipRaster).RasterDataset).Delete();

            IRaster outRaster = clipOutput.CreateDefaultRaster();
            //IRaster outRaster = clipOutput.CreateFullRaster(); //this method has same result
            return outRaster;
        }
0 Kudos
4 Replies
DuncanHornby
MVP Notable Contributor
Eric,

Just a thought, if you have used the geoprocessing clip tool could you not then use the SetNull tool after the clip, if the ISaveAs is not working?

Duncan
0 Kudos
EricWeber
New Contributor III
Duncan - thanks for the suggestion. I tried to use SetNull, both in the map algebra expression, as well as in the geoprocessing method (after the Clip tool), and it does not change the result. As I understand SetNull, it doesn't change which value is treated as NoData, but rather changes individual cell values to the NoData value. Correct me if I'm wrong on that.

Eric,

Just a thought, if you have used the geoprocessing clip tool could you not then use the SetNull tool after the clip, if the ISaveAs is not working?

Duncan


I still think the IRasterProps/ISaveAs approach should work. It's prescribed by ESRI (http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//0001000000w6000000). As far as I can tell, there must be a bug in the NoData property of IRasterProps or in the SaveAs method of ISaveAs. Can anyone tell me if I'm doing something wrong? Or does anyone know of a workaround?
0 Kudos
DavidWilton
Occasional Contributor
I'm having this same issue. It appears to be a problem with setting the no data value when using a file geodatabase as the output workspace. I have followed the code in this help topic and if you import to a FileGDBWorkspaceFactory it fails to set the no data value. If you out save to a RasterWorkspaceFactory it holds the no data value so I believe there is nothing wrong with my workflow

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000464000000

The only way I could get it to work was to do a saveAs using iSavAs after I had finished processing the raster. This also gets around another what appears to be another bug. If you import to a RasterWorkspaceFactory and then add it to the map programmatically I found it adds a blank raster (whereas geodatabase is fine). Doing the save as and adding that dataset works fine.

Hope this helps someone.
Dave

ArcGIS 10.1
0 Kudos
GregMcQuat
New Contributor III

Try using the IRasterWorkspaceEx.SaveAsRasterDataset() method.

e.g.

var rasterWorkspace = (IRasterWorkspaceEx) workspace;
IRasterProps propsSource = sourceRaster as IRasterProps;

IRasterDef rasterDef = new RasterDef();
rasterDef.SpatialReference = propsSource.SpatialReference;
var raster = ((IRasterDataset3)tempClipRaster).CreateFullRaster();
((IRasterProps)raster).NoDataValue = propsSource.NoDataValue // Ensure that this is the value you expect.
IRasterDataset3 clipOutput = rasterWorkspace.SaveAsRasterDataset(rasterName, raster, null, null, rasterDef, null);
0 Kudos