gdal2tiles.py是GDAL库中用于生成TMS瓦片的python代码,支持谷歌墨卡托EPSG:3857与经纬度EPSG:4326两种瓦片,输出png格式图像。

gdal2tiles.py More info at:

http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
http://wiki.osgeo.org/wiki/WMS_Tiling_Client_Recommendation
http://msdn.microsoft.com/en-us/library/bb259689.aspx
http://code.google.com/apis/maps/documentation/overlays.html#Google_Maps_Coordinates 为啥要改写为纯C++的?项目需求呗,一个系统需要集成一个瓦片切图的功能,但甲方又不希望安装复杂,每次都要配置python环境。
于是开始在网上找切图的开源资源。
使用AE来切图,直接调用GP服务,利用CreateMapServerCache 、ManageMapServerCacheTiles 和Geoprocessor 类来做。但代码中的结构都是必须先发布地图服务。
GeoServer中的GeoWebCache中间件也可切图,但也是需要先发布地图服务,并且切出的瓦片文件命名方式很恶心。http://www.geowebcache.org/ http://www.klokan.cz/projects/gdal2tiles/中核心代码不是开源的。。。。
总之最后决定改写gdal2tiles.py为纯C++代码了。
其实这种改写也不复杂,gdal2tiles.py中需要改写的代码不超过500行,并且调用的python接口gdal函数在c++接口函数里面肯定都有,并且改写后速度有可能更快。 下面是改写成C++的部分关键代码:
根据项目需要。仅支持裁切byte全色与多光谱经纬度投影图像为经纬度网格切片,初始0层为两个切片。生成jpg图像。
接口说明:

Hu2Tiles.exe+ +输入图像+ +结果路径+ +最小层数+ +最大层数+ +querysize

其中querysize数值能取256或者1024,前者最近邻采样,后者平均采样

例子:

echo %time%

Hu2Tiles.exe "D:\\GF3_MYN_QPSI_003841_E119.7_N33.2_20170503_L1A_HH_L10002340710.tiff" "D:\\huPyTiles" 2 14 256

echo %time%

pause

-------------------------------------------------------------------------------------

涉及到坐标转换的函数如下,可见python和C++的代码还是很相似的。

