A solution:
I solved this earlier today. The code is an adaptation of this method. The concept behind this wasn't terribly difficult once I figured out what the objects used to interface with the raster actually do. The below method takes two input datasets (inRasterDS and outRasterDS). They are both the same dataset, I just made a copy of inRasterDS and passed it into the method as outRasterDS. This way they both have the same extent, spatial reference, etc. The method reads the values from inRasterDS, cell by cell, and does nearest neighbor comparisons on them. It uses the results of those comparisons as stored values in outRasterDS.
The Process:
I used IRasterCursor -> IPixelBlock -> SafeArray to get at the pixel values and IRasterEdit to write new ones to the raster. When you create IPixelBlock, you are telling the machine the size and location of the area that you want to read/write to. If you only want to edit the bottom half of a raster, you set that as your IPixelBlock parameters. If you want to loop over the entire raster, you have to set IPixelBlock equal to the size of the entire raster. I do this in the method below by passing the size to IRasterCursor (pSize) then getting the PixelBlock from the raster cursor.
The other key is that you have to use SafeArray to interface with the values in this method. You get IPixelBlock from IRasterCursor, then SafeArray from IPixelBlock. Then you read and write to SafeArray. When you finish read/write to SafeArray, write your entire SafeArray back to IPixelBlock, then write your IPixelBlock to IRasterCursor, then finally use IRasterCursor to set the location to start write and IRasterEdit to do the write itself. This final step is where you actually edit the values of the dataset.
public static void CreateBoundaryRaster(IRasterDataset2 inRasterDS, IRasterDataset2 outRasterDS)
{
try
{
//Create a raster.
IRaster2 inRaster = inRasterDS.CreateFullRaster() as IRaster2; //Create dataset from input raster
IRaster2 outRaster = outRasterDS.CreateFullRaster() as IRaster2; //Create dataset from output raster
IRasterProps pInRasterProps = (IRasterProps)inRaster;
//Create a raster cursor with a pixel block size matching the extent of the input raster
IPnt pSize = new DblPnt();
pSize.SetCoords(pInRasterProps.Width, pInRasterProps.Height); //Give the size of the raster as a IPnt to pass to IRasterCursor
IRasterCursor inrasterCursor = inRaster.CreateCursorEx(pSize); //Create IRasterCursor to parse input raster
IRasterCursor outRasterCursor = outRaster.CreateCursorEx(pSize); //Create IRasterCursor to parse output raster
//Declare IRasterEdit, used to write the new values to raster
IRasterEdit rasterEdit = outRaster as IRasterEdit;
IRasterBandCollection inbands = inRasterDS as IRasterBandCollection;//set input raster as IRasterBandCollection
IRasterBandCollection outbands = outRasterDS as IRasterBandCollection;//set output raster as IRasterBandCollection
IPixelBlock3 inpixelblock3 = null; //declare input raster IPixelBlock
IPixelBlock3 outpixelblock3 = null; //declare output raster IPixelBlock
long blockwidth = 0; //store # of columns of raster
long blockheight = 0; //store # of rows of raster
//create system array for input/output raster. System array is used to interface with values directly. It is a grid that overlays your IPixelBlock which in turn overlays your raster.
System.Array inpixels;
System.Array outpixels;
IPnt tlc = null; //set the top left corner
// define the 3x3 neighborhood objects
object center;
object topleft;
object topmiddle;
object topright;
object middleleft;
object middleright;
object bottomleft;
object bottommiddle;
object bottomright;
long bandCount = outbands.Count; //use for multiple bands (only one in this case)
do
{
inpixelblock3 = inrasterCursor.PixelBlock as IPixelBlock3; //get the pixel block from raster cursor
outpixelblock3 = outRasterCursor.PixelBlock as IPixelBlock3;
blockwidth = inpixelblock3.Width; //set the # of columns in raster
blockheight = inpixelblock3.Height; //set the # of rows in raster
outpixelblock3.Mask(255); //set any NoData values
for (int k = 0; k < bandCount; k++) //for every band in raster (will always be 1 in this case)
{
//Get the pixel array.
inpixels = (System.Array)inpixelblock3.get_PixelData(k); //store the raster values in a System Array to read
outpixels = (System.Array)outpixelblock3.get_PixelData(k); //store the raster values in a System Array to write
for (long i = 1; i < blockwidth - 1; i++) //for every column (except outside columns)
{
for (long j = 1; j < blockheight - 1; j++) //for every row (except outside rows)
{
//Get the pixel values of center cell and neighboring cells
center = inpixels.GetValue(i, j);
topleft = inpixels.GetValue(i - 1, j + 1);
topmiddle = inpixels.GetValue(i, j + 1);
topright = inpixels.GetValue(i + 1, j + 1);
middleleft = inpixels.GetValue(i - 1, j);
middleright = inpixels.GetValue(i + 1, j);
bottomleft = inpixels.GetValue(i - 1, j - 1);
bottommiddle = inpixels.GetValue(i, j - 1);
bottomright = inpixels.GetValue(i - 1, j - 1);
//compare center cell value with middle left cell and middle right cell in a 3x3 grid. If true, give output raster value of 1
if ((Convert.ToDouble(center) >= Convert.ToDouble(middleleft)) && (Convert.ToDouble(center) >= Convert.ToDouble(middleright)))
{
outpixels.SetValue(1, i, j);
}
//compare center cell value with top middle and bottom middle cell in a 3x3 grid. If true, give output raster value of 1
else if ((Convert.ToDouble(center) >= Convert.ToDouble(topmiddle)) && (Convert.ToDouble(center) >= Convert.ToDouble(bottommiddle)))
{
outpixels.SetValue(1, i, j);
}
//if neither conditions are true, give raster value of 0
else
{
outpixels.SetValue(0, i, j);
}
}
}
//Write the pixel array to the pixel block.
outpixelblock3.set_PixelData(k, outpixels);
}
//Finally, write the pixel block back to the raster.
tlc = outRasterCursor.TopLeft;
rasterEdit.Write(tlc, (IPixelBlock)outpixelblock3);
}
while (inrasterCursor.Next() == true && outRasterCursor.Next() == true);
System.Runtime.InteropServices.Marshal.ReleaseComObject(rasterEdit);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}