我在使用 geotools
StreamingRenderer
来正确显示来自 Geotiff 的图像时遇到了困难。我正在使用来自 NASA 的 visible Earth geotiff ,但我在其他 EPSGE:4326 geotiff 中看到了这个问题。 非 EPSG:4326 的 Geotiff 没有这个问题,并且渲染得很漂亮。 Geotools版本是31.1
这是来自
GeotiffReader
CRS toWKT()
方法的 CRS WKT:
GEOGCS["WGS 84",
DATUM["World Geodetic System 1984",
SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],
UNIT["degree", 0.017453292519943295],
AXIS["Geodetic latitude", NORTH],
AXIS["Geodetic longitude", EAST],
AUTHORITY["EPSG","4326"]]
我的理解是
StreamingRenderer
应该从给定的读取器读取并重新投影/重新采样到视口边界和图像尺寸,但它最多会生成一个侧面翻转的图像,或者最坏的情况下会生成一个没有数据的图像请求整个 EPSG:4326 边界。
@Test
public void testGeotiffReader() throws IOException, FactoryException {
Path path = TestSupport.classPathResourceAsFile("/testdata/grids/eo_base.tif").toPath();
GridCoverage2DReader reader = GridFormatFinder.findFormat(path.toFile()).getReader(path.toFile());
ParameterValue bands = GeoTiffFormat.BANDS.createValue();
bands.setValue(new int[]{0});
GridCoverage2D coverage = reader.read(new GeneralParameterValue[]{bands});
//at this point the coverage is rendered in the correct orientation
Path out = Paths.get("rendered-coverage.png");
try(FileOutputStream fos= new FileOutputStream(out.toFile())) {
ImageIO.write(coverage.getRenderedImage(),"PNG",fos);
}
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,0,0,90,CRS.decode("EPSG:4326"));
Rectangle imageDim = new Rectangle(0, 0, 1200, 800);
MapViewport viewport = new MapViewport(envelope,false);
MapContent content = new MapContent();
content.setViewport(viewport);
StyleFactory sf = CommonFactoryFinder.getStyleFactory();
FilterFactory ff = CommonFactoryFinder.getFilterFactory();
ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
SelectedChannelType sct = sf.createSelectedChannelType(String.valueOf(1), ce);
RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
ChannelSelection sel = sf.channelSelection(sct);
sym.setChannelSelection(sel);
Style style = SLD.wrapSymbolizers(sym);
GridReaderLayer layer = new GridReaderLayer(reader, style);
content.addLayer(layer);
StreamingRenderer renderer = new StreamingRenderer();
renderer.setMapContent(content);
final BufferedImage image =
new BufferedImage(imageDim.width, imageDim.height, BufferedImage.TYPE_INT_ARGB);
final Graphics2D graphics = image.createGraphics();
renderer.paint(graphics, imageDim, envelope);
final ImageWorker iw = new ImageWorker(image);
iw.prepareForRendering();
out = Paths.get("streaming-renderer.png");
/**
* At this point, the image will be flipped on it's side
*/
try(FileOutputStream fos = new FileOutputStream(out.toFile())) {
iw.writePNG(fos, null, 0, false, false);
}
}
没有 rendered-coverage.png
渲染的
StreamingRenderer
就可以了:
但是当使用
StreamingRenderer
渲染到视口时:
如果需要完整范围,则可以是完全空白的图像。 我尝试过forceXY,在引用的信封中交换坐标顺序,似乎没有任何效果。我缺少什么? 如何让 EPSG:4326 geotiffs 正确渲染?我确信我在这里遗漏了一些明显的东西。
我尝试过不同的 EPSG:4326 geotiffs、forceXY 系统属性、交换坐标
ReferencedEnvelope
我不能发誓,但我怀疑这是使用 GeoTiffReader 的一个众所周知的问题。我这样说是因为我们的图像教程包含以下代码:
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);
说实话,每当我要处理4326时,我都觉得需要去洗澡才能再次干净。