Arccgis Engine中关于创建栅格数据集的NoData问题

时间:2024-03-30 16:37:38

Arcgis Engine中关于创建栅格数据集的NoData问题

我们知道在ArcMap中生成一张栅格图像时,其有效值所包含的区域内形状不一定是和屏幕横向或纵向平行的,而ArcMap在生成栅格图像时,也是和我们一样创建了格网,通过分析他的数据,我个人认为ArcMap也是创建了规则格网,因为在其四个角点组成的最大外接矩形框内,透明白色区域的值会显示“NoData”,而之外的透明白色区域都无值可查。如下图所示(自己也可以在ArcMap中生成一副栅格试验一下):
Arccgis Engine中关于创建栅格数据集的NoData问题
据此可以推断,在生成栅格时,其建立格网均是以规则切与屏幕方向平行的方向建立的,遍历规则也需从左上角(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的定义如下:
Arccgis Engine中关于创建栅格数据集的NoData问题
我们由此可知,用此接口来设置“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中一样的效果。
感谢各位浏览支持,多多交流。