开工之前要先了解一下瓦片地图,瓦片地图金字塔模型是一种多分辨率层次模型,从瓦片金字塔的底层到顶层,分辨率越来越低,但表示的地理范围不变。实现原理就是,首先确定地图服务平台所要提供的缩放级别的数量N,把缩放级别最低、地图比例尺最大的地图图片作为金字塔的底层,即第0层,并对其进行分块,从地图图片的左上角开始,从左至右、从上到下进行切割,分割成相同大小(比如256x256像素)的正方形地图瓦片,形成第0层瓦片矩阵;在第O层地图图片的基础上,按每2x2像素合成为一个像素的方法生成第1层地图图片,并对其进行分块,分割成与下一层相同大小的正方形地图瓦片,形成第1层瓦片矩阵;采用同样的方法生成第2层瓦片矩阵;…;如此下去,直到第N一1层,构成整个瓦片金字塔。

在Google地图中,地图数据由大量的正方形图片组成。共有2级缩放比例,每个地图图片都有坐标值,由X和Y值构成。比例因子zoom取值范围是(0-22)。操作地图滑竿显示更大比例尺地图时,图片的数量发生裂变。两种模式在请求及响应的速度方面有明显的差异,基于地图瓦片服务框架的响应速度要快于传统的WebGIS,同时对地图服务器的负载也相应小一些。

现在可以开工,首先准备好瓦片地图,如果是用来学习研究的话,我们可以通过一些第三方工具(当然自己写一个也可以)从谷歌地图抓取瓦片地图存放到本地,例如以C:\googlemas\satelite\x\y.jpg的格式存放,其中x,y,z分别代瓦片所在的列、行、缩放等级。

有了这些图我们开始拼接了,关于gdal库的介绍的文章很多了,现在我主要是介绍如何用C#来拼接谷歌地图,废话不多说了,直接上代码:

