1 WHAT:什么是栅格类型?
ArcGIS海量影像管理解决方案推出已经有一年时间了,相信很多朋友已经对ArcGIS中如何管理海量影像数据有了大致了解。ArcGIS 10.0中推出了适用于海量影像管理的镶嵌数据集模型(Mosaic Dataset),单个镶嵌数据集就可以管理数百万景,不同时相、不同分辨率、不同坐标系、不同空间位置的影像。
为了将各种来源,形式各异的影像数据导入镶嵌数据集中,我们需要为影像指定“栅格类型(Raster Type)”。简单说,栅格类型就是对各种影像数据的分门别类,而这种分类,基本上是按照卫星传感器类型、航摄相机类型进行划分的。下图是ArcGIS内置支持的一些栅格类型:
这里需要将栅格类型和栅格数据格式进行区分:栅格数据格式用于定义栅格像素如何存储,例如行列数、波段数、像素值等。而栅格类型则定义了如何识别影像关联的元数据,以及为影像定义的处理函数,如波段组合、全色融合等。
为了更好地理解栅格类型,我们可以打个比方:你要去电影院看电影,除了人要进去,还需要电影票,如果是3D电影,还需要带上3D眼镜。栅格影像数据入库,就相当于去看电影的过程:除了栅格影像数据本身要进去,还需要元数据信息(电影票),如果是多波段影像,可能还需要进行波段组合(看3D需要3D眼镜)。
2 WHEN:什么时候需要栅格类型扩展?
那么既然ArcGIS已经默认支持这么多的栅格类型,我们还有必要进行栅格类型扩展吗?当然需要了,在下面几个常见的场景中,栅格类型扩展是必须的:
1) 需要管理处理过的成果影像:很多单位会对影像数据进行各种处理,例如几何纠正、大气校正、影像拼接等等。经过这些处理的影像,就可能产生了自定义格式的元数据,这样就需要进行栅格类型扩展。
2) 需要管理国产卫星影像:很多单位都有国产卫星影像数据,例如风云系列、北京系列、环境星系列等等。这些卫星的元数据格式,也都形式各异,由于并不是国际通用的商业卫星,因此也需要进行栅格类型扩展。
3) 需要管理军用卫星影像:这类影像元数据格式可能就更加神秘了,如果读者有幸参与相关项目,则必须要通过栅格类型扩展才能管理这类影像。
4) 需要管理航飞拍摄的影像:航片也是影像数据的最大来源之一,比如无人机拍摄等。根据搭载的相机不同,生成的元数据也不尽相同,因此进行栅格类型扩展也是必要的。
那么有哪些影像是不需要进行栅格类型扩展就可以入库的呢?读者可以参考ArcGIS帮助中的介绍:
卫星传感器栅格类型:http://resources.arcgis.com/en/help/#/Satellite_sensor_raster_types/009t000001z6000000/
航空影像栅格类型:http://resources.arcgis.com/en/help/#/Aerial_imagery_raster_types/009t000001zp000000/
3 HOW:如何进行栅格类型扩展
OK,到这里,你已经了解了什么是栅格类型,以及在什么情况下需要进行栅格类型扩展,现在是时候学习如何进行栅格类型扩展了。
栅格类型扩展,实际上是通过ArcObjects开发来完成的。读者不必担心开发的难度,因为ArcGIS提供了非常完善的示例,而开发人员需要做的事情,其实就是给栅格类型扩展起个名字,然后去解析一下元数据文件,再根据需要定义一些预处理函数。
3.1 程序结构
在ArcObjects安装目录下,可以找到栅格类型扩展的示例程序,例如:C:\ArcGIS\DeveloperKit10.1\Samples\ArcObjectsNet\CustomRasterType\CSharp\ThumbnailBuilder,打开示例程序,可以看到ThumbnailBuilder.cs文件,其中包含了一个接口和两个类,如下图所示:
其中IThumbnailBuilder只包含一个属性,InnerRasterBuilder,表示栅格类型内置的构造器。
ThumbnailFactory则实现了IRasterTypeFactory接口,主要包含COM注册/反注册函数,栅格类型的名称,以及调用栅格类型构造器的流程。
ThumbnailBuilder则是具体的栅格类型构造器,其中包含了栅格类型扩展的具体处理算法。
3.2 实战案例
本例中,我们参考示例程序,但考虑到实际应用,加入了其他的功能,例如:记录操作日志,解析元数据文件等。程序结构如下图所示:
上述文件分别为:
1) CgcImageryBuilder:栅格类型构造器,执行具体的栅格类型构造操作;
2) CgcRasterTypeFactory:栅格类型工厂,定义栅格类型名称,提供COM注册函数,提供栅格类型构造器调用流程;
3) BuilderHelper:一些通用的处理函数,比如获取镶嵌数据集默认字段、自定义字段,或者添加字段等;
4) LogHelper:记录操作日志,写日志文件;
MetaReader:包含元数据解析函数,将指定格式的元数据文件,读取为标注的键值对。
3.3 主要代码
3.3.1 IAppendedBuilder
[csharp] view
plain copy
- interface IAppendedBuilder : IRasterBuilder
- {
- ///<summary>
- /// 附加的内置目标Raster Builder对象
- ///</summary>
- IRasterBuilder InnerRasterBuilder
- {
- get;
- set;
- }
- }
3.3.2 CgcRasterTypeFactory
[csharp] view
plain copy
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Runtime.InteropServices;
- using ESRI.ArcGIS.esriSystem;
- using ESRI.ArcGIS.DataSourcesRaster;
- using esricd.demos.cgc.imagery.util;
- namespace esricd.demos.cgc.imagery.ext
- {
- /// <summary>
- /// 重庆地理信息中心影像数据栅格类型工厂
- /// </summary>
- [Guid("AE299550-610F-44B6-9069-5C6E5CDC2F80")]
- [ClassInterface(ClassInterfaceType.None)]
- [ProgId("RasterTypeExtension.CgcRasterTypeFactory")]
- [ComVisible(true)]
- public class CgcRasterTypeFactory : IRasterTypeFactory
- {
- #region 私有成员
- public const string CGC_IMAGERY = "重庆地理信息中心影像类型";
- private IStringArray myRasterTypeNames;
- private UID myUID;
- public CgcRasterTypeFactory()
- {
- //指定栅格类型的名称,这些类型可以与扩展的栅格构造器关联
- myRasterTypeNames = new StrArrayClass();
- myRasterTypeNames.Add(CGC_IMAGERY);
- myUID = new UIDClass();
- myUID.Value = "{AE299550-610F-44B6-9069-5C6E5CDC2F80}";
- }
- #endregion
- #region IRasterTypeFactory 成员
- public ESRI.ArcGIS.esriSystem.UID CLSID
- {
- get { return myUID; }
- }
- public IRasterType CreateRasterType(string RasterTypeName)
- {
- try
- {
- // 1-首先获取内置栅格类型(Raster Dataset)
- IRasterTypeName theRasterTypeName = new RasterTypeNameClass();
- theRasterTypeName.Name = "Raster Dataset";//接受指向.art文件的路径,或内置栅格类型的名称
- IRasterType theRasterType = (IRasterType)(((IName)theRasterTypeName).Open());
- if (theRasterType == null)
- {
- LogHelper.AddMessage("错误:未找到栅格类型 " + theRasterTypeName.Name);
- return null;
- }
- // 2-在内置栅格类型(Raster Dataset)的栅格构造器上附加自定义的栅格构造器
- IAppendedBuilder pAppendedBuilder = new CgcImageryBuilder();
- pAppendedBuilder.InnerRasterBuilder = theRasterType.RasterBuilder;
- theRasterType.RasterBuilder = pAppendedBuilder as IRasterBuilder;
- // 3-将内置栅格类型(Raster Dataset)的名称改为自定义栅格类型的名称
- IName theName = theRasterType.FullName;
- ((IRasterTypeName)theName).Name = RasterTypeName;
- return theRasterType;
- }
- catch (Exception ex)
- {
- LogHelper.AddMessage("创建栅格类型 " + RasterTypeName + " 失败:" + ex.Message);
- return null;
- }
- }
- public string Name
- {
- get { return "Cgc Raster Type Factory"; }
- }
- public ESRI.ArcGIS.esriSystem.IStringArray RasterTypeNames
- {
- get { return myRasterTypeNames; }
- }
- #endregion
- #region COM 注册函数
- [ComRegisterFunction()]
- static void Reg(string regKey)
- {
- ESRI.ArcGIS.ADF.CATIDs.RasterTypeFactory.Register(regKey);
- }
- [ComUnregisterFunction()]
- static void Unreg(string regKey)
- {
- ESRI.ArcGIS.ADF.CATIDs.RasterTypeFactory.Unregister(regKey);
- }
- #endregion
- }
- }
3.3.3 CgcImageryBuilder
[csharp] view
plain copy
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Runtime.InteropServices;
- using ESRI.ArcGIS.DataSourcesRaster;
- using ESRI.ArcGIS.esriSystem;
- using ESRI.ArcGIS.Geodatabase;
- using esricd.demos.cgc.imagery.util;
- using ESRI.ArcGIS.Geometry;
- namespace esricd.demos.cgc.imagery.ext
- {
- [Guid("A1AE3CF4-2C9E-4A9C-9287-C8D9BF182F64")]
- [ClassInterface(ClassInterfaceType.None)]
- [ProgId("RasterTypeExtension.CgcImageryBuilder")]
- [ComVisible(true)]
- public class CgcImageryBuilder : IAppendedBuilder, IPersistVariant, IRasterBuilderInit
- {
- #region 私有成员
- public IRasterBuilder innerRasterBuilder; // Inner Raster Builder
- private UID myUID; // UID for the Builder.
- #endregion
- #region 附加构造器成员
- /// <summary>
- /// 构造函数不能含参数,否则报内存访问错误
- /// </summary>
- public CgcImageryBuilder()
- {
- innerRasterBuilder = null;
- myUID = new UIDClass();
- myUID.Value = "{A1AE3CF4-2C9E-4A9C-9287-C8D9BF182F64}";
- }
- public IRasterBuilder InnerRasterBuilder
- {
- get
- {
- return innerRasterBuilder;
- }
- set
- {
- innerRasterBuilder = value;
- }
- }
- #endregion
- #region IRasterBuilder 成员
- /// <summary>
- /// AuxiliaryFieldAlias property gets and sets the Auxiliary(辅助、备用) fields Alias
- /// present in the raster builder
- /// </summary>
- public ESRI.ArcGIS.esriSystem.IPropertySet AuxiliaryFieldAlias
- {
- get
- {
- return innerRasterBuilder.AuxiliaryFieldAlias;
- }
- set
- {
- innerRasterBuilder.AuxiliaryFieldAlias = value;
- }
- }
- /// <summary>
- /// Flag to specify whether the Raster Builder can build items in place.
- /// </summary>
- public bool CanBuildInPlace
- {
- get { return innerRasterBuilder.CanBuildInPlace; }
- }
- /// <summary>
- /// Prepare the Raster Type for generating Crawler items
- /// </summary>
- /// <param name="pCrawler">Crawler to use to generate the crawler items</param>
- public void BeginConstruction(IDataSourceCrawler pCrawler)
- {
- innerRasterBuilder.BeginConstruction(pCrawler);
- }
- /// <summary>
- /// Construct a Unique Resource Identifier (URI)
- /// for each crawler item
- /// </summary>
- /// <param name="crawlerItem">Crawled Item from which the URI is generated</param>
- public void ConstructURIs(object crawlerItem)
- {
- innerRasterBuilder.ConstructURIs(crawlerItem);
- }
- /// <summary>
- /// Finish Construction of the URI‘s
- /// </summary>
- /// <returns></returns>
- public IItemURIArray EndConstruction()
- {
- return innerRasterBuilder.EndConstruction();
- }
- /// <summary>
- /// Generate the next URI.
- /// </summary>
- /// <returns>The URI generated.</returns>
- public IItemURI GetNextURI()
- {
- return innerRasterBuilder.GetNextURI();
- }
- /// <summary>
- /// Get the recommended data crawler for the Raster Type based on
- /// properties provided by the user.
- /// </summary>
- /// <param name="pDataSourceProperties">List of properties provided by the user</param>
- /// <returns></returns>
- public IDataSourceCrawler GetRecommendedCrawler(IPropertySet pDataSourceProperties)
- {
- return innerRasterBuilder.GetRecommendedCrawler(pDataSourceProperties);
- }
- /// <summary>
- /// Check if the item provided is "stale不新鲜的,过时的" or not valid
- /// </summary>
- /// <param name="pItemURI">URI for the item to be checked</param>
- /// <returns></returns>
- public bool IsStale(IItemURI pItemURI)
- {
- return innerRasterBuilder.IsStale(pItemURI);
- }
- /// <summary>
- /// Properties associated with the Raster Type
- /// </summary>
- public IPropertySet Properties
- {
- get
- {
- return innerRasterBuilder.Properties;
- }
- set
- {
- innerRasterBuilder.Properties = value;
- }
- }
- /// <summary>
- /// 添加辅助字段,所有非镶嵌数据集默认字段均可视为辅助字段
- /// </summary>
- public IFields AuxiliaryFields
- {
- get
- {
- ESRI.ArcGIS.DataSourcesRaster.IRasterBuilder pRasterBuilder = innerRasterBuilder;
- IFields myFields = pRasterBuilder.AuxiliaryFields;
- try
- {
- IMosaicDataset pMosaicDataset = ((IRasterBuilderInit)innerRasterBuilder).MosaicDataset;
- IFields pAllFields = BuilderHelper.GetMosaicDatasetFields(pMosaicDataset);
- Dictionary<string, esriFieldType> lstCustomFields = BuilderHelper.GetMosaicDatasetCustomFields(pAllFields);
- foreach (KeyValuePair<string,esriFieldType> fieldItem in lstCustomFields)
- {
- int count = myFields.FindField(fieldItem.Key);
- if (count == -1)
- {
- BuilderHelper.AddNewField(myFields, fieldItem.Key, fieldItem.Value);
- pRasterBuilder.AuxiliaryFields = myFields;
- }
- }
- }
- catch (Exception ex)
- {
- LogHelper.AddMessage("添加辅助字段失败:" + ex.ToString());
- }
- return innerRasterBuilder.AuxiliaryFields;
- }
- set
- {
- innerRasterBuilder.AuxiliaryFields = value;
- }
- }
- /// <summary>
- /// 构建栅格数据项,可在此对每一项执行附加的构建操作.
- /// </summary>
- /// <param name="pItemURI"></param>
- /// <returns></returns>
- public IBuilderItem Build(IItemURI pItemURI)
- {
- try
- {
- // 执行内置的构建操作(参数为待构建项的URI)
- LogHelper.AddMessage("正在读取栅格数据:" + pItemURI.Key);
- IBuilderItem pBuilderItem = innerRasterBuilder.Build(pItemURI);
- //获取镶嵌数据集字段列表,以便根据字段别名提取元数据项
- IMosaicDataset md = ((IRasterBuilderInit)innerRasterBuilder).MosaicDataset;
- IFields pFields = BuilderHelper.GetMosaicDatasetFields(md);
- //获取栅格数据的属性,以便将元数据项写入属性表中
- IPropertySet pPropSet = pBuilderItem.Dataset.Properties;
- //读写元数据
- MetaReader.ReadCgcImageryMeta(pItemURI.Key, pFields, pPropSet);
- LogHelper.AddMessage("已完成栅格数据添加。");
- LogHelper.WriteToLogFile();
- return pBuilderItem;
- }
- catch (Exception ex)
- {
- LogHelper.AddMessage("构建栅格数据失败:" + ex.ToString());
- LogHelper.WriteToLogFile();
- return null;
- }
- }
- #endregion
- #region IPersistVariant 成员
- /// <summary>
- /// UID for the object implementing the Persist Variant
- /// </summary>
- UID IPersistVariant.ID
- {
- get { return myUID; }
- }
- /// <summary>
- /// Load the object from the stream provided
- /// </summary>
- /// <param name="Stream">Stream that represents the serialized Raster Type</param>
- void IPersistVariant.Load(IVariantStream Stream)
- {
- string name = (string)Stream.Read();
- innerRasterBuilder = (IRasterBuilder)Stream.Read(); // Load the innerRasterBuilder from the stream.
- }
- /// <summary>
- /// Same the Raster Type to the stream provided
- /// </summary>
- /// <param name="Stream">Stream to serialize the Raster Type into</param>
- void IPersistVariant.Save(IVariantStream Stream)
- {
- Stream.Write("CgcImageryBuilder");
- Stream.Write(innerRasterBuilder); // Save the innerRasterBuilder into the stream.
- }
- #endregion
- #region IRasterBuilderInit 成员
- /// <summary>
- /// Default spatial reference for the MD.
- /// </summary>
- ISpatialReference IRasterBuilderInit.DefaultSpatialReference
- {
- get
- {
- return ((IRasterBuilderInit)innerRasterBuilder).DefaultSpatialReference;
- }
- set
- {
- ((IRasterBuilderInit)innerRasterBuilder).DefaultSpatialReference = value;
- }
- }
- /// <summary>
- /// Parent mosaic dataset for the Raster Builder.
- /// </summary>
- IMosaicDataset IRasterBuilderInit.MosaicDataset
- {
- get
- {
- return ((IRasterBuilderInit)innerRasterBuilder).MosaicDataset;
- }
- set
- {
- ((IRasterBuilderInit)innerRasterBuilder).MosaicDataset = value;
- }
- }
- /// <summary>
- /// The raster type operation helper object associated with this raster type.
- /// </summary>
- IRasterTypeOperation IRasterBuilderInit.RasterTypeOperation
- {
- get
- {
- return ((IRasterBuilderInit)innerRasterBuilder).RasterTypeOperation;
- }
- set
- {
- ((IRasterBuilderInit)innerRasterBuilder).RasterTypeOperation = value;
- }
- }
- /// <summary>
- /// Tracker for when cancel is pressed.
- /// </summary>
- ITrackCancel IRasterBuilderInit.TrackCancel
- {
- get
- {
- return ((IRasterBuilderInit)innerRasterBuilder).TrackCancel;
- }
- set
- {
- ((IRasterBuilderInit)innerRasterBuilder).TrackCancel = value;
- }
- }
- #endregion
- }
- }
扩展开发完成、注册之后,可以在栅格类型中看到自定义的栅格类型,如下图最后一个:
这样在影像数据导入镶嵌数据集的时候,就可以选择扩展的栅格类型,保证元数据信息正确入库管理,为下一步影像管理、应用打下坚实的基础。
本文仅介绍栅格类型扩展的技术路线和关键代码,日志记录和其他辅助函数则没有上传,如需完整代码,请在评论中留下邮箱地址。如有疑问,也请在评论中留言探讨。
转自http://blog.csdn.net/esrichinacd/article/details/7844494