Arcgis Engine中关于创建栅格数据集的NoData问题
我们知道在ArcMap中生成一张栅格图像时,其有效值所包含的区域内形状不一定是和屏幕横向或纵向平行的,而ArcMap在生成栅格图像时,也是和我们一样创建了格网,通过分析他的数据,我个人认为ArcMap也是创建了规则格网,因为在其四个角点组成的最大外接矩形框内,透明白色区域的值会显示“NoData”,而之外的透明白色区域都无值可查。如下图所示(自己也可以在ArcMap中生成一副栅格试验一下):
据此可以推断,在生成栅格时,其建立格网均是以规则切与屏幕方向平行的方向建立的,遍历规则也需从左上角(ArcEngine遍历规则)或者左下角(哈希表遍历规则)依次遍历。
ArcGIS Engine 10 开发手册中的创建栅格数据集是这样的:
public IRasterDataset CreateRasterDataset (string pRasterFolderPath,string pFileName, string pRasterType, ISpatialReference pSpr)
{
IRasterWorkspace2 pRasterWs = GetRasterWorkspace (pRasterFolderPath) as IRasterWorkspace2;
IPoint pPoint = new PointClass ();
pPoint.PutCoords (15.0, 15.0);
int pWidth = 300;
int pHeight = 300;
double xCell = 30;
double yCell = 30;
int NumBand = 1;
IRasterDataset pRasterDataset = pRasterWs.CreateRasterDataset (pFileName, pRasterType,pPoint, pWidth, pHeight, xCell, yCell, NumBand, rstPixelType.PT_UCHAR, pSpr,true);
IRasterBandCollection pRasterBands = (IRasterBandCollection) pRasterDataset;
IRasterBand pRasterBand = pRasterBands.Item (0);
IRasterProps pRasterProps = (IRasterProps) pRasterBand;
pRasterProps.NoDataValue = 255;
IRaster pRaster = pRasterDataset.CreateDefaultRaster ();
IPnt pPnt = new PntClass ();
pPnt.SetCoords (30, 30);
IRaster2 pRaster2 = pRaster as IRaster2;
IRasterEdit pRasterEdit = (IRasterEdit) pRaster2;
IRasterCursor pRasterCursor = pRaster2.CreateCursorEx (pPnt);
do
{
IPixelBlock3 pPixelblock = pRasterCursor.PixelBlock as IPixelBlock3;
System.Array pixels = (System.Array) pPixelblock.get_PixelData (0);
for (int i = 0; i & lt; pPixelblock.Width; i++)
for (int j = 0; j & lt; pPixelblock.Height; j++)
if (i == j)
pixels.SetValue (Convert.ToByte (255), i, j);
else
pixels.SetValue (Convert.ToByte ((i* j + 30) / 255), i, j);
pPixelblock.set_PixelData (0,(System.Array) pixels);
IPnt pUpperLeft = pRasterCursor.TopLeft;
pRasterEdit.Write (pUpperLeft,(IPixelBlock) pPixelblock);
} while (pRasterCursor.Next ());
System.Runtime.InteropServices.Marshal.ReleaseComObject (pRasterEdit);
return pRasterDataset;
}
其中,有这样一句pRasterProps.NoDataValue = 255;
,我们可以按F12查看此接口IRasterProps
的定义。关于NoDataValue的定义如下:
我们由此可知,用此接口来设置“NoData”,我们知道灰度图像的值范围为0-255,因此,如果超出这个值,在输出灰度图像栅格时,我们将这些值统一标记为“NoData”即可。具体代码如下:
PS:我是以哈希表来传递值的,因此在后面遍历传值时,涉及到ArcEngine的遍历和HashTable的遍历转换问题。
/// <summary>
/// 创建栅格数据集
/// </summary>
/// <param name="pFileDirectoryName"></param>
/// <param name="pFielName"></param>
/// <param name="pXmin">格网最小X</param>
/// <param name="pYmin">格网最小Y</param>
/// <param name="pGridSide">一个格网长</param>
/// <param name="pHashtable">输入的哈希表</param>
/// <param name="pRowSum">格网总行数</param>
/// <param name="pColumnSum">格网总列数</param>
/// <returns></returns>
public IRasterDataset CreateRasterDataset(string pFileDirectoryName, string pFielName, double pXmin, double pYmin, double pGridSide, Hashtable pHashtable, int pRowSum, int pColumnSum)
{
//原点
IPoint pOriginPoint = new PointClass();
pOriginPoint.PutCoords(pXmin, pYmin);
//创建数据集
IWorkspaceFactory pWorkspaceFactory = new RasterWorkspaceFactoryClass();//using ESRI.ArcGIS.DataSourcesRaster;
IRasterWorkspace2 pRasterWorkspace = pWorkspaceFactory.OpenFromFile(pFileDirectoryName, 0) as IRasterWorkspace2;
IRasterDataset pRasterDataset = pRasterWorkspace.CreateRasterDataset(pFielName, "TIFF", pOriginPoint, pColumnSum, pRowSum, pGridSide, pGridSide, 1, rstPixelType.PT_DOUBLE, new UnknownCoordinateSystemClass(), true);
IRasterBandCollection pIRasterBandCollection = (IRasterBandCollection)pRasterDataset;
IRasterBand pIRasterBand;
IRasterProps pIRasterProps;
pIRasterBand = pIRasterBandCollection.Item(0);
pIRasterProps = (IRasterProps)pIRasterBand;
//Set NoData if necessary. For a multiband image, a NoData value needs to be set for each band.
pIRasterProps.NoDataValue = 256; //以此值来标记“NoData”
IRaster pIRaster = ((IRasterDataset2)pRasterDataset).CreateFullRaster();
IPnt blocksize = new PntClass();
blocksize.SetCoords(pColumnSum, pRowSum);
IPixelBlock3 pIPixelBlock3 = pIRaster.CreatePixelBlock(blocksize) as IPixelBlock3;
System.Array pPixelData;
pPixelData = (System.Array)pIPixelBlock3.get_PixelData(0);
byte[] outputArray = (byte[])pIPixelBlock3.get_NoDataMaskByRef(0);
for (int i = 0; i < pColumnSum; i++)//列数
{
for (int j = 0; j < pRowSum; j++)//行数
{
int pGridIndex = (pRowSum - j - 1) * pColumnSum + (i + 1);//遍历顺序转换
if (pHashtable.ContainsKey(pGridIndex))
{
pPixelData.SetValue(Convert.ToDouble(pHashtable[pGridIndex]), i, j);
}
else
{
pPixelData.SetValue(Convert.ToDouble(256), i, j); //将此值输出,结果为“NoData”
}
}
}
pIPixelBlock3.set_PixelData(0, (System.Object)pPixelData);
IPnt upLeft = new PntClass();
upLeft.SetCoords(0, 0);
IRasterEdit rasterEdit = (IRasterEdit)pIRaster;
rasterEdit.Write(upLeft, (IPixelBlock)pIPixelBlock3);
System.Runtime.InteropServices.Marshal.ReleaseComObject(rasterEdit);
return pRasterDataset;
}
}
至此,我们可以达到和ArcMap中一样的效果。
感谢各位浏览支持,多多交流。