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入门(七)-- 操作栅格数据相关推荐
- GeoTools入门(五)-- CRS操作
1. CRS概述 CRS全称为CoordinateReferenceSystems,中文叫坐标参考系统.它是GeoTools中的一个类,也是我们这次讨论的重点. 在前面我们谈到了JTS库,了解到了数据 ...
- 网络编程懒人入门(七):深入浅出,全面理解HTTP协议
转自即时通讯网:http://www.52im.net/ 本文引用了自简书作者"涤生_Woo"的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全 ...
- MySQL入门 (七) : 储存引擎与资料型态
1 表格与储存引擎 表格(table)是资料库中用来储存纪录的基本单位,在建立一个新的资料库以后,你必须为这个资料库建立一些储存资料的表格: 每一个资料库都会使用一个资料夹,这些资料库资料夹用来储存所 ...
- Lisp:AutoLisp入门、操作编程实例详细攻略
Lisp:AutoLisp入门.操作编程实例详细攻略 目录 AutoLisp入门 1.图文教程 AutoLisp操作 AutoLisp入门 AutoLISP是由Autodesk公司开发的一种LISP程 ...
- ROS入门七 机器人建模——URDF
ROS入门七 机器人建模--URDF urdf ufdf介绍 语法 创建机器人URDF模型 创建机器人描述功能包 创建URDF模型 在rviz中显示模型 改进URDF模型 添加物理和碰撞属性 使用xa ...
- Linux快速入门(操作基础)
Linux快速入门(操作基础) 一.Linux操作系统 Shell简介: shell的原意是外壳,用来形容物体外部的架构.Linux系统的shell作为操作系统的外壳,为用户提供了使用操作系统的接口. ...
- java入门(七) | 循环结构
java入门(七) | 循环结构 java入门系列,从零开始!!! 上一期是对方法(method)的基本运用的讲解和方法重载的实练 . 这一期是对循环结构的讲解,除了for循环你还知道几种?他们的使用 ...
- 思科CCNA入门实验操作实战视频课程-李云鹏-专题视频课程
思科CCNA入门实验操作实战视频课程-241人已学习 课程介绍 学员将学习如何在局域网和广域网(LAN和WAN)的多协议网络中安装和配置思科交换机和路由器,提供一级故障排除服务并改善网 ...
- CSS入门七、CSS3新特性
零.文章目录 CSS入门七.CSS3新特性 1.CSS3 的现状 新增的CSS3特性有兼容性问题,ie9+才支持 移动端支持优于 PC 端 不断改进中 应用相对广泛 2.CSS3 新增选择器 CSS3 ...
- OpenCV入门基础操作(二)----图像像素的处理
OpenCV入门基础操作(二)----图像像素的处理 像素处理 读取一个图像像素 修改像素值 代码案例 像素处理 读取一个图像像素 在读取图像的时候一般要用到如下的命令: 返回值=图像(位置参数), ...
最新文章
- 为什么一定情况下scanf比cin快
- 工业用微型计算机(19)-指令系统(14)
- Keras笔记(一)关于Keras模型
- SAP CRM Fiori Simulation Pipeline 设计介绍
- 用python输入任意三条边长_如何用python求第三条边边长
- org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI
- 7-237 有理数加法 (15 分)
- Jsp之建立JDBC-ODBC桥接器连接数据库
- 党媒发声IT圈里的35岁现象
- 【得物技术】AB实验设计实现与分流算法
- Castaways钓鱼还能参与么,数据来告诉你答案
- 时间复杂度O(n)的理解
- spring-xxx-xxx-0.0.1-SNAPSHOT.jar中没有主清单属性
- 微信二次开发-windows版微信Hook开发SDK之C#版
- Linux WiFi使用
- 4.9-4.10 矩阵乘法的性质 矩阵的幂运算 矩阵的转置及其性质
- Tofu Icecream and Tai-chi man
- 蒋勋:知识分子应具备怎样的美学修养
- 如何搭建大规模机器学习平台?以阿里和蚂蚁的多个实际场景为例
- 【量化】量化交易入门系列2:经典的量化交易策略(上)
热门文章
- 台式电脑怎么进入修复计算机,电脑为什么提示自动修复?电脑开机提示自动修复的解决办法...
- 如何使用手机快速完成证件照制作?
- 利用python自动写Word文档(一)——python-docx初探
- Java 将Excel转为PDF(基于Spire.Cloud.SDK for Java)
- 工行聚合支付经验总结
- 16日彻底去除安卓应用的内置广告
- Python 的Tkinter包系列之一:窗口初步
- setAttribute() 与 getAttribute() 用法剖析及选项卡操作的实例展示,这一篇就够了
- 字体图标,变形,及渐变
- 区块链的信任机制--从制度信任到机器信任