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

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

gdal2tiles.py More info at:

http://wiki.osgeo.org/wiki/Tile_Map_Service_Specificationhttp://wiki.osgeo.org/wiki/WMS_Tiling_Client_Recommendationhttp://msdn.microsoft.com/en-us/library/bb259689.aspxhttp://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


 
				
时间: 2024-08-07 08:36:47

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

切图工具上线了

百度地图离线开发,用在内网于局域网项目开发上,完全脱离互联网访问,可支持完整的全国瓦片图下载,使用目前最新的V2.0百度API,BS架构,CS架构,支持热力,聚合,海量标注,根据范围米数来圈范围,画图工具等完全支持.http://api.jjszd.com:8081/apituiguang/gisysw.html 切图工具上线了,用于大图切成百度瓦片,无缝对接,无偏移,所见即所得的效果,图片直接地图上拖动,点击切图,显示在哪就切在哪.免费下载地址: http://www.jjszd.com/Ma

利用AE制作切图工具的一些探讨

1.前言 这周利用晚上在家时间研究了下如何使用AE来开发切图工具.最初的想法是直接调用GP服务,利用CreateMapServerCache .ManageMapServerCacheTiles 和Geoprocessor 这样三个类来做.但是这个思路有个巨大的弊端就是必须先发布地图服务.于是接下里我又马上转换思路,想能否通过瓦片选址算法以及AE的一些细粒度类来实现这个功能.在经过了三个夜晚的煎熬后,整个工具基本成型,其中包括了对算法的优化以及一些具体问题的解决.这里我跟大家大致分享下. 2.切

前段切图工具---Mark Man

前段切图工具---Mark Man Mark Man是一款非常不错的切图工具,当我们拿到设计图时,可以将图片拖进Mark Man中,然后我们就可以利用Mark Man来量取尺寸(注意:不论你放大还是缩小图片,量出来的尺寸都是不会改变的). 获取颜色值.备注等等.总之,这款软件值得拥有. 安装步骤如下: 第一步:进入官网下载. 第二步:由于我们得到的是air类型的文件,所以必须下载Adobe Air Runtime. 第三步:安装Adobe Air Runtime, 此时就能正常打开Mark Ma

fabric.js的简单上手及基于fabric.js的canvas切图工具:1、基本使用及配置

参考链接 Fabric.js 简单介绍和使用 简介 Fabric.js是一个可以简化canvas程序编写的库. Fabric.js为canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的工具.基于MIT协议开源,在github上有许多人贡献代码. 为什么选择fabric.js 手上的项目必须使用canvas 原生的canvas API不够友好 用fabric.js实现切图用户体验更好 为项目以后的迭代留下扩展的余地 简单上手 请参考文章开头的参考链接 这里主要介绍

PS切图工具

# Cutterman 3.2安装指南 当前版本: 3.2 适用于MAC/WIN 下的PS CC/CC2014/CC2015版本,注意不支持CS6 !!! 注意 !!! 更新cutterman的同学,请阅读##卸载安装##的步骤!!!注意结束 !!! ## 这里有安装的视频教程,请查看http://www.cutterman.cn/v2/installation ## 第一次安装(之前没安装过Cutterman)1. 打开PS2. 菜单栏 文件->脚本->浏览,选择当前目录下的“第一次安装.j

WebGIS中矢量切图的初步研究

1.背景 在GIS领域,金字塔技术一直是一个基础性技术,WMTS规范专门制定了针对切片请求的格式.利用这种技术,前端可以快速展示出指定级别的地图或影像. 但是,由于切图本身是一张图片,图片上看似是兴趣点的要素根本无法进行前端交互.于是,针对兴趣点等矢量数据的展示,基本原理都是先获取到矢量的地理信息(比如GeoJson),在前端绘制(内核为一个element),于是该element便能进行鼠标响应等交互了. 2.矢量数据的一般展示方法 2.1 矢量数据按需请求 根据需要,每次向服务器(比如根据地理

ps切图步骤

我们要用到的切图工具有两个,一个是切片工具,另一个是切片选择工具.左边有个小按钮,你按住它这三个选项就会显示出来. 2.这是我等下用做示范的图片. 3.在切图之前有一点需要说明的是,如果你需要辅助切图,你可以先添加参考线.在PS上方的菜单栏,你可以在视图里找到新建参考线选项.如上图,我已经添加两条参考线,因为参考线在鼠标靠近的时候有吸附功能,所以切图不容易切错位置. 4.好了现在我们开始切图,我用切图工具先裁一个框出来,我们可以看到图片上已经有01的框,但是右边02显示为灰色. 5.我继续用切图

网页设计中的切图

一般的网站制作步骤大体上为:设计效果图–>切图+制作静态html模板–>嵌套至CMS,其中,切图虽然是很简单的一个步骤,但其中也有很多技巧,以下是我个人总结出来的几点. 总体上,把握一个原则,能用css写的,坚决不要用图片. 经验告诉我们,首页图片很多的网站打开会很慢,一是因为图片多,需要下载的文件体积就增大,二是每一个图片下载都会对服务器有一个请求,增大了浏览器与服 务端的交互次数,如果能把纯色的部分用css来写,而不因为省事直接切图,就会极大提高网站的运行效率,我最早开始学习制作网站时,就

做一个会PS切图的前端开发

系列链接 做一个会使用PS的前端开发 做一个会PS切图的前端开发 切图方法分类 PhotoShop从CS版本演变到现在的CC版本,切图功能发生了比较大的变化,我们可以把PhotoShop CS版本时的切图功能称为传统切图,而从PhotoShop CC版本开始PS提出了精准切图.所谓传统切图就是切图人员基本上都是自己分割图层切图,传统切图又分为全手工切图和参考线切图:现在CC版本提出的精准切图,切图人员可以依赖计算机把图层对象精确的切割出来,这样切割出来的图层肯定比传统切图切出来的精准度高.另一方