void SaveBitmapBuffered(Dataset src, Dataset dst, int x, int y)
{
if (src.RasterCount < 3) {
System.Environment.Exit(-1);
} // Get the GDAL Band objects from the Dataset
Band redBand = src.GetRasterBand(1);
Band greenBand = src.GetRasterBand(2);
Band blueBand = src.GetRasterBand(3); // Get the width and height of the raster
int width = redBand.XSize;
int height = redBand.YSize; byte[] r = new byte[width * height];
byte[] g = new byte[width * height];
byte[] b = new byte[width * height]; redBand.ReadRaster(0, 0, width, height, r, width, height, 0, 0);
greenBand.ReadRaster(0, 0, width, height, g, width, height, 0, 0);
blueBand.ReadRaster(0, 0, width, height, b, width, height, 0, 0); Band wrb = dst.GetRasterBand(1);
wrb.WriteRaster(x * width, y * height, width, height, r, width, height, 0, 0);
Band wgb = dst.GetRasterBand(2);
wgb.WriteRaster(x * width, y * height, width, height, g, width, height, 0, 0);
Band wbb = dst.GetRasterBand(3);
wbb.WriteRaster(x * width, y * height, width, height, b, width, height, 0, 0);
} /// <summary>
/// 拼接瓦片
/// </summary>
/// <param name="tilesBounds"></param>
/// <param name="tilePath"></param>
/// <param name="outPutFileName"></param>
public void CombineTiles(TilesBounds tilesBounds, string tilePath, string outPutFileName)
{
if (File.Exists(outPutFileName))
{
File.Delete(outPutFileName);
}
int imageWidth = 256 * (tilesBounds.maxCol - tilesBounds.minCol + 1);
int imageHeight = 256 * (tilesBounds.maxRow - tilesBounds.minRow + 1); //Register driver(s).
Gdal.AllRegister();
Driver driver = Gdal.GetDriverByName("GTiff");
Dataset destDataset = driver.Create(outPutFileName, imageWidth, imageHeight, 3, DataType.GDT_Byte, null); for (int col = tilesBounds.minCol; col <= tilesBounds.maxCol; col++)
{
for (int row = tilesBounds.minRow; row <= tilesBounds.maxRow; row++)
{
try
{
string sourceFileName = tilePath + tilesBounds.zoomLevel.ToString() + "\\" + col.ToString() + "\\" + row.ToString() + ".jpg";
if (File.Exists(sourceFileName))
{
Dataset sourceDataset = Gdal.Open(sourceFileName, Access.GA_ReadOnly);
if (sourceDataset != null)
{
SaveBitmapBuffered(sourceDataset, destDataset, col - tilesBounds.minCol, row - tilesBounds.minRow);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
destDataset.Dispose(); } //调用
TilesBounds tilesBounds = new TilesBounds();
tilesBounds.minCol = 107901;
tilesBounds.maxCol = 107926;
tilesBounds.minRow = 49652;
tilesBounds.maxRow = 49668;
tilesBounds.zoomLevel = 17;
string outPutFileName = "c:\\北京卫星图" + tilesBounds.zoomLevel.ToString() + ".tif";
string tilePath = "C:\\googlemaps\\\satelite\\";
CombineTiles(tilesBounds, tilePath, outPutFileName);

ok,大功告成了,看看效果图吧。

GDAL库学习笔记(1):无缝拼接Google卫星图的更多相关文章

  1. numpy, matplotlib库学习笔记

    Numpy库学习笔记: 1.array()   创建数组或者转化数组 例如,把列表转化为数组 >>>Np.array([1,2,3,4,5]) Array([1,2,3,4,5]) ...

  2. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  3. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  4. muduo网络库学习笔记(三)TimerQueue定时器队列

    目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...

  5. C++STL标准库学习笔记(三)multiset

    C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...

  6. 【python】numpy库和matplotlib库学习笔记

    Numpy库 numpy:科学计算包,支持N维数组运算.处理大型矩阵.成熟的广播函数库.矢量运算.线性代数.傅里叶变换.随机数生成,并可与C++/Fortran语言无缝结合.树莓派Python v3默 ...

  7. C++STL标准库学习笔记(一)sort

    前言: 近来在学习STL标准库,做一份笔记并整理好,方便自己梳理知识.以后查找,也方便他人学习,两全其美,快哉快哉! 这里我会以中国大学慕课上北京大学郭炜老师的<程序设计与算法(一)C语言程序设 ...

  8. Java学习笔记(四)——google java编程风格指南(上)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  9. Java学习笔记(五)——google java编程风格指南(中)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

随机推荐

  1. 从客户端(******)中检测到有潜在危险的 Request.Form 值。

    在 提交表单时候,asp.net 提示:"从客户端(......)中检测到有潜在危险的 Request.Form 值" .asp.net中的请求验证特性提供了某一等级的保护措施防止 ...

  2. path类和directory类对文件的路径或目录进行操作

    Path: 对文件或目录的路径进行操作(很方便)[只是对字符串的操作] 1.目录和文件操作的命名控件System.IO    2.string Path.ChangeExtension(string ...

  3. SqlCommand类

    一.常用属性 CommandText 获取或设置要对数据源执行的 Transact-SQL 语句.表名或存储过程. CommandTimeout 获取或设置在终止执行命令的尝试并生成错误之前的等待时间 ...

  4. RTP 包格式 详细解析

    H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +---------------+      |0|1|2|3|4|5|6|7 ...

  5. UESTC_Big Brother 2015 UESTC Training for Graph Theory<Problem G>

    G - Big Brother Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) ...

  6. What is NicEdit?

    NicEdit - WYSIWYG Content Editor, Inline Rich Text Application   What is NicEdit? NicEdit is a Light ...

  7. JAVA JNI

    jni非常好的一篇文章 http://m.blog.csdn.net/article/details?id=22827307 JAVA JNI介绍 http://blog.csdn.net/cyg08 ...

  8. Elasticsearch 安装与集群配置

    一.软件版本 操作系统:CentOS-6.5-x86_64 ES版本:5.0 主机:192.168.63.246 主机: 192.168.63.242 二.部署环境规划:   1. 需求:jdk版本: ...

  9. Robot Framework 安装AutoItLibrary

    1. 下载AutoItLibrary-1.1_x64包,http://code.google.com/p/robotframework-autoitlibrary/ 2. 安装pywin32库,htt ...

  10. 格而知之4:寻找EXC_BAD_ACCESS

    EXC_BAD_ACCESS算是一个比较常见的错误,大部分情况下,它出现在某个对象还未初始化或已被释放后,还去试图访问这个对象的时候,即是在出现悬挂指针的时候(当然也有非悬挂指针导致的EXC_BAD_ ...