利用ArcGIS Server SOI 创建水印地图
ArcGIS Server 10.3.1中新出了一个功能叫SOI,其本质上是一个拦截器,可以对地图服务进行拦截,更改返回的地图信息,具体各种官方术语看官方文档。
开发和部署SOI需要安装ArcObject sdk 10.3.1 和 ArcGIS Server 10.3.1。安装步骤详见百度等等搜索引擎,下面进入主题。
1、首先打开VS2013(其他版本不清楚,因为本人安装的是2013),然后新建ArcGIS的模板项目,如图
2、新建之后会生成一个.cs文件,我这里是打算做一个给地图添加水印的功能,CS文件为WaterMarkSOI.cs
[ComVisible(true)]
[Guid("2a0f1bb6-62f3-4b5a-b287-d01530162aca")]
[ClassInterface(ClassInterfaceType.None)]
//这里说的是如果用来给地图服务做扩展,就用MapServer,如果用影像服务就用ImageServer,
//ArcGIS Server给我们自带了一个MapServer,那我就选择用MapServer,其他就不改了
[ServerObjectInterceptor("MapServer",//use "MapServer" if SOI extends a Map service and "ImageServer" if it extends an Image service.
Description = "",
DisplayName = "WaterMarkSOI",
Properties = "")]
3、WaterMarkSOI类实现了接口IRESTRequestHandler,该接口有两个方法GetSchema()、HandleRESTRequest(string Capabilities, string resourceName, string operationName, string operationInput, string outputFormat, string requestProperties, out string responseProperties),我想后面调用的就是REST服务,所以就对该接口的方法进行实现。
水印功能无须获取图层之类的进行操作,所以可以直接在HandleRESTRequest方法中实现即可,其他方法可以不予理会。
restRequestHandler.HandleRESTRequest(Capabilities, resourceName,operationName,operationInput,outputFormat,requestProperties, out responseProperties)的返回实际就是response,下面我们查看一下完整的代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.SOESupport;
using System.Drawing;
//TODO: sign the project (project properties > signing tab > sign the assembly)
// this is strongly suggested if the dll will be registered using regasm.exe <your>.dll /codebase
namespace WaterMarkSOI
{
[ComVisible(true)]
[Guid("2a0f1bb6-62f3-4b5a-b287-d01530162aca")]
[ClassInterface(ClassInterfaceType.None)]
//这里说的是如果用来给地图服务做扩展,就用MapServer,如果用影像服务就用ImageServer,
//ArcGIS Server给我们自带了一个MapServer,那我就选择用MapServer,其他就不改了
[ServerObjectInterceptor("MapServer",//use "MapServer" if SOI extends a Map service and "ImageServer" if it extends an Image service.
Description = "",
DisplayName = "WaterMarkSOI",
Properties = "")]
public class WaterMarkSOI : IServerObjectExtension, IRESTRequestHandler, IWebRequestHandler, IRequestHandler2, IRequestHandler
{
private string _soiName;
private IServerObjectHelper _soHelper;
private ServerLogger _serverLog;
private Dictionary<String, IServerObjectExtension> _extensionCache = new Dictionary<String, IServerObjectExtension>();
IServerEnvironment2 _serverEnvironment;
//定义一个输出目录,Init方法中对变量进行初始化
private string _outputDirectory = string.Empty;
public WaterMarkSOI()
{
_soiName = this.GetType().Name;
}
public void Init(IServerObjectHelper pSOH)
{
try
{
_soHelper = pSOH;
_serverLog = new ServerLogger();
try
{
var se4 = ServerEnvironment as IServerEnvironmentEx;
var dirInfos = se4.GetServerDirectoryInfos();
dirInfos.Reset();
object dirInfo = dirInfos.Next();
while (dirInfo != null)
{
var dinfo2 = dirInfo as IServerDirectoryInfo2;
if (null != dinfo2 && dinfo2.Type == esriServerDirectoryType.esriSDTypeOutput)
{
_outputDirectory = dinfo2.Path;
break;
}
dirInfo = dirInfos.Next();
}
}
catch (Exception ignore)
{
_outputDirectory = string.Empty;
}
_outputDirectory = _outputDirectory.Trim();
if (string.IsNullOrEmpty(_outputDirectory))
{
_serverLog.LogMessage(ServerLogger.msgType.error, _soiName + ".init()", 500, "OutputDirectory is empty or missing. Reset to default.");
_outputDirectory = "C:\\arcgisserver\\directories\\arcgisoutput";
}
_serverLog.LogMessage(ServerLogger.msgType.infoDetailed, _soiName + ".init()", 500, "OutputDirectory is " + _outputDirectory);
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".init()", 200, "Initialized " + _soiName + " SOI.");
}
catch (Exception e)
{
_serverLog.LogMessage(ServerLogger.msgType.error, _soiName + ".HandleRESTRequest()", 500, "Exception " + e.GetType().Name + " " + e.Message + " " + e.StackTrace);
throw;
}
}
public void Shutdown()
{
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".init()", 200, "Shutting down " + _soiName + " SOI.");
}
#region REST interceptors
public string GetSchema()
{
IRESTRequestHandler restRequestHandler = FindRequestHandlerDelegate<IRESTRequestHandler>();
if (restRequestHandler == null)
return null;
return restRequestHandler.GetSchema();
}
public byte[] HandleRESTRequest(string Capabilities, string resourceName, string operationName,
string operationInput, string outputFormat, string requestProperties, out string responseProperties)
{
responseProperties = null;
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".HandleRESTRequest()",
200, "Request received in Sample Object Interceptor for handleRESTRequest");
/*
* Add code to manipulate REST requests here
*/
// Find the correct delegate to forward the request too
IRESTRequestHandler restRequestHandler = FindRequestHandlerDelegate<IRESTRequestHandler>();
if (restRequestHandler == null)
return null;
//定义一个变量response等于restRequestHandler.HandleRESTRequest
var response= restRequestHandler.HandleRESTRequest(
Capabilities, resourceName, operationName, operationInput,
outputFormat, requestProperties, out responseProperties);
//如果想知道operationName有多少种方式,可以查询AO的帮助文档,搜索Server,
//搜索结果中有一个Extending ArcGIS for Server->Developing server object interceptors
//然后就可以看到一行字:
//This sample illustrates how to filter access to individual operations available on the map server.
//Three operations – "find", "identify", and "export" – are checked against the incoming request’s user’s role.
//打开一个服务的REST链接,最下面有这样一句:Supported Operations: Export Map Identify Find Return Updates Generate KML
//具体每个操作对应的字符串就不再去找了
//我们还可以在\DeveloperKit10.3\samples\ArcObjectsNET的目录中找到一些实例代码,其中水印就是示例代码之一,我们将实例代码可以拷过来使用
if (operationName.Equals("export", StringComparison.CurrentCultureIgnoreCase))
{
Image sourceImage = null;
if (outputFormat.Equals("image", StringComparison.CurrentCultureIgnoreCase))
{
sourceImage = Image.FromStream(new System.IO.MemoryStream(response));
var watermarker = new ApplyWatermark();
//我们把水印文字改一下,改成自己想要的文字
var watermarkedImage = watermarker.Mark(sourceImage, "用SOI生成水印文字");
var newResponse = new System.IO.MemoryStream();
watermarkedImage.Save(newResponse, sourceImage.RawFormat);
return newResponse.GetBuffer();
}
else if (outputFormat.Equals("json", StringComparison.CurrentCultureIgnoreCase))
{
var responseString = System.Text.Encoding.UTF8.GetString(response);
var jo = new JsonObject(responseString);
string hrefString = null;
if (!jo.TryGetString("href", out hrefString))
{
//这里只是一个小demo,就不整复杂了,这个位置我把他注释掉,不需要抛出异常
//throw new RESTErrorException("Export operation returned invalid response");
}
if (string.IsNullOrEmpty(hrefString))
{
//这个位置也注释,不需要抛出异常
//throw new RESTErrorException("Export operation returned invalid response");
}
// 生成输出文件
var outputImageFileLocation = GetOutputImageFileLocation(hrefString);
// debug logging 调试日志
//_serverLog.LogMessage(ServerLogger.msgType.error, "debug", 0, "output is " + outputImageFileLocation);
var watermarker = new ApplyWatermark();
Image watermarkedImage;
System.Drawing.Imaging.ImageFormat sourceImageFormat;
using (sourceImage = Image.FromFile(outputImageFileLocation))
{
sourceImageFormat = sourceImage.RawFormat;
watermarkedImage = watermarker.Mark(sourceImage, "(c) SuperMap Inc.");
}
// 确保调用Dispose之前保存sourceImage
watermarkedImage.Save(outputImageFileLocation, sourceImageFormat);
watermarkedImage.Dispose();//Save方法在前
// 返回修改后的response
return response;
}
else if (outputFormat.Equals("kmz", StringComparison.CurrentCultureIgnoreCase))
{
// Note: Watermark can be added for the kmz format too. In this example we didn't
// implement it.
//throw new RESTErrorException("Kmz format is not supported");
}
else
{
//throw new RESTErrorException("Invalid operation parameters");
}
}//if operationName==export
return response;
}
#endregion
#region SOAP interceptors
public byte[] HandleStringWebRequest(esriHttpMethod httpMethod, string requestURL,
string queryString, string Capabilities, string requestData,
out string responseContentType, out esriWebResponseDataType respDataType)
{
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".HandleStringWebRequest()",
200, "Request received in Sample Object Interceptor for HandleStringWebRequest");
/*
* Add code to manipulate requests here
*/
IWebRequestHandler webRequestHandler = FindRequestHandlerDelegate<IWebRequestHandler>();
if (webRequestHandler != null)
{
return webRequestHandler.HandleStringWebRequest(
httpMethod, requestURL, queryString, Capabilities, requestData, out responseContentType, out respDataType);
}
responseContentType = null;
respDataType = esriWebResponseDataType.esriWRDTPayload;
//Insert error response here.
return null;
}
public byte[] HandleBinaryRequest(ref byte[] request)
{
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".HandleBinaryRequest()",
200, "Request received in Sample Object Interceptor for HandleBinaryRequest");
/*
* Add code to manipulate requests here
*/
IRequestHandler requestHandler = FindRequestHandlerDelegate<IRequestHandler>();
if (requestHandler != null)
{
return requestHandler.HandleBinaryRequest(request);
}
//Insert error response here.
return null;
}
public byte[] HandleBinaryRequest2(string Capabilities, ref byte[] request)
{
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".HandleBinaryRequest2()",
200, "Request received in Sample Object Interceptor for HandleBinaryRequest2");
/*
* Add code to manipulate requests here
*/
IRequestHandler2 requestHandler = FindRequestHandlerDelegate<IRequestHandler2>();
if (requestHandler != null)
{
return requestHandler.HandleBinaryRequest2(Capabilities, request);
}
//Insert error response here.
return null;
}
public string HandleStringRequest(string Capabilities, string request)
{
_serverLog.LogMessage(ServerLogger.msgType.infoStandard, _soiName + ".HandleStringRequest()",
200, "Request received in Sample Object Interceptor for HandleStringRequest");
/*
* Add code to manipulate requests here
*/
IRequestHandler requestHandler = FindRequestHandlerDelegate<IRequestHandler>();
if (requestHandler != null)
{
return requestHandler.HandleStringRequest(Capabilities, request);
}
//Insert error response here.
return null;
}
#endregion
#region Utility code
private IServerEnvironment2 ServerEnvironment
{
get
{
if (_serverEnvironment == null)
{
UID uid = new UIDClass();
uid.Value = "{32D4C328-E473-4615-922C-63C108F55E60}";
// CoCreate an EnvironmentManager and retrieve the IServerEnvironment
IEnvironmentManager environmentManager = new EnvironmentManager() as IEnvironmentManager;
_serverEnvironment = environmentManager.GetEnvironment(uid) as IServerEnvironment2;
}
return _serverEnvironment;
}
}
private THandlerInterface FindRequestHandlerDelegate<THandlerInterface>() where THandlerInterface : class
{
try
{
IPropertySet props = ServerEnvironment.Properties;
String extensionName;
try
{
extensionName = (String)props.GetProperty("ExtensionName");
}
catch (Exception /*e*/)
{
extensionName = null;
}
if (String.IsNullOrEmpty(extensionName))
{
return (_soHelper.ServerObject as THandlerInterface);
}
// Get the extension reference from cache if available
if (_extensionCache.ContainsKey(extensionName))
{
return (_extensionCache[extensionName] as THandlerInterface);
}
// This request is to be made on a specific extension
// so we find the extension from the extension manager
IServerObjectExtensionManager extnMgr = _soHelper.ServerObject as IServerObjectExtensionManager;
IServerObjectExtension soe = extnMgr.FindExtensionByTypeName(extensionName);
return (soe as THandlerInterface);
}
catch (Exception e)
{
_serverLog.LogMessage(ServerLogger.msgType.error,
_soiName + ".FindRequestHandlerDelegate()", 500, e.ToString());
throw;
}
}
#endregion
private String GetOutputImageFileLocation(String virtualPath)
{
/*
* Sample output returned by MapServer SO
*
* example : /rest/directories/arcgisoutput/SampleWorldCities_MapServer/
* _ags_map26c62f8c2c0c4965b53e87e300e1912f.png
*/
var virtualPathParts = virtualPath.Split('/');
String imageFileLocation = _outputDirectory;
// build the physical path to the image file
bool buildPath = false;
foreach (String virtualPathPart in virtualPathParts)
{
if (buildPath)
{
imageFileLocation += "\\" + virtualPathPart;
}
if (virtualPathPart.Equals("arcgisoutput", StringComparison.CurrentCultureIgnoreCase))
{
buildPath = true;
}
}
return imageFileLocation;
}
}
}
4、运行生成项目即可生成WaterMarkSOI.soe文件,具体路径可以通过输出窗口查看
5、打开Server,添加soe文件到扩展模块中,具体操作如下
6、效果图如下:
源码下载地址:http://download.csdn.net/detail/u010520626/9462545
ApplyWatermark.cs类的代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace WaterMarkSOI
{
public class ApplyWatermark
{
public Color Color { get; set; }
public Font Font { get; set; }
public string WatermarkText { get; set; }
public ContentAlignment TextAlignment { get; set; }
/// <summary>
/// Creates an instance of Watermarker class.
/// </summary>
public ApplyWatermark ()
{
Color = Color.Aquamarine;
Font = new Font(FontFamily.GenericSansSerif, 16);
WatermarkText = "(c) ESRI Inc.";
TextAlignment = ContentAlignment.BottomLeft;
}
public Image Mark( Image image, string waterMarkText )
{
WatermarkText = waterMarkText;
Bitmap originalBmp = (Bitmap)image;
// avoid "A Graphics object cannot be created from an image that has an indexed pixel format." exception
Bitmap tempBitmap = new Bitmap(originalBmp.Width, originalBmp.Height);
// From this bitmap, the graphics can be obtained, because it has the right PixelFormat
Graphics g = Graphics.FromImage(tempBitmap);
using (Graphics graphics = Graphics.FromImage(tempBitmap))
{
// Draw the original bitmap onto the graphics of the new bitmap
g.DrawImage(originalBmp, 0, 0);
var size =
graphics.MeasureString(WatermarkText, Font);
var brush =
new SolidBrush(Color.FromArgb(255, Color));
graphics.DrawString
(WatermarkText, Font, brush,
GetTextPosition(image, size));
}
return tempBitmap as Image;
}
public Image Mark ( Image image )
{
return Mark(image, WatermarkText);
}
private PointF GetTextPosition ( Image image, SizeF size )
{
PointF point = default(PointF);
switch (TextAlignment)
{
case ContentAlignment.BottomCenter:
point = new PointF((image.Width - size.Width) / 2,
(image.Height - size.Height));
break;
case ContentAlignment.BottomLeft:
point = new PointF(0, (image.Height - size.Height));
break;
case ContentAlignment.BottomRight:
point = new PointF((image.Width - size.Width),
(image.Height - size.Height));
break;
case ContentAlignment.MiddleCenter:
point = new PointF((image.Width - size.Width) / 2,
(image.Height - size.Height) / 2);
break;
case ContentAlignment.MiddleLeft:
point = new PointF(0, (image.Height - size.Height) / 2);
break;
case ContentAlignment.MiddleRight:
point = new PointF((image.Width - size.Width),
(image.Height - size.Height) / 2);
break;
case ContentAlignment.TopCenter:
point = new PointF((image.Width - size.Width) / 2, 0);
break;
case ContentAlignment.TopLeft:
point = new PointF(0, 0);
break;
case ContentAlignment.TopRight:
point = new PointF((image.Width - size.Width), 0);
break;
}
return point;
}
}
}
利用ArcGIS Server SOI 创建水印地图相关推荐
- ArcGIS Server SOI的调试与触发
本人在完成创建水印出图SOI(https://blog.csdn.net/u010520626/article/details/50899642,感谢yizhi鬼的实验记录)的实验编码后,一度懵逼不知 ...
- 一、ArcGIS Server篇:利用ArcGIS Server发布动态地图服务
写在前面的话:本篇博客参考 在WebGIS开发过程中,我们所需要的数据不仅仅来自于ArcGIS online,有时候我们需要发布自己的数据服务,在本篇博客中主要说明一下如何利用ArcGIS Serve ...
- ArcGIS Server ADF开发:地图配置:美丽的新疆地图
ArcGIS Server ADF开发:地图配置:美丽的新疆地图 美丽的新疆地图2:
- arcgis Server 站点创建报错 Server machine is not a local server machine
ArcGIS Server版本 10.4.1 问题描述 Failed to create the site. Failed to configure the server machine 'WIN-M ...
- arcgis server账号需要设置地图缓存的访问权限
如果gis服务起不来,那么可以看看arcgis server账号有没有设置地图缓存的访问权限,有可能arcgis server账号没有这个文件夹的访问权限. 本文用菊子曰发布 转载于:https:/ ...
- ArcGIS Server 开发之鹰眼地图的实现
2019独角兽企业重金招聘Python工程师标准>>> 鹰眼简单点说就是地图的联动,鹰眼的全称是OverviewMap,在ERSI提供的API包中,在dijit中进行类的调用.查了很 ...
- 手机调用ArcGIS Server发布的Rest地图服务不显示问题
如果是本地发布的服务,在手机端调用server服务时,访问rest地址主机名要改为IP加端口号(192.168.1.100:6080),而且必须是内网才能访问 "http://192.168 ...
- Arcgis Javascript那些事儿(五)--arcgis server发布自定义比例尺地图
有时候我们使用arcgisserver发布切片地图的时候,比例尺放大级别达不到我们的要求,这个时候我们使用平时用的切片方案:arcigs online,bing map,google map就行不通了 ...
- ArcGIS Server 简介
ArcGIS Server ArcGIS Server--企业级GIS服务器 产品概况 关键特征 扩展模块 常见问题 ArcGIS Server--企业级GIS服务器 ArcGIS Server是一个 ...
最新文章
- matlab模型参数不匹配怎么办,修改Simulink模型后出现初始状态大小不匹配的错误...
- [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍
- 在html页面比较两个时间戳,如何比较C中的两个时间戳?
- boost::hana::extend用法的测试程序
- OSS在线迁移服务剖析
- 【python】字符串连接错误,类型错误 TypeError: coercing to Unicode
- 大数据学习笔记45:Sqoop - 数据迁移工具
- 计算机是通过 来访问存储单元的,计算机是通过____来访问存储单元的
- JAVA的sleep
- Linux操作汇总(常用命令、vim)
- 马虎将classname加到了id属性中,造成报错
- NeatUpload——支持大文件上传的控件
- 账龄分析表excel模板_老会计分享财务报表及EXCEL会计报表分析系统模板!收藏领取!...
- c语言结构体stamp是什么意思,stamp是什么意思
- 2的17次方java中表示什么_2的17次方是多少
- linux中批量删除用户,Linux shell批量删除用户
- 《修C传》——初始C语言 <凝气篇>
- PS抠图之单色背景图片
- 知乎高赞的7个顶级资源网站,记住了帮你减少一半的搜索时间
- 【Java进阶营】阿里架构师手把手教你如何简单快捷地构建Spring应用
热门文章
- 吉林建筑大学电气与计算机学院讲师,吉林建筑大学导师教师信息介绍-电气与计算机学院刘航...
- 2021全国人工智能师资培训正式“开课”,百度飞桨助力高校教师提升AI“超能力”...
- 用于Arduino的S4A图形化编程图文详解
- 如何从服务器复制cadence库文件到windows,cadence使用笔记
- 什么是REST以及 RESTful?
- [Violet]天使玩偶/SJY摆棋子
- c++数独游戏3.3
- CVE-2022-0847(Dirty Pipe)
- typescript完成日期转换
- 疯狂android讲义第4版光盘_卧槽!当当网又又又可以 4 折买书了!!跟我一起薅羊毛了!...