geotools 影像切片 缩放
图像瓦片应用
ImageLab教程涵盖了加载和渲染;本教程将演示如何使用CoverageProcessor和friends在覆盖率上直接执行基本操作(如裁剪和缩放),并使用Arguments工具简化命令行处理。我们将创建一个简单的实用程序应用程序来“平铺”一个覆盖范围(为了简单起见,只是简单地细分信封)并可选地缩放结果平铺
预先准备
其中许多可能已经在前面示例中的pom.xml中了,但至少要确保以下依赖项是可用的
<dependencies><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-geotiff</artifactId><version>${geotools.version}</version></dependency></dependencies>
在 org.geotools.tutorial.coverage包中创建imagetier .java文件。覆盖和复制粘贴以下代码,其中包含我们的样板导入,字段和getter /setter:
package org.geotools.tutorial.coverage;import java.io.File;
import java.io.IOException;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.coverage.processing.Operations;
import org.geotools.gce.geotiff.GeoTiffFormat;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.util.Arguments;
import org.geotools.util.factory.Hints;
import org.opengis.geometry.Envelope;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CoordinateReferenceSystem;/*** Simple tiling of a coverage based simply on the number vertical/horizontal tiles desired and* subdividing the geographic envelope. Uses coverage processing operations.*/
public class ImageTiler {private final int NUM_HORIZONTAL_TILES = 16;private final int NUM_VERTICAL_TILES = 8;private Integer numberOfHorizontalTiles = NUM_HORIZONTAL_TILES;private Integer numberOfVerticalTiles = NUM_VERTICAL_TILES;private Double tileScale;private File inputFile;private File outputDirectory;private String getFileExtension(File file) {String name = file.getName();try {return name.substring(name.lastIndexOf(".") + 1);} catch (Exception e) {return "";}}public Integer getNumberOfHorizontalTiles() {return numberOfHorizontalTiles;}public void setNumberOfHorizontalTiles(Integer numberOfHorizontalTiles) {this.numberOfHorizontalTiles = numberOfHorizontalTiles;}public Integer getNumberOfVerticalTiles() {return numberOfVerticalTiles;}public void setNumberOfVerticalTiles(Integer numberOfVerticalTiles) {this.numberOfVerticalTiles = numberOfVerticalTiles;}public File getInputFile() {return inputFile;}public void setInputFile(File inputFile) {this.inputFile = inputFile;}public File getOutputDirectory() {return outputDirectory;}public void setOutputDirectory(File outputDirectory) {this.outputDirectory = outputDirectory;}public Double getTileScale() {return tileScale;}public void setTileScale(Double tileScale) {this.tileScale = tileScale;}
请注意,这并不是完整的代码清单——我们将在进行过程中完成它——所以如果您的IDE出现问题,现在不要担心
参数处理
因为我们正在创建一个命令行应用程序,所以我们需要处理命令行参数。GeoTools包含一个名为Arguments的类来促进这一点;我们将使用这个类来解析两个强制参数——输入文件和输出目录——以及一些可选参数——垂直和水平的瓦片计数和瓦片缩放。
public static void main(String[] args) throws Exception {// GeoTools provides utility classes to parse command line argumentsArguments processedArgs = new Arguments(args);ImageTiler tiler = new ImageTiler();try {tiler.setInputFile(new File(processedArgs.getRequiredString("-f")));tiler.setOutputDirectory(new File(processedArgs.getRequiredString("-o")));tiler.setNumberOfHorizontalTiles(processedArgs.getOptionalInteger("-htc"));tiler.setNumberOfVerticalTiles(processedArgs.getOptionalInteger("-vtc"));tiler.setTileScale(processedArgs.getOptionalDouble("-scale"));} catch (IllegalArgumentException e) {System.out.println(e.getMessage());printUsage();System.exit(1);}tiler.tile();}private static void printUsage() {System.out.println("Usage: -f inputFile -o outputDirectory [-tw tileWidth<default:256> "+ "-th tileHeight<default:256> ");System.out.println("-htc horizontalTileCount<default:16> -vtc verticalTileCount<default:8>");}
加载覆盖
首先,我们需要加载覆盖范围;GeoTools提供了GridFormatFinder和AbstractGridFormat来抽象地完成这一任务。注意:在写这篇文章的时候,GeoTiff处理有一个小问题,我们单独处理它。
private void tile() throws IOException {AbstractGridFormat format = GridFormatFinder.findFormat(this.getInputFile());String fileExtension = this.getFileExtension(this.getInputFile());// working around a bug/quirk in geotiff loading via format.getReader which doesn't set this// correctlyHints hints = null;if (format instanceof GeoTiffFormat) {hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);}GridCoverage2DReader gridReader = format.getReader(this.getInputFile(), hints);GridCoverage2D gridCoverage = gridReader.read(null);
分割影像
接下来,我们将根据所请求的水平和垂直瓦片计数来细分覆盖率,方法是询问其信封的覆盖率,并将该信封水平和垂直地除以瓦片计数。这将给我们我们的瓦片信封的宽度和高度。然后我们将循环我们的水平和垂直瓷砖计数作物和规模
Envelope2D coverageEnvelope = gridCoverage.getEnvelope2D();double coverageMinX = coverageEnvelope.getBounds().getMinX();double coverageMaxX = coverageEnvelope.getBounds().getMaxX();double coverageMinY = coverageEnvelope.getBounds().getMinY();double coverageMaxY = coverageEnvelope.getBounds().getMaxY();int htc =this.getNumberOfHorizontalTiles() != null? this.getNumberOfHorizontalTiles(): NUM_HORIZONTAL_TILES;int vtc =this.getNumberOfVerticalTiles() != null? this.getNumberOfVerticalTiles(): NUM_VERTICAL_TILES;double geographicTileWidth = (coverageMaxX - coverageMinX) / (double) htc;double geographicTileHeight = (coverageMaxY - coverageMinY) / (double) vtc;CoordinateReferenceSystem targetCRS = gridCoverage.getCoordinateReferenceSystem();// make sure to create our output directory if it doesn't already existFile tileDirectory = this.getOutputDirectory();if (!tileDirectory.exists()) {tileDirectory.mkdirs();}// iterate over our tile countsfor (int i = 0; i < htc; i++) {for (int j = 0; j < vtc; j++) {System.out.println("Processing tile at indices i: " + i + " and j: " + j);// create the envelope of the tileEnvelope envelope =getTileEnvelope(coverageMinX,coverageMinY,geographicTileWidth,geographicTileHeight,targetCRS,i,j);GridCoverage2D finalCoverage = cropCoverage(gridCoverage, envelope);if (this.getTileScale() != null) {finalCoverage = scaleCoverage(finalCoverage);}// use the AbstractGridFormat's writer to write out the tileFile tileFile = new File(tileDirectory, i + "_" + j + "." + fileExtension);format.getWriter(tileFile).write(finalCoverage, null);}}}
创建包络线
我们将根据我们的索引和目标包络线的宽度和高度创建瓦片的包络线:
private Envelope getTileEnvelope(double coverageMinX,double coverageMinY,double geographicTileWidth,double geographicTileHeight,CoordinateReferenceSystem targetCRS,int horizontalIndex,int verticalIndex) {double envelopeStartX = (horizontalIndex * geographicTileWidth) + coverageMinX;double envelopeEndX = envelopeStartX + geographicTileWidth;double envelopeStartY = (verticalIndex * geographicTileHeight) + coverageMinY;double envelopeEndY = envelopeStartY + geographicTileHeight;return new ReferencedEnvelope(envelopeStartX, envelopeEndX, envelopeStartY, envelopeEndY, targetCRS);}
裁剪
现在我们已经有了tile envelope宽度和高度,我们将遍历tile count并根据目标envelope进行裁剪。在本例中,我们将手动创建参数并使用覆盖率处理器来执行CoverageCrop操作。在下一步中,我们将遇到执行覆盖操作的更简单的方法。
private GridCoverage2D cropCoverage(GridCoverage2D gridCoverage, Envelope envelope) {CoverageProcessor processor = CoverageProcessor.getInstance();// An example of manually creating the operation and parameters we wantfinal ParameterValueGroup param = processor.getOperation("CoverageCrop").getParameters();param.parameter("Source").setValue(gridCoverage);param.parameter("Envelope").setValue(envelope);return (GridCoverage2D) processor.doOperation(param);}
缩放
我们可以使用缩放操作来选择缩放我们的瓦片。在本例中,我们将使用Operations类来简化我们的工作。这个类包装了操作,并为它们提供了一个稍微更类型安全的接口。在这里,我们将按相同的比例调整X和Y维度,以保持原始覆盖率的高宽比。
/*** Scale the coverage based on the set tileScale** <p>As an alternative to using parameters to do the operations, we can use the Operations* class to do them in a slightly more type safe way.** @param coverage the coverage to scale* @return the scaled coverage*/private GridCoverage2D scaleCoverage(GridCoverage2D coverage) {Operations ops = new Operations(null);coverage =(GridCoverage2D)ops.scale(coverage, this.getTileScale(), this.getTileScale(), 0, 0);return coverage;}
}
运行程序
在运行应用程序之前,我们需要样本数据。 Natural Earth 50m的数据将做得很好。
用ide运行
如果您一直使用IDE,那么内建的运行功能是运行应用程序的最简单方法。例如,在Eclipse中,我们可以从菜单中选择Run -> Run Configurations并使用以下配置创建新的Java应用程序配置。
image.png
在Arguments选项卡下,我们将把应用程序指向下载的光栅数据,给它一个16x8的瓦片计数,将它输出给一个临时控制器,并将瓦片缩放两倍。
-f /Users/devon/Downloads/NE2_50M_SR_W/NE2_50M_SR_W.tif -htc 16 -vtc 8 -o /Users/devon/tmp/tiles -scale 2.0
请确保将文件名和目录替换为您自己的位置
如果您正在使用Eclipse,那么这些路径可以被提示符替换。在运行对话框中选择变量并使用file_prompt和folder_prompt变量。
image.png
最后,单击Run运行我们的应用程序。你可能会看到一些与ImageIO相关的警告信息,但这些都是正常的。
除Eclipse外的其他ide,如Netbeans和IntelliJ,都有非常类似的Java应用程序运行选项
用maven运行
如果您不使用IDE,那么运行我们的应用程序的最简单方法就是使用Maven exec任务来运行我们的应用程序,详情参见Maven Quickstart。我们只需将Maven Shade插件添加到pom.xml中
mvn exec:java -Dexec.mainClass=org.geotools.tutorial.ImageTiler -Dexec.args="-f /Users/devon/Downloads/NE2_50M_SR_W/NE2_50M_SR_W.tif -htc 16 -vtc 8 -o /Users/devon/tmp/tiles -scale 2.0"
扩展
- 有关覆盖率上可用操作的更多信息,请参阅覆盖率处理器文档。CoverageProcessor中可用的操作之一是Resample(参见操作类),我们可以使用它非常容易地重新投射我们的覆盖率。尝试重新投射覆盖到EPSG:3587(谷歌的网墨卡托投影)。
- 我们可以通过将tiles加载到GeoServer ImageMosaic存储中来验证它们是否正常。或者,我们可以通过编程创建一个指向目录文件的ImageMosaicReader并从中读取。
geotools 影像切片 缩放相关推荐
- GeoServer源码解析栅格数据Image Mosaic JDBC插件原理(一)GDAL生产影像切片
1. 作者声明 GeoServer源码解析栅格数据Image Mosaic JDBC插件原理共分三篇幅 (一)GDAL生产影像切片 (二)GeoTools Image Mosaic JDBC插件源码解 ...
- ArcGIS Server 注册私有云存储并发布影像切片服务
通过本地发布影像切片服务,但切片缓存在私有云存储中 环境配置 ArcGIS Server 1071 ArcGIS desktop1071或Arc GIS Pro 2.4 S3私有云存储 注册私有云存储 ...
- 360°全景影像切片和POI管理
1管理全景影像 ① 点击菜单"文件>>打开全景影像",打开全景影像所在文件夹: ② 编辑全景影像信息: ③ 加入数据库:编辑好信息,单击"加入数据 ...
- 一个简单的影像切片工具,生成xyz格式
使用C#调用gdal写了个简单的遥感影像切xyz工具,只能切tiff影像.界面没设计,代码没优化,也没上多线程,有兴趣的自己拿去改. 全部代码如下,切片逻辑参见 MapTile 这个方法 : usin ...
- Cesium中加载地形影像切片,以及3dtiles和shp及kml方法
1geoserver影像服务 var layerWMTSRest1 = new Cesium.WebMapTileServiceImageryProvider({// 注意:gwc/rest/wmts ...
- geoserver2.18(4):wms服务——GeoWebCache影像切片缓存
1 配置GeoWebCache缓存路径 打开webapps/geoserver/WEB-INF下的web.xml文件,在display-name节点后面添加一下内容: <context-para ...
- GIS开发入坑(二)--ArcGIS影像切片并使用GeoServer发布
目录 1.使用ArcGIS切片 1.1修改ArcMap选项 1.2创建切片缓存方案 1.3开始切片 2.使用GeoServer发布切片缓存 2.1 启用GeoWebcache 2.2 发布切片 Geo ...
- python整形怎么切片_遥感影像切分切片
遥感影像切片 生活当中,我们可能经常遇到处理一个很大的遥感影像情况,例如做一些逐像元运算,不便于并行处理.因此制作了将影像切分成多个小片的程序,切分后保持原有的数值.数据类型.波段数.投影. 切片 用 ...
- OpenLayers 调用 Tomcat 发布的栅格切片服务
前提 Tomcat 8.5.38 CesiumLab 2 OpenLayers JavaScript {z}/{x}/{y}.png 第一次看见这种切片加载形式是在加载谷歌地图中.也是因为在做项目的时 ...
- C#开发PACS医学影像三维重建(一):使用VTK重建3D影像
VTK简介: VTK是一个开源的免费软件系统,主要用于三维计算机图形学.图像处理和可视化.Vtk是在面向对象原理的基础上设计和实现的,它的内核是用C++构建的. 因为使用C#语言开发,而VTK是C++ ...
最新文章
- LeetCode 143. 重排链表(Reorder List)
- python聚类分析如何确定分类个数_Python数据挖掘—聚类—KMeans划分法
- 第18章 类加载机制与反射
- GeoServer简介、下载、配置启动、发布shapefile全流程(图文实践)
- laravel中的数据迁移表结构、字段类型、定义整理
- css未知尺寸的图片的水平和垂直居中
- HTML连载70-相片墙、盒子阴影和文字阴影
- “一键删除中国App”应用海外走红,下载量破500万!谷歌:我先把你删除了
- python中quad_python – 沿quadmesh的x轴的日期
- 日常工作中,个人总结的 - Git - 常用操作方法 (三)
- SQL_Server_2008完全学习之第五章操作架构、索引和视图
- c语言编程中的幂函数如何编写,c语言幂函数_C语言循环与递归实现整数幂函数...
- zip压缩大于4g文件linux,linux下解压大于4G文件提示error: Zip file too big错误的解决办法...
- Debian没有reboot命令
- Win10和win11有什么区别?想重装win10系统怎么操作?
- Vscode 与服务器建立远程连接(ssh)
- WebService 深入详解
- Linux设备驱动---OMAP3630 Linux I2C总线驱动分析(2)
- 妥妥的去面试之Android基础(五)
- 知云文献翻译安装教程_阅读英文文献的好帮手