一个简单的影像切片工具,生成xyz格式
使用C#调用gdal写了个简单的遥感影像切xyz工具,只能切tiff影像。界面没设计,代码没优化,也没上多线程,有兴趣的自己拿去改。
全部代码如下,切片逻辑参见 MapTile 这个方法 :
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using GDAL = OSGeo.GDAL;
using OGR = OSGeo.OGR;
using System.IO;
namespace MapTileTool
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
}
private void HandleGeoTiffSelect(object sender, EventArgs e)
{
string title = "选择遥感影像";
string filter = "tif文件(*.tif,*.tiff)|*.tif;*.tiff";
string fileName = FileChooserSelect(title, filter);
if (null != fileName) {
this.tifTextBox.Text = fileName;
}
}
private void HandleGeoTiffRest(object sender, EventArgs e)
{
this.tifTextBox.Text = ""; ;
}
private void HandleOutputSelect(object sender, EventArgs e)
{
string outputPath = FoloderChooserSelect("选择输出文件夹");
if (null != outputPath) {
this.outputTextBox.Text = outputPath;
}
}
private void HandleOutputRest(object sender, EventArgs e)
{
this.outputTextBox.Text = "";
}
private void ExecuteMapTile(object sender, EventArgs e)
{
string geoTiffPath = tifTextBox.Text;
string outputPath = outputTextBox.Text;
string zMin = zMinTextBox.Text;
string zMax = zMaxTextBox.Text;
if (string.IsNullOrEmpty(geoTiffPath)
|| string.IsNullOrEmpty(outputPath)
|| string.IsNullOrEmpty(zMin)
|| string.IsNullOrEmpty(zMax)) {
MessageBox.Show("信息填写有误");
return;
}
try
{
int zMinLevel = Convert.ToInt32(zMin);
int zMaxLevel = Convert.ToInt32(zMax);
executeBtn.Enabled = false;
consoleLabel.Text = "正在切片,请稍候。。。";
MapTile(geoTiffPath, outputPath, zMinLevel, zMaxLevel);
consoleLabel.Text = "恭喜,影像切片已完成";
executeBtn.Enabled = true;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
consoleLabel.Text = "切图异常:" + ex.Message;
executeBtn.Enabled = true;
}
}
/**
* 切片处理逻辑
*/
private void MapTile(string geoTiffPath, string outputPath, int zMin, int zMax) {
try
{
OGR.Ogr.RegisterAll();
GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
}
catch (Exception ex)
{
Console.WriteLine("Gdal驱动注册失败:" + ex.Message);
}
OSGeo.GDAL.Dataset dataset = GDAL.Gdal.Open(geoTiffPath, OSGeo.GDAL.Access.GA_ReadOnly);
int width = dataset.RasterXSize;
int height = dataset.RasterYSize;
int bandCount = dataset.RasterCount;
double[] transform = new double[6];
dataset.GetGeoTransform(transform);
double lonMin = transform[0];
double lonMax = transform[0] + (width * transform[1]);
double latMin = transform[3] + (height * transform[5]);
double latMax = transform[3];
if (zMin < 6)
{
zMin = 6;
}
if (zMax > 18)
{
zMax = 18;
}
for (int z = zMin; z <= zMax; z++)
{
int tileRowMin = GetXyTileByZ(lonMin, latMax, z)[0];
int tileRowMax = GetXyTileByZ(lonMax, latMin, z)[0];
int tileColMin = GetXyTileByZ(lonMin, latMax, z)[1];
int tileColMax = GetXyTileByZ(lonMax, latMin, z)[1];
double tempLonMin = GetLngLatByXyz(tileRowMin, tileColMin, z)[0];
double tempLonMax = GetLngLatByXyz(tileRowMin + 1, tileColMin, z)[0];
double tempLatMin = GetLngLatByXyz(tileRowMin, tileColMin + 1, z)[1];
double tempLatMax = GetLngLatByXyz(tileRowMin, tileColMin, z)[1];
// 获取X轴方向分辨率
double xResolution = (tempLonMax - tempLonMin) / 256;
// 获取Y轴方向分辨率
double yResolution = (tempLatMax - tempLatMin) / 256;
for (int x = tileRowMin; x <= tileRowMax; x++)
{
for (int y = tileColMin; y <= tileColMax; y++)
{
double tileLonMin = tempLonMin + (x - tileRowMin) * xResolution * 256;
double tileLatMax = tempLatMax - (y - tileColMin) * yResolution * 256;
try
{
double xTileMax = tileLonMin + 256 * xResolution;
double yTileMin = tileLatMax - 256 * yResolution;
List<int> positionMin = GetPosition(tileLonMin, tileLatMax, transform);
List<int> positionMax = GetPosition(xTileMax, yTileMin, transform);
Boolean contain = positionMin[0] < width && positionMin[0] >= 0
&& positionMin[1] < height && positionMin[1] >= 0
&& positionMax[0] < width && positionMax[0] >= 0
&& positionMax[1] < height && positionMax[1] >= 0;
Bitmap bitmap = new Bitmap(256, 256);
if (contain)
{
int xDistant = positionMax[0] - positionMin[0] + 1;
int yDistant = positionMax[1] - positionMin[1] + 1;
bitmap = new Bitmap(xDistant, yDistant);
if (bandCount == 1)
{
float[] gs = new float[xDistant * yDistant];
dataset.GetRasterBand(1).ReadRaster(positionMin[0], positionMin[1], xDistant, yDistant, gs, xDistant, yDistant, 0, 0);
for (int i = 0; i < xDistant; i++)
{
for (int j = 0; j < yDistant; j++)
{
float g = gs[xDistant * j + i];
if (g < 0)
{
continue;
}
int gray = (int)(255 * g);
Color color = Color.FromArgb(gray, gray, gray);
bitmap.SetPixel(i, j, color);
}
}
}
else
{
int[] rs = new int[xDistant * yDistant];
int[] gs = new int[xDistant * yDistant];
int[] bs = new int[xDistant * xDistant];
dataset.GetRasterBand(1).ReadRaster(positionMin[0], positionMin[1], xDistant, yDistant, rs, xDistant, yDistant, 0, 0);
dataset.GetRasterBand(2).ReadRaster(positionMin[0], positionMin[1], xDistant, yDistant, gs, xDistant, yDistant, 0, 0);
dataset.GetRasterBand(3).ReadRaster(positionMin[0], positionMin[1], xDistant, yDistant, bs, xDistant, yDistant, 0, 0);
for (int i = 0; i < xDistant; i++)
{
for (int j = 0; j < yDistant; j++)
{
int r = rs[xDistant * j + i];
int g = gs[xDistant * j + i];
int b = bs[xDistant * j + i];
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
{
continue;
}
Color color = Color.FromArgb(r, g, b);
bitmap.SetPixel(i, j, color);
}
}
}
}
else
{
for (int i = 0; i < 256; i++)
{
for (int j = 0; j < 256; j++)
{
double tileLon = tileLonMin + i * xResolution;
double tileLat = tileLatMax - j * yResolution;
List<int> position = GetPosition(tileLon, tileLat, transform);
int xPosition = position[0];
int yPosition = position[1];
if (xPosition < 0 || yPosition < 0 || xPosition >= width || yPosition >= height)
{
continue;
}
Color color;
if (bandCount == 1)
{
float[] values = new float[1];
dataset.GetRasterBand(1).ReadRaster(xPosition, yPosition, 1, 1, values, 1, 1, 0, 0);
if (values[0] < 0)
{
continue;
}
int gray = (int)(255 * values[0]);
color = Color.FromArgb(gray, gray, gray);
}
else
{
int[] rs = new int[1];
int[] gs = new int[1];
int[] bs = new int[1];
dataset.GetRasterBand(1).ReadRaster(xPosition, yPosition, 1, 1, rs, 1, 1, 0, 0 );
dataset.GetRasterBand(2).ReadRaster(xPosition, yPosition, 1, 1, gs, 1, 1, 0, 0);
dataset.GetRasterBand(3).ReadRaster(xPosition, yPosition, 1, 1, bs, 1, 1, 0, 0);
int r = rs[0];
int g = gs[0];
int b = bs[0];
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
{
continue;
}
color = Color.FromArgb(r, g, b);
}
bitmap.SetPixel(i, j, color);
}
}
}
try
{
String layerPath = outputPath + "/" + z + "/" + x;
if (!System.IO.Directory.Exists(layerPath))
{
System.IO.Directory.CreateDirectory(layerPath);
}
String imagePath = layerPath + "/" + y + ".png";
bitmap.Save(imagePath);
}
catch (Exception e)
{
Console.WriteLine("切图异常:" + e.Message);
consoleLabel.Text = "切图异常:" + e.Message;
}
}
catch (Exception e)
{
Console.WriteLine("切图异常:" + e.Message);
consoleLabel.Text = "切图异常:" + e.Message;
}
}
}
}
}
/**
* 获取行列号
*
* @param lng
* @param lat
* @param z
*/
public static List<int> GetXyTileByZ(double lng, double lat, int z)
{
List<int> xy = new List<int>(2);
int x = (int)Math.Floor((lng + 180) / 360 * Math.Pow(2, z));
int y = (int)Math.Floor((1 - Math.Log(Math.Tan(Math.PI*lat/180) + 1 / Math.Cos( Math.PI*lat/180)) / Math.PI) / 2 * (Math.Pow(2, z)));
xy.Add(x);
xy.Add(y);
return xy;
}
/**
* 根据经纬度获取影像像素位置
*/
public static List<int> GetPosition(double lng, double lat, double[] transform)
{
double dTemp = transform[1] * transform[5] - transform[2] * transform[4];
int xPix = (int)((transform[5] * (lng - transform[0]) - transform[2] * (lat - transform[3])) / dTemp);
int yPix = (int)((transform[1] * (lat - transform[3]) - transform[4] * (lng - transform[0])) / dTemp);
List<int> xy = new List<int>(2);
xy.Add(xPix);
xy.Add(yPix);
return xy;
}
/**
* 根据切片序列号获取经纬度坐标
* @return
*/
public static List<Double> GetLngLatByXyz(int x, int y, int z)
{
List<Double> xy = new List<Double>(2);
double n = Math.Pow(2, z);
double lng = x / n * 360.0 - 180.0;
double lat = Math.Atan(Math.Sinh(Math.PI * (1 - 2 * y / n)));
lat = lat * 180.0 / Math.PI;
xy.Add(lng);
xy.Add(lat);
return xy;
}
/**
* 选择文件控件
*/
private static string FileChooserSelect(string title, string filter)
{
string fileName = "";
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Multiselect = true;
fileDialog.Title = title;
fileDialog.Filter = filter;
if (fileDialog.ShowDialog() == DialogResult.OK)
{
fileName = fileDialog.FileName;
}
return fileName;
}
/**
* 选择文件夹控件
*/
private static string FoloderChooserSelect(string title)
{
string folderPath = "";
FolderBrowserDialog folderDialog = new FolderBrowserDialog();
folderDialog.Description = title;
if (folderDialog.ShowDialog() == DialogResult.OK)
{
folderPath = folderDialog.SelectedPath;
}
return folderPath;
}
}
}
一个简单的影像切片工具,生成xyz格式相关推荐
- [Winform]一个简单的账户管理工具
最近一直觉得注册的账户越来越多,帐号密码神马的容易弄混.自己就折腾了一个简单的账户管理工具,其实实现也挺简单,将每个账户的密码及相关密码提示信息,经aes算法加密之后保存到数据库,当前登录用户可以查询 ...
- JNI开发笔记(四)--实现一个简单的JNI工程并生成so库
实现一个简单的JNI工程并生成so库 引 前言 1. 编写C/h文件并添加到工程 2. 修改CmakeLists.txt文件 3. 编写native-lib.cpp文件 4. 在MainActivit ...
- 实现一个简单的压测工具
公司开发了一些服务器程序:上生产前需要进行压力测试,测试点包括:并发数.响应时间.吞吐量等指标.领导说,能不能仿照LoadRunner实现一个简单的压测工具(并发数在10000以上,结果指标以曲线图的 ...
- [HDF5] 封装了一个简单的C++ HDF5工具库,实现常用数据类型的读写
目录 一.开发环境 二.主要功能 三.文件结构 四.HDF5写数据到hdf5文件功能实现 五.HDF5读hdf5文件数据到程序中数据结构功能实现 六.头文件Hdf5Function.h 七.工具类 八 ...
- 虚拟桌面:一个简单的桌面管理工具
转载请标明是引用于 http://blog.csdn.net/chenyujing1234 欢迎大家拍砖! 参考英文文章: <<Virtual Desktop: A Simple Desk ...
- SpringBoot + FFmpeg实现一个简单的M3U8切片转码系统
使用大名鼎鼎的ffmpeg,把视频文件切片成m3u8,并且通过springboot,可以实现在线的点播. 想法 客户端上传视频到服务器,服务器对视频进行切片后,返回m3u8,封面等访问路径.可以在线的 ...
- 一个简单的monkey测试工具
Monkey的概念: "猴子测试"是指没有测试经验的人甚至对计算机根本不了解的人(就像猴子一样)不需要知道程序的任何用户交互方面的知识,如果给他一个程序,他就会针对他看到的界面进行 ...
- 研究开源gpt-2-simple项目,跑一个简单的模型,然后生成一段对话。用的是 Intel(R) Core(TM) i7-9700,8核8线程,训练最小的模型200次跑1个小时20分钟
目录 前言 1,关于gpt2的几个例子学习 2,使用docker配置环境 3,使用uget工具下载模型,文件大容易卡死 4,研究使用gpt2-simple执行demo,训练200次 5,总结 前言 本 ...
- php随机数怎么获取?一个简单的函数就能生成
小美女建了一个站,有些页面相似度比较高,想添加一些字段来实现差异化,比如用php随机数生成从10到100之间随机一个数字.其实会php的朋友几十个字符就能实现了,如下代码所示,简单吧?10代表最小值, ...
最新文章
- matlab各名称,Matlab-Simulink各模块对应的中文名称及介绍
- Ubuntu 16.04卸载一些不必要的预装软件
- 求根节点到叶节点数字之和Python解法
- 软工网络15个人阅读作业2——提问题
- react+redux+node报错Tapable.plugin is deprecated. Use new API on `.h ooks` instead
- GitHub更新Fork代码
- 转 JMeter之修改Sampler响应数据的编码格式
- 三电系统集成技术杂谈
- webpower邮件营销平台可以带来什么?
- 语法分析——自顶向下分析方法
- 编码器/译码器(Verilog HDL)|计算机组成
- pink老师世纪佳缘作业
- (软考高级、高项)信息系统项目管理师(第三版)过关经验
- 【寒假每日一题2022】acw1934. 贝茜放慢脚步【二路归并】
- linux系统查看dns缓存,如何清空linux的DNS缓存
- MATLAB 数据分析方法(第2版)1.2 MATLAB基础概述
- 计算机技术应用体验,2018教师信息技术应用体验学习个人心得体会2篇
- Matlab 求方程的根
- 【Flutter】ListView 列表高级功能 ( RefreshIndicator 下拉刷新组件 )
- uniapp中tabbar设置报错文件查找失败,at mian.js:5