1. 概述

在前面的章节,我们主要讲述了GeoTools对于矢量(主要是Shape)数据的操作。在地理信息系统的世界里,还有一类很重要的数据类型,那便是栅格数据。虽然GeoTools对于栅格数据的支持并没有gdal强大,但既然他作为GeoTools的一部分,我们还是又必要了解一下它。

2. GridCoverage

GeoTools对于栅格数据的支持主要又由GridCoverage实现的。作为一名程序员,我们习惯于处理诸如JPEG、GIF或者PNG等格式的栅格数据。在地理空间方面,有一个Coverage个概念,他是空间定位要素的集合。非正式地,我们将地图和Coverage视为等同,当然,这是相对于地理意思而非编程思维上。

GridCoverage是Coverage的一个特例,他要求栅格要以矩形的形式填充到Coverage的区域中。在我们的java代码中,我们可以使用位图图形作为GridCoverage的后台数据结构,并使用其他元素记录特定坐标系中的空间边界。

这里有许多种GridCoverage的文件格式,最常用的如一下三类。

  • World+ 图像

    一种普通的图像格式,如jpeg或png,它有一个sidecar 文件来描述它的位置,还有一个prjsidecar文件来定义地图投影,就像shapefile使用的那样。请注意,尽管jpeg格式由于下载量小而很常见;运行时的性能非常糟糕,因为整个图像都需要读入内存。TIFF等格式没有此限制。

  • GeoTiff

    具有存储在图像元数据字段中的地理空间信息的普通tiff图像。这通常在安全的前提下表现出良好的性能;特别是如果它已经准备了一个内部覆盖(可用于缩小)或内部平铺(允许快速平移时放大)。当计算机的磁盘速度比CPU快时,性能最佳。

  • JPEG2000

    他jpeg的扩展,使用小波压缩来处理大量图像。文件格式还支持可用于存储地理空间信息的元数据字段。当您CPU速度比磁盘访问更快的情况下,这种格式的性能最好。

针对上面三种数据个数的描述,我们知道,第一种数据格式基本是被摒弃的那种。GeoTiff和JPEG2000的区别是要看IO性能VS CPU性能。

3. GridCoverage对栅格数据的操作

在本篇文章中,我们主要关注GridCoverage对于栅格数据的加载,波段提取,显示样式的创建。

3.1 栅格数据的加载

AbstractGridFormat format = GridFormatFinder.findFormat(rasterFile);
// this is a bit hacky but does make more geotiffs work
Hints hints = new Hints();
if (format instanceof GeoTiffFormat) {hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
}
reader = format.getReader(rasterFile, hints);

3.2 波段提取

GridCoverage2D cov = reader.read(null);
int numBands = cov.getNumSampleDimensions();
for (int i = 0; i < numBands; i++) {GridSampleDimension dim = cov.getSampleDimension(i);//这里依次输出 RED_BAND  GREEN_BANK BLUE_BANKSystem.out.println(dim.getDescription().toString());
}

3.3 样式创建

3.3.1 创建灰度的样式

private Style createGreyscaleStyle(int band) {StyleFactory sf = CommonFactoryFinder.getStyleFactory();FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);SelectedChannelType sct = sf.createSelectedChannelType(String.valueOf(band), ce);RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();ChannelSelection sel = sf.channelSelection(sct);sym.setChannelSelection(sel);return SLD.wrapSymbolizers(sym);
}

3.3.2 创建RGB样式

StyleFactory sf = CommonFactoryFinder.getStyleFactory();
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
SelectedChannelType[] sct = new SelectedChannelType[cov.getNumSampleDimensions()];
ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
for (int i = 0; i < 3; i++) {sct[i] = sf.createSelectedChannelType(String.valueOf(channelNum[i]), ce);
}
RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
ChannelSelection sel = sf.channelSelection(sct[RED], sct[GREEN], sct[BLUE]);
sym.setChannelSelection(sel);
return SLD.wrapSymbolizers(sym);

通过上面的例子,我们可以简单画个时序图及流程图方便大家记忆:

#mermaid-svg-8nAWs1k8mlw14eKn .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-8nAWs1k8mlw14eKn .label text{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .node rect,#mermaid-svg-8nAWs1k8mlw14eKn .node circle,#mermaid-svg-8nAWs1k8mlw14eKn .node ellipse,#mermaid-svg-8nAWs1k8mlw14eKn .node polygon,#mermaid-svg-8nAWs1k8mlw14eKn .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-8nAWs1k8mlw14eKn .node .label{text-align:center;fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .node.clickable{cursor:pointer}#mermaid-svg-8nAWs1k8mlw14eKn .arrowheadPath{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-8nAWs1k8mlw14eKn .flowchart-link{stroke:#333;fill:none}#mermaid-svg-8nAWs1k8mlw14eKn .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-8nAWs1k8mlw14eKn .edgeLabel rect{opacity:0.9}#mermaid-svg-8nAWs1k8mlw14eKn .edgeLabel span{color:#333}#mermaid-svg-8nAWs1k8mlw14eKn .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-8nAWs1k8mlw14eKn .cluster text{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-8nAWs1k8mlw14eKn .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-8nAWs1k8mlw14eKn text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-8nAWs1k8mlw14eKn .actor-line{stroke:grey}#mermaid-svg-8nAWs1k8mlw14eKn .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-8nAWs1k8mlw14eKn .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-8nAWs1k8mlw14eKn #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-8nAWs1k8mlw14eKn .sequenceNumber{fill:#fff}#mermaid-svg-8nAWs1k8mlw14eKn #sequencenumber{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn #crosshead path{fill:#333;stroke:#333}#mermaid-svg-8nAWs1k8mlw14eKn .messageText{fill:#333;stroke:#333}#mermaid-svg-8nAWs1k8mlw14eKn .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-8nAWs1k8mlw14eKn .labelText,#mermaid-svg-8nAWs1k8mlw14eKn .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-8nAWs1k8mlw14eKn .loopText,#mermaid-svg-8nAWs1k8mlw14eKn .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-8nAWs1k8mlw14eKn .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-8nAWs1k8mlw14eKn .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-8nAWs1k8mlw14eKn .noteText,#mermaid-svg-8nAWs1k8mlw14eKn .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-8nAWs1k8mlw14eKn .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-8nAWs1k8mlw14eKn .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-8nAWs1k8mlw14eKn .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-8nAWs1k8mlw14eKn .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .section{stroke:none;opacity:0.2}#mermaid-svg-8nAWs1k8mlw14eKn .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-8nAWs1k8mlw14eKn .section2{fill:#fff400}#mermaid-svg-8nAWs1k8mlw14eKn .section1,#mermaid-svg-8nAWs1k8mlw14eKn .section3{fill:#fff;opacity:0.2}#mermaid-svg-8nAWs1k8mlw14eKn .sectionTitle0{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .sectionTitle1{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .sectionTitle2{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .sectionTitle3{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-8nAWs1k8mlw14eKn .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .grid path{stroke-width:0}#mermaid-svg-8nAWs1k8mlw14eKn .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-8nAWs1k8mlw14eKn .task{stroke-width:2}#mermaid-svg-8nAWs1k8mlw14eKn .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .taskText:not([font-size]){font-size:11px}#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-8nAWs1k8mlw14eKn .task.clickable{cursor:pointer}#mermaid-svg-8nAWs1k8mlw14eKn .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-8nAWs1k8mlw14eKn .taskText0,#mermaid-svg-8nAWs1k8mlw14eKn .taskText1,#mermaid-svg-8nAWs1k8mlw14eKn .taskText2,#mermaid-svg-8nAWs1k8mlw14eKn .taskText3{fill:#fff}#mermaid-svg-8nAWs1k8mlw14eKn .task0,#mermaid-svg-8nAWs1k8mlw14eKn .task1,#mermaid-svg-8nAWs1k8mlw14eKn .task2,#mermaid-svg-8nAWs1k8mlw14eKn .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutside0,#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutside2{fill:#000}#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutside1,#mermaid-svg-8nAWs1k8mlw14eKn .taskTextOutside3{fill:#000}#mermaid-svg-8nAWs1k8mlw14eKn .active0,#mermaid-svg-8nAWs1k8mlw14eKn .active1,#mermaid-svg-8nAWs1k8mlw14eKn .active2,#mermaid-svg-8nAWs1k8mlw14eKn .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-8nAWs1k8mlw14eKn .activeText0,#mermaid-svg-8nAWs1k8mlw14eKn .activeText1,#mermaid-svg-8nAWs1k8mlw14eKn .activeText2,#mermaid-svg-8nAWs1k8mlw14eKn .activeText3{fill:#000 !important}#mermaid-svg-8nAWs1k8mlw14eKn .done0,#mermaid-svg-8nAWs1k8mlw14eKn .done1,#mermaid-svg-8nAWs1k8mlw14eKn .done2,#mermaid-svg-8nAWs1k8mlw14eKn .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-8nAWs1k8mlw14eKn .doneText0,#mermaid-svg-8nAWs1k8mlw14eKn .doneText1,#mermaid-svg-8nAWs1k8mlw14eKn .doneText2,#mermaid-svg-8nAWs1k8mlw14eKn .doneText3{fill:#000 !important}#mermaid-svg-8nAWs1k8mlw14eKn .crit0,#mermaid-svg-8nAWs1k8mlw14eKn .crit1,#mermaid-svg-8nAWs1k8mlw14eKn .crit2,#mermaid-svg-8nAWs1k8mlw14eKn .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-8nAWs1k8mlw14eKn .activeCrit0,#mermaid-svg-8nAWs1k8mlw14eKn .activeCrit1,#mermaid-svg-8nAWs1k8mlw14eKn .activeCrit2,#mermaid-svg-8nAWs1k8mlw14eKn .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-8nAWs1k8mlw14eKn .doneCrit0,#mermaid-svg-8nAWs1k8mlw14eKn .doneCrit1,#mermaid-svg-8nAWs1k8mlw14eKn .doneCrit2,#mermaid-svg-8nAWs1k8mlw14eKn .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-8nAWs1k8mlw14eKn .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-8nAWs1k8mlw14eKn .milestoneText{font-style:italic}#mermaid-svg-8nAWs1k8mlw14eKn .doneCritText0,#mermaid-svg-8nAWs1k8mlw14eKn .doneCritText1,#mermaid-svg-8nAWs1k8mlw14eKn .doneCritText2,#mermaid-svg-8nAWs1k8mlw14eKn .doneCritText3{fill:#000 !important}#mermaid-svg-8nAWs1k8mlw14eKn .activeCritText0,#mermaid-svg-8nAWs1k8mlw14eKn .activeCritText1,#mermaid-svg-8nAWs1k8mlw14eKn .activeCritText2,#mermaid-svg-8nAWs1k8mlw14eKn .activeCritText3{fill:#000 !important}#mermaid-svg-8nAWs1k8mlw14eKn .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-8nAWs1k8mlw14eKn g.classGroup text .title{font-weight:bolder}#mermaid-svg-8nAWs1k8mlw14eKn g.clickable{cursor:pointer}#mermaid-svg-8nAWs1k8mlw14eKn g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-8nAWs1k8mlw14eKn g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-8nAWs1k8mlw14eKn .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-8nAWs1k8mlw14eKn .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-8nAWs1k8mlw14eKn .dashed-line{stroke-dasharray:3}#mermaid-svg-8nAWs1k8mlw14eKn #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn .commit-id,#mermaid-svg-8nAWs1k8mlw14eKn .commit-msg,#mermaid-svg-8nAWs1k8mlw14eKn .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-8nAWs1k8mlw14eKn g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-8nAWs1k8mlw14eKn g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-8nAWs1k8mlw14eKn g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-8nAWs1k8mlw14eKn .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-8nAWs1k8mlw14eKn .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-8nAWs1k8mlw14eKn .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-8nAWs1k8mlw14eKn .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-8nAWs1k8mlw14eKn .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-8nAWs1k8mlw14eKn .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-8nAWs1k8mlw14eKn .edgeLabel text{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-8nAWs1k8mlw14eKn .node circle.state-start{fill:black;stroke:black}#mermaid-svg-8nAWs1k8mlw14eKn .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-8nAWs1k8mlw14eKn #statediagram-barbEnd{fill:#9370db}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-state .divider{stroke:#9370db}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-8nAWs1k8mlw14eKn .note-edge{stroke-dasharray:5}#mermaid-svg-8nAWs1k8mlw14eKn .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-8nAWs1k8mlw14eKn .error-icon{fill:#522}#mermaid-svg-8nAWs1k8mlw14eKn .error-text{fill:#522;stroke:#522}#mermaid-svg-8nAWs1k8mlw14eKn .edge-thickness-normal{stroke-width:2px}#mermaid-svg-8nAWs1k8mlw14eKn .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-8nAWs1k8mlw14eKn .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-8nAWs1k8mlw14eKn .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-8nAWs1k8mlw14eKn .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-8nAWs1k8mlw14eKn .marker{fill:#333}#mermaid-svg-8nAWs1k8mlw14eKn .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-8nAWs1k8mlw14eKn {color: rgba(0, 0, 0, 0.75);font: ;} CommonFactoryFinder StyleFactory FilterFactory2 ContrastEnhancement SelectedChannelType RasterSymbolizer ChannelSelection SLD Style 1.getStyleFactory 2.getFilterFactory2 3.contrastEnhancement(CommonFactoryFinder) 4.createSelectedChannelType 5.getDefaultRasterSymbolizer 6.channelSelection(SelectedChannelType) 7.setChannelSelection(ChannelSelection) 7.wrapSymbolizers(RasterSymbolizer) CommonFactoryFinder StyleFactory FilterFactory2 ContrastEnhancement SelectedChannelType RasterSymbolizer ChannelSelection SLD Style

4. 示例

前面的示例中,我们查看了如何读取和显示Shape文件。对于ImageLab.java,我们将通过显示一个三波段的全球卫星图像,并将其与shapefile中的国家边界进行叠加,将光栅数据添加到混合中。

4.1 pom引入

<dependencies><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-swing</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><dependency><groupId>org.geotools</groupId><artifactId>gt-image</artifactId><version>${geotools.version}</version></dependency>
</dependencies>
<repositories><repository><id>osgeo</id><name>OSGeo Release Repository</name><url>https://repo.osgeo.org/repository/release/</url><snapshots><enabled>false</enabled></snapshots><releases><enabled>true</enabled></releases></repository><repository><id>osgeo-snapshot</id><name>OSGeo Snapshot Repository</name><url>https://repo.osgeo.org/repository/snapshot/</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>false</enabled></releases></repository>
</repositories>

4.2 创建ImageLab类

public class ImageLab {private StyleFactory sf = CommonFactoryFinder.getStyleFactory();private FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();private JMapFrame frame;private GridCoverage2DReader reader;public static void main(String[] args) throws Exception {ImageLab me = new ImageLab();me.getLayersAndDisplay();}
}

4.3 选择Image和shape文件

 private void getLayersAndDisplay() throws Exception {List<Parameter<?>> list = new ArrayList<>();list.add(new Parameter<>("image",File.class,"Image","GeoTiff or World+Image to display as basemap",new KVP(Parameter.EXT, "tif", Parameter.EXT, "jpg")));list.add(new Parameter<>("shape",File.class,"Shapefile","Shapefile contents to display",new KVP(Parameter.EXT, "shp")));JParameterListWizard wizard =new JParameterListWizard("Image Lab", "Fill in the following layers", list);int finish = wizard.showModalDialog();if (finish != JWizard.FINISH) {System.exit(0);}File imageFile = (File) wizard.getConnectionParameters().get("image");File shapeFile = (File) wizard.getConnectionParameters().get("shape");displayLayers(imageFile, shapeFile);}

4.4 显示地图

private void displayLayers(File rasterFile, File shpFile) throws Exception {AbstractGridFormat format = GridFormatFinder.findFormat(rasterFile);Hints hints = new Hints();if (format instanceof GeoTiffFormat) {hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);}reader = format.getReader(rasterFile, hints);// 创建一个灰度样式Style rasterStyle = createGreyscaleStyle(1);// 连接shape图层FileDataStore dataStore = FileDataStoreFinder.getDataStore(shpFile);SimpleFeatureSource shapefileSource = dataStore.getFeatureSource();//创建一个黄色边界且没有填充的简单样式Style shpStyle = SLD.createPolygonStyle(Color.YELLOW, null, 0.0f);// 创建一个两个图层的地图final MapContent map = new MapContent();map.setTitle("ImageLab");Layer rasterLayer = new GridReaderLayer(reader, rasterStyle);map.addLayer(rasterLayer);Layer shpLayer = new FeatureLayer(shapefileSource, shpStyle);map.addLayer(shpLayer);//设置地图界面的样式frame = new JMapFrame(map);frame.setSize(800, 600);frame.enableStatusBar(true);frame.enableToolBar(true);JMenuBar menuBar = new JMenuBar();frame.setJMenuBar(menuBar);JMenu menu = new JMenu("Raster");menuBar.add(menu);menu.add(new SafeAction("Grayscale display") {public void action(ActionEvent e) throws Throwable {Style style = createGreyscaleStyle();if (style != null) {((StyleLayer) map.layers().get(0)).setStyle(style);frame.repaint();}}});menu.add(new SafeAction("RGB display") {public void action(ActionEvent e) throws Throwable {Style style = createRGBStyle();if (style != null) {((StyleLayer) map.layers().get(0)).setStyle(style);frame.repaint();}}});frame.setVisible(true);
}

4.4.1 创建选择灰度的对话框

private Style createGreyscaleStyle() {GridCoverage2D cov = null;try {cov = reader.read(null);} catch (IOException giveUp) {throw new RuntimeException(giveUp);}int numBands = cov.getNumSampleDimensions();Integer[] bandNumbers = new Integer[numBands];for (int i = 0; i < numBands; i++) {bandNumbers[i] = i + 1;}Object selection =JOptionPane.showInputDialog(frame,"Band to use for greyscale display","Select an image band",JOptionPane.QUESTION_MESSAGE,null,bandNumbers,1);if (selection != null) {int band = ((Number) selection).intValue();return createGreyscaleStyle(band);}return null;
}

4.4.2 创建灰度样式

private Style createGreyscaleStyle(int band) {ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);SelectedChannelType sct = sf.createSelectedChannelType(String.valueOf(band), ce);RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();ChannelSelection sel = sf.channelSelection(sct);sym.setChannelSelection(sel);return SLD.wrapSymbolizers(sym);
}

4.5 创建RGB样式

private Style createRGBStyle() {GridCoverage2D cov = null;try {cov = reader.read(null);} catch (IOException giveUp) {throw new RuntimeException(giveUp);}//我们需要至少三个波段的样式int numBands = cov.getNumSampleDimensions();if (numBands < 3) {return null;}//获取各个波段的名称String[] sampleDimensionNames = new String[numBands];for (int i = 0; i < numBands; i++) {GridSampleDimension dim = cov.getSampleDimension(i);sampleDimensionNames[i] = dim.getDescription().toString();}final int RED = 0, GREEN = 1, BLUE = 2;int[] channelNum = {-1, -1, -1};for (int i = 0; i < numBands; i++) {String name = sampleDimensionNames[i].toLowerCase();if (name != null) {if (name.matches("red.*")) {channelNum[RED] = i + 1;} else if (name.matches("green.*")) {channelNum[GREEN] = i + 1;} else if (name.matches("blue.*")) {channelNum[BLUE] = i + 1;}}}if (channelNum[RED] < 0 || channelNum[GREEN] < 0 || channelNum[BLUE] < 0) {channelNum[RED] = 1;channelNum[GREEN] = 2;channelNum[BLUE] = 3;}//我们使用selected通道创建RasterSymbolizer样式SelectedChannelType[] sct = new SelectedChannelType[cov.getNumSampleDimensions()];ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);for (int i = 0; i < 3; i++) {sct[i] = sf.createSelectedChannelType(String.valueOf(channelNum[i]), ce);}RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();ChannelSelection sel = sf.channelSelection(sct[RED], sct[GREEN], sct[BLUE]);sym.setChannelSelection(sel);return SLD.wrapSymbolizers(sym);
}

GeoTools入门(七)-- 操作栅格数据相关推荐

  1. GeoTools入门(五)-- CRS操作

    1. CRS概述 CRS全称为CoordinateReferenceSystems,中文叫坐标参考系统.它是GeoTools中的一个类,也是我们这次讨论的重点. 在前面我们谈到了JTS库,了解到了数据 ...

  2. 网络编程懒人入门(七):深入浅出,全面理解HTTP协议

    转自即时通讯网:http://www.52im.net/ 本文引用了自简书作者"涤生_Woo"的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全 ...

  3. MySQL入门 (七) : 储存引擎与资料型态

    1 表格与储存引擎 表格(table)是资料库中用来储存纪录的基本单位,在建立一个新的资料库以后,你必须为这个资料库建立一些储存资料的表格: 每一个资料库都会使用一个资料夹,这些资料库资料夹用来储存所 ...

  4. Lisp:AutoLisp入门、操作编程实例详细攻略

    Lisp:AutoLisp入门.操作编程实例详细攻略 目录 AutoLisp入门 1.图文教程 AutoLisp操作 AutoLisp入门 AutoLISP是由Autodesk公司开发的一种LISP程 ...

  5. ROS入门七 机器人建模——URDF

    ROS入门七 机器人建模--URDF urdf ufdf介绍 语法 创建机器人URDF模型 创建机器人描述功能包 创建URDF模型 在rviz中显示模型 改进URDF模型 添加物理和碰撞属性 使用xa ...

  6. Linux快速入门(操作基础)

    Linux快速入门(操作基础) 一.Linux操作系统 Shell简介: shell的原意是外壳,用来形容物体外部的架构.Linux系统的shell作为操作系统的外壳,为用户提供了使用操作系统的接口. ...

  7. java入门(七) | 循环结构

    java入门(七) | 循环结构 java入门系列,从零开始!!! 上一期是对方法(method)的基本运用的讲解和方法重载的实练 . 这一期是对循环结构的讲解,除了for循环你还知道几种?他们的使用 ...

  8. 思科CCNA入门实验操作实战视频课程-李云鹏-专题视频课程

    思科CCNA入门实验操作实战视频课程-241人已学习 课程介绍         学员将学习如何在局域网和广域网(LAN和WAN)的多协议网络中安装和配置思科交换机和路由器,提供一级故障排除服务并改善网 ...

  9. CSS入门七、CSS3新特性

    零.文章目录 CSS入门七.CSS3新特性 1.CSS3 的现状 新增的CSS3特性有兼容性问题,ie9+才支持 移动端支持优于 PC 端 不断改进中 应用相对广泛 2.CSS3 新增选择器 CSS3 ...

  10. OpenCV入门基础操作(二)----图像像素的处理

    OpenCV入门基础操作(二)----图像像素的处理 像素处理 读取一个图像像素 修改像素值 代码案例 像素处理 读取一个图像像素 在读取图像的时候一般要用到如下的命令: 返回值=图像(位置参数), ...

最新文章

  1. 为什么一定情况下scanf比cin快
  2. 工业用微型计算机(19)-指令系统(14)
  3. Keras笔记(一)关于Keras模型
  4. SAP CRM Fiori Simulation Pipeline 设计介绍
  5. 用python输入任意三条边长_如何用python求第三条边边长
  6. org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI
  7. 7-237 有理数加法 (15 分)
  8. Jsp之建立JDBC-ODBC桥接器连接数据库
  9. 党媒发声IT圈里的35岁现象
  10. 【得物技术】AB实验设计实现与分流算法
  11. Castaways钓鱼还能参与么,数据来告诉你答案
  12. 时间复杂度O(n)的理解
  13. spring-xxx-xxx-0.0.1-SNAPSHOT.jar中没有主清单属性
  14. 微信二次开发-windows版微信Hook开发SDK之C#版
  15. Linux WiFi使用
  16. 4.9-4.10 矩阵乘法的性质 矩阵的幂运算 矩阵的转置及其性质
  17. Tofu Icecream and Tai-chi man
  18. 蒋勋:知识分子应具备怎样的美学修养
  19. 如何搭建大规模机器学习平台?以阿里和蚂蚁的多个实际场景为例
  20. 【量化】量化交易入门系列2:经典的量化交易策略(上)

热门文章

  1. 台式电脑怎么进入修复计算机,电脑为什么提示自动修复?电脑开机提示自动修复的解决办法...
  2. 如何使用手机快速完成证件照制作?
  3. 利用python自动写Word文档(一)——python-docx初探
  4. Java 将Excel转为PDF(基于Spire.Cloud.SDK for Java)
  5. 工行聚合支付经验总结
  6. 16日彻底去除安卓应用的内置广告
  7. Python 的Tkinter包系列之一:窗口初步
  8. setAttribute() 与 getAttribute() 用法剖析及选项卡操作的实例展示,这一篇就够了
  9. 字体图标,变形,及渐变
  10. 区块链的信任机制--从制度信任到机器信任