//////////////////////////////////////////////////////////////////////////////////////////////////
//def LonLatToPixels(self, lon, lat, zoom):
//"Converts lon/lat to pixel coordinates in given zoom of the EPSG:4326 pyramid"
//
// res = self.resFact / 2**zoom
// px = (180 + lon) / res
// py = (90 + lat) / res
// return px, py
void CHuGlobalGeodetic::LonLatToPixels(double lon,double lat,int zoom,double* pxy)
{
double res = resFact / pow(2,(double)zoom);
pxy[0] = (180.0 + lon) / res;
pxy[1] = (90.0 + lat) / res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// def PixelsToTile(self, px, py):
//"Returns coordinates of the tile covering region in pixel coordinates"
//
// tx = int( math.ceil( px / float(self.tileSize) ) - 1 )
// ty = int( math.ceil( py / float(self.tileSize) ) - 1 )
// return tx, ty
void CHuGlobalGeodetic::PixelsToTile(double px,double py,int* txy)
{
txy[0] = int(ceil(px/256.0) - 1);
txy[1] = int(ceil(py/256.0) - 1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// def LonLatToTile(self, lon, lat, zoom):
//"Returns the tile for zoom which covers given lon/lat coordinates"
//
// px, py = self.LonLatToPixels( lon, lat, zoom)
// return self.PixelsToTile(px,py)
void CHuGlobalGeodetic::LonLatToTile(double lon,double lat,int zoom,int* txy)
{
double pxy[2] = {0.0,0.0};
double res = resFact / pow(2,(double)zoom);
pxy[0] = (180.0 + lon) / res;
pxy[1] = (90.0 + lat) / res;

txy[0] = int(ceil(pxy[0]/256.0) - 1);
txy[1] = int(ceil(pxy[1]/256.0) - 1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// def Resolution(self, zoom ):
//"Resolution (arc/pixel) for given zoom level (measured at Equator)"
//
// return self.resFact / 2**zoom
//#return 180 / float( 1 << (8+zoom) )
double CHuGlobalGeodetic::Resolution(int zoom)
{
return resFact / pow(2,(double)zoom);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// def ZoomForPixelSize(self, pixelSize ):
//"Maximal scaledown zoom of the pyramid closest to the pixelSize."
//
// for i in range(MAXZOOMLEVEL):
// if pixelSize > self.Resolution(i):
// if i!=0:
// return i-1
// else:
// return 0 # We don't want to scale up
int CHuGlobalGeodetic::ZoomForPixelSize(double pixelSize)
{
for (int i=0;i<32;i++)
{
if(pixelSize > Resolution(i))
{
if (i!=0)
{
return i-1;
}
else
{
return 0;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// def TileBounds(self, tx, ty, zoom):
//"Returns bounds of the given tile"
// res = self.resFact / 2**zoom
// return (
// tx*self.tileSize*res - 180,
// ty*self.tileSize*res - 90,
// (tx+1)*self.tileSize*res - 180,
// (ty+1)*self.tileSize*res - 90
// )
void CHuGlobalGeodetic::TileBounds(int tx, int ty,int zoom, double* bound4)
{
double res = resFact / pow(2,(double)zoom);
bound4[0] = tx * 256.0 * res - 180.0;
bound4[1] = ty * 256.0 * res - 90.0;
bound4[2] = (tx+1) * 256.0 * res - 180.0;
bound4[3] = (ty+1) * 256.0 * res - 90.0;
}

------------------------------------------------------------------------------------------

几个调用gdal函数接口的例子如下,总体上pthon的gdal接口函数更智能,换回C++的稍微麻烦点。。。

int CHu2Tiles::hu_scale_query_to_tile(GDALDataset *dsquery,GDALDataset *dstile)
{

int querysize = dsquery->GetRasterXSize();
int tilesize = dstile->GetRasterXSize();
int tilebands = dstile->GetRasterCount();

if (resampling == "average")
{
if (tilebands == 1)
{
GDALRasterBandH *pRasterBand = new GDALRasterBandH();
pRasterBand[0] = dstile->GetRasterBand(1);
GDALRegenerateOverviews(dsquery->GetRasterBand(1),1,pRasterBand,"AVERAGE",NULL,NULL);
//dstile->GetRasterBand(2)->SetNoDataValue(0);
}
if (tilebands == 3)
{
GDALRasterBandH *pRasterBand = new GDALRasterBandH();
pRasterBand[0] = dstile->GetRasterBand(1);
pRasterBand[1] = dstile->GetRasterBand(2);
pRasterBand[2] = dstile->GetRasterBand(3);
GDALRegenerateOverviews(dsquery->GetRasterBand(1),3,pRasterBand,"AVERAGE",NULL,NULL);
//dstile->GetRasterBand(4)->SetNoDataValue(0);
}
}
else
{
double trans1[6] ={0.0,tilesize/(float)querysize,0.0,0.0,0.0,tilesize/(float)querysize};
double trans2[6] ={0.0,1.0,0.0,0.0,0.0,1.0};
dsquery->SetGeoTransform(trans1);
dstile->SetGeoTransform(trans2);
GDALReprojectImage(dsquery,NULL,dstile,NULL,GRA_Bilinear,0,0,NULL,NULL,NULL);
}

return 0;
}

保存结果图像为jpg格式,就比png图像少处理了一个alpha波段,加上不输出KML文件,最终C++版本程序要比python的快些。实验图像从8秒缩减到4秒左右,更多分层的还没试。

目前只是改写代码,只能生成松散的瓦片图像,并且是单线程处理。后续可考虑修改为多线程。

比如这个:

https://github.com/commenthol/gdal2tiles-leaflet

里面有个:gdal2tiles-multiprocess.py


 
												

瓦片切图工具gdal2tiles.py改写为纯c++版本的更多相关文章

  1. 瓦片切图工具gdal2tiles.py改写为纯c++版本(二)

    python这么火,C++/C#的程序员都生存不下去了,为啥还要干把python转写成c++的这种反动的事? 项目需要呗... gdal2tiles.py文件中有两个类是计算全球墨卡托与WGS84两种 ...

  2. 利用AE编写切图工具的一些探讨

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 这周利用晚上在家时间研究了下如何使用AE来开发切图工具.最初 ...

  3. Cutterman - 最好用的切图工具

    Cutterman - 最好用的切图工具 http://www.cutterman.cn/zh/cutterman

  4. AGS Server 10.1 切图工具

    在AGS Sever中很重要的功能就是地图缓存的制作,安装AGS Sever会在catalog中增加相关的工具箱,利用这些工具可以制作.删除.更新切片 一.Convert map server cac ...

  5. PS切图工具

    缓存设置: 编辑-首选项-暂存盘 改完除了C盘之外的其他盘 单位设置: 编辑-首选项-单位与标尺 将单位修改成像素  PS预设: 工具   (窗口-工具) 标尺  (视图-标尺) 图层  (窗口-图层 ...

  6. Assistor PS 切图工具的使用说明。

    一.如何运行Assistor PS   使用这个Assistor PS 软件有一个最最重要的条件,那就是:你要打开你的Photoshop (官方建议版本在CS 3以上)   下载-安装-运行. 运行成 ...

  7. sketch最强切图工具Sketch Measure

    https://www.inpandora.com/sketch-measure.html https://www.jianshu.com/p/c11ae88e6b1d

  8. WebGIS中矢量切图的初步研究

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在GIS领域,金字塔技术一直是一个基础性技术,WMTS规范专 ...

  9. 页面制作部分之PS切图

    页面制作部分之PS切图 <--本标签下,通过页面制作.页面架构.javascript程序设计.DOM编程艺术.产品前端架构五部分来分享总结笔记,总结笔记会陆续分享--> 网页设计在技术层面 ...

随机推荐

  1. PHP 技能精进之 PHP-FPM 多进程模型

    PHP-FPM 提供了更好的 PHP 进程管理方式,可以有效控制内存和进程.可以平滑重载PHP配置.那么当我们谈论 PHP-FPM 多进程模型的时候,作为 PHPer 的你了解多少呢? 首先,让我们一 ...

  2. 基于 HTTP 请求拦截,快速解决跨域和代理 Mock

    近几年,随着 Web 开发逐渐成熟,前后端分离的架构设计越来越被众多开发者认可,使得前端和后端可以专注各自的职能,降低沟通成本,提高开发效率. 在前后端分离的开发模式下,前端和后端工程师得以并行工作. ...

  3. PHP扩展高性能日志系统SeasLog简单上手

    Windows部分:-------------------------------------------------------- https://pecl.php.net/package/Seas ...

  4. vue安装jquery和配置(不需要在页面引入直接可以使用)

    首先在命令行工具上输入 npm install jquery --save-dev 安装完成之后在build文件夹下的webpack.base.conf.js进行配置,在顶部添加:const webp ...

  5. SQL注入渗透实战

    概述: 判断注入点: http://www.xxxxx.com/page.php?pid=42 and 1=1 #true http://www.xxxxx.com/page.php?pid=42 a ...

  6. Android ADB命令详解

    adb的全称为Android Debug Bridge.是android司机经常用到的工具 . 你能在本篇文章中学到什么? adb基本指令 Shell AM&PM adb模拟用户事件 logc ...

  7. CentOS_关机与重启命令详解

    Linux centos关机与重启命令详解 Linux centos重启命令: 1.reboot 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 10 过 ...

  8. 20171201 - macOS High Sierra 神级 bug

    昨日亲测有效,macOS High Sierra 神级 bug,系统管理员 root 密码为空,输入就可以登录,具备最高权限. 让人不禁想象 Apple Software 怎么了,人才都流失了吗?

  9. OKR能解决996吗?德鲁克怎么看?

    最近网络上热议的“996”,不由让人想起我们的邻国日本.他们在20年前就有过一个热词“过劳死”,就是职场加班太严重导致的猝死. 最近有一本书新书<过劳时代>,说的就是日本20年前的过劳死. ...

  10. 露脸!钉钉通过SOC2隐私性原则审计,安全和隐私保护达超一流国际标准

    2018年4月3日,阿里巴巴钉钉宣布已经正式通过了两项安全方面的权威资质:SOC2Type1服务审计报告和ISO27018(公有云体系下的隐私保护)证书. 钉钉方透露,此次通过美国注册会计师协会(AI ...