904 lines
32 KiB
Python
Executable File
904 lines
32 KiB
Python
Executable File
#!/usr/bin/env pytest
|
|
# -*- coding: utf-8 -*-
|
|
###############################################################################
|
|
# $Id$
|
|
#
|
|
# Project: GDAL/OGR Test Suite
|
|
# Purpose: test librarified gdalbuildvrt
|
|
# Author: Even Rouault <even dot rouault @ spatialys dot com>
|
|
#
|
|
###############################################################################
|
|
# Copyright (c) 2016, Even Rouault <even dot rouault @ spatialys dot com>
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
###############################################################################
|
|
|
|
import pathlib
|
|
import struct
|
|
|
|
import gdaltest
|
|
import pytest
|
|
|
|
from osgeo import gdal
|
|
|
|
###############################################################################
|
|
# Simple test
|
|
|
|
|
|
def test_gdalbuildvrt_lib_1():
|
|
|
|
# Source = String
|
|
ds = gdal.BuildVRT("", "../gcore/data/byte.tif")
|
|
assert ds is not None, "got error/warning"
|
|
|
|
assert ds.GetRasterBand(1).Checksum() == 4672, "Bad checksum"
|
|
|
|
# Source = Array of string
|
|
ds = gdal.BuildVRT("", ["../gcore/data/byte.tif"])
|
|
assert ds is not None, "got error/warning"
|
|
|
|
assert ds.GetRasterBand(1).Checksum() == 4672, "Bad checksum"
|
|
|
|
# Source = Dataset
|
|
ds = gdal.BuildVRT("", gdal.Open("../gcore/data/byte.tif"))
|
|
assert ds is not None, "got error/warning"
|
|
|
|
assert ds.GetRasterBand(1).Checksum() == 4672, "Bad checksum"
|
|
|
|
# Source = Array of dataset
|
|
ds = gdal.BuildVRT("", [gdal.Open("../gcore/data/byte.tif")])
|
|
assert ds is not None, "got error/warning"
|
|
|
|
assert ds.GetRasterBand(1).Checksum() == 4672, "Bad checksum"
|
|
|
|
|
|
###############################################################################
|
|
# Test callback
|
|
|
|
|
|
def mycallback(pct, msg, user_data):
|
|
# pylint: disable=unused-argument
|
|
user_data[0] = pct
|
|
return 1
|
|
|
|
|
|
def test_gdalbuildvrt_lib_2():
|
|
|
|
tab = [0]
|
|
ds = gdal.BuildVRT(
|
|
"", "../gcore/data/byte.tif", callback=mycallback, callback_data=tab
|
|
)
|
|
assert ds is not None
|
|
|
|
assert ds.GetRasterBand(1).Checksum() == 4672, "Bad checksum"
|
|
|
|
assert tab[0] == 1.0, "Bad percentage"
|
|
|
|
ds = None
|
|
|
|
|
|
###############################################################################
|
|
# Test creating overviews
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not gdaltest.vrt_has_open_support(),
|
|
reason="VRT driver open missing",
|
|
)
|
|
def test_gdalbuildvrt_lib_ovr(tmp_vsimem):
|
|
|
|
tmpfilename = tmp_vsimem / "my.vrt"
|
|
ds = gdal.BuildVRT(tmpfilename, pathlib.Path("../gcore/data/byte.tif"))
|
|
ds.BuildOverviews("NEAR", [2])
|
|
ds = None
|
|
ds = gdal.Open(tmpfilename)
|
|
assert ds.GetRasterBand(1).GetOverviewCount() == 1
|
|
ds = None
|
|
|
|
|
|
def test_gdalbuildvrt_lib_te_partial_overlap():
|
|
|
|
ds = gdal.BuildVRT(
|
|
"",
|
|
"../gcore/data/byte.tif",
|
|
outputBounds=[440600, 3750060, 441860, 3751260],
|
|
xRes=30,
|
|
yRes=60,
|
|
)
|
|
assert ds is not None
|
|
|
|
assert ds.GetRasterBand(1).Checksum() == 8454
|
|
xml = ds.GetMetadata("xml:VRT")[0]
|
|
assert '<SrcRect xOff="0" yOff="1" xSize="19" ySize="19" />' in xml
|
|
assert '<DstRect xOff="4" yOff="0" xSize="38" ySize="19" />' in xml
|
|
|
|
|
|
###############################################################################
|
|
# Test BuildVRT() with sources that can't be opened by name
|
|
|
|
|
|
def test_gdalbuildvrt_lib_mem_sources():
|
|
def create_sources():
|
|
src1_ds = gdal.GetDriverByName("MEM").Create(
|
|
"i_have_a_name_but_nobody_can_open_me_through_it", 1, 1
|
|
)
|
|
src1_ds.SetGeoTransform([2, 1, 0, 49, 0, -1])
|
|
src1_ds.GetRasterBand(1).Fill(100)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1, 1)
|
|
src2_ds.SetGeoTransform([3, 1, 0, 49, 0, -1])
|
|
src2_ds.GetRasterBand(1).Fill(200)
|
|
|
|
return src1_ds, src2_ds
|
|
|
|
def scenario_1():
|
|
src1_ds, src2_ds = create_sources()
|
|
vrt_ds = gdal.BuildVRT("", [src1_ds, src2_ds])
|
|
vals = struct.unpack("B" * 2, vrt_ds.ReadRaster())
|
|
assert vals == (100, 200)
|
|
|
|
vrt_of_vrt_ds = gdal.BuildVRT("", [vrt_ds])
|
|
vals = struct.unpack("B" * 2, vrt_of_vrt_ds.ReadRaster())
|
|
assert vals == (100, 200)
|
|
|
|
# Alternate scenario where the Python objects of sources and intermediate
|
|
# VRT are no longer alive when the VRT of VRT is accessed
|
|
def scenario_2():
|
|
def get_vrt_of_vrt():
|
|
src1_ds, src2_ds = create_sources()
|
|
return gdal.BuildVRT("", [gdal.BuildVRT("", [src1_ds, src2_ds])])
|
|
|
|
vrt_of_vrt_ds = get_vrt_of_vrt()
|
|
vals = struct.unpack("B" * 2, vrt_of_vrt_ds.ReadRaster())
|
|
assert vals == (100, 200)
|
|
|
|
scenario_1()
|
|
scenario_2()
|
|
|
|
|
|
###############################################################################
|
|
# Test BuildVRT() with sources that can't be opened by name, in separate mode
|
|
|
|
|
|
def test_gdalbuildvrt_lib_mem_sources_separate():
|
|
def create_sources():
|
|
src1_ds = gdal.GetDriverByName("MEM").Create(
|
|
"i_have_a_name_but_nobody_can_open_me_through_it", 1, 1
|
|
)
|
|
src1_ds.SetGeoTransform([2, 1, 0, 49, 0, -1])
|
|
src1_ds.GetRasterBand(1).Fill(100)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1, 1)
|
|
src2_ds.SetGeoTransform([2, 1, 0, 49, 0, -1])
|
|
src2_ds.GetRasterBand(1).Fill(200)
|
|
|
|
return src1_ds, src2_ds
|
|
|
|
def scenario_1():
|
|
src1_ds, src2_ds = create_sources()
|
|
vrt_ds = gdal.BuildVRT("", [src1_ds, src2_ds], options="-separate")
|
|
vals = struct.unpack("B" * 2, vrt_ds.ReadRaster())
|
|
assert vals == (100, 200)
|
|
|
|
vrt_of_vrt_ds = gdal.BuildVRT("", [vrt_ds])
|
|
vals = struct.unpack("B" * 2, vrt_of_vrt_ds.ReadRaster())
|
|
assert vals == (100, 200)
|
|
|
|
# Alternate scenario where the Python objects of sources and intermediate
|
|
# VRT are no longer alive when the VRT of VRT is accessed
|
|
def scenario_2():
|
|
def get_vrt_of_vrt():
|
|
src1_ds, src2_ds = create_sources()
|
|
return gdal.BuildVRT(
|
|
"", [gdal.BuildVRT("", [src1_ds, src2_ds], options="-separate")]
|
|
)
|
|
|
|
vrt_of_vrt_ds = get_vrt_of_vrt()
|
|
vals = struct.unpack("B" * 2, vrt_of_vrt_ds.ReadRaster())
|
|
assert vals == (100, 200)
|
|
|
|
scenario_1()
|
|
scenario_2()
|
|
|
|
|
|
###############################################################################
|
|
# Test BuildVRT() with virtual overviews
|
|
|
|
|
|
def test_gdalbuildvrt_lib_virtual_overviews():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.BuildOverviews("NEAR", [2, 4, 8])
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 2000, 2000)
|
|
src2_ds.SetGeoTransform([3, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.BuildOverviews("NEAR", [2, 4, 16])
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src1_ds, src2_ds])
|
|
assert vrt_ds.GetRasterBand(1).GetOverviewCount() == 2
|
|
|
|
|
|
def test_gdalbuildvrt_lib_virtual_overviews_not_same_res():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.BuildOverviews("NEAR", [2, 4])
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 500, 500)
|
|
src2_ds.SetGeoTransform([3, 0.002, 0, 49, 0, -0.002])
|
|
src2_ds.BuildOverviews("NEAR", [2, 4])
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src1_ds, src2_ds])
|
|
assert vrt_ds.GetRasterBand(1).GetOverviewCount() == 0
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_nodata(tmp_vsimem):
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).SetNoDataValue(1)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).SetNoDataValue(2)
|
|
|
|
gdal.BuildVRT(tmp_vsimem / "out.vrt", [src1_ds, src2_ds], separate=True)
|
|
|
|
f = gdal.VSIFOpenL(tmp_vsimem / "out.vrt", "rb")
|
|
data = gdal.VSIFReadL(1, 10000, f)
|
|
gdal.VSIFCloseL(f)
|
|
|
|
assert b"<NoDataValue>1</NoDataValue>" in data
|
|
assert b"<NODATA>1</NODATA>" in data
|
|
assert b"<NoDataValue>2</NoDataValue>" in data
|
|
assert b"<NODATA>2</NODATA>" in data
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_nodata_2(tmp_vsimem):
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).SetNoDataValue(1)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).SetNoDataValue(2)
|
|
|
|
gdal.BuildVRT(
|
|
tmp_vsimem / "out.vrt", [src1_ds, src2_ds], separate=True, srcNodata="-3 4"
|
|
)
|
|
|
|
f = gdal.VSIFOpenL(tmp_vsimem / "out.vrt", "rb")
|
|
data = gdal.VSIFReadL(1, 10000, f)
|
|
gdal.VSIFCloseL(f)
|
|
|
|
assert b"<NoDataValue>-3</NoDataValue>" in data
|
|
assert b"<NODATA>-3</NODATA>" in data
|
|
assert b"<NoDataValue>4</NoDataValue>" in data
|
|
assert b"<NODATA>4</NODATA>" in data
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_nodata_3(tmp_vsimem):
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).SetNoDataValue(1)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).SetNoDataValue(2)
|
|
|
|
gdal.BuildVRT(
|
|
tmp_vsimem / "out.vrt",
|
|
[src1_ds, src2_ds],
|
|
separate=True,
|
|
srcNodata="3 4",
|
|
VRTNodata="-5 6",
|
|
)
|
|
|
|
f = gdal.VSIFOpenL(tmp_vsimem / "out.vrt", "rb")
|
|
data = gdal.VSIFReadL(1, 10000, f)
|
|
gdal.VSIFCloseL(f)
|
|
|
|
assert b"<NoDataValue>-5</NoDataValue>" in data
|
|
assert b"<NODATA>3</NODATA>" in data
|
|
assert b"<NoDataValue>6</NoDataValue>" in data
|
|
assert b"<NODATA>4</NODATA>" in data
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_nodata_4(tmp_vsimem):
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).SetNoDataValue(1)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1000, 1000)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).SetNoDataValue(2)
|
|
|
|
gdal.BuildVRT(
|
|
tmp_vsimem / "out.vrt",
|
|
[src1_ds, src2_ds],
|
|
separate=True,
|
|
srcNodata="None",
|
|
VRTNodata="None",
|
|
)
|
|
|
|
f = gdal.VSIFOpenL(tmp_vsimem / "out.vrt", "rb")
|
|
data = gdal.VSIFReadL(1, 10000, f)
|
|
gdal.VSIFCloseL(f)
|
|
|
|
assert b"<NoDataValue>" not in data
|
|
assert b"<NODATA>" not in data
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_multiband():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 2)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).Fill(1)
|
|
src1_ds.GetRasterBand(2).Fill(2)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 3)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).Fill(3)
|
|
src2_ds.GetRasterBand(2).Fill(4)
|
|
src2_ds.GetRasterBand(3).Fill(5)
|
|
|
|
ds = gdal.BuildVRT(
|
|
"",
|
|
[src1_ds, src2_ds],
|
|
separate=True,
|
|
)
|
|
assert ds.RasterCount == 5
|
|
for i in range(ds.RasterCount):
|
|
assert ds.GetRasterBand(i + 1).Checksum() == i + 1
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_multiband_regular_raster(tmp_vsimem):
|
|
|
|
src1_filename = str(tmp_vsimem / "src1.tif")
|
|
src1_ds = gdal.GetDriverByName("GTiff").Create(src1_filename, 1, 1, 2)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).Fill(1)
|
|
src1_ds.GetRasterBand(2).Fill(2)
|
|
src1_ds = None
|
|
|
|
src2_filename = str(tmp_vsimem / "src2.tif")
|
|
src2_ds = gdal.GetDriverByName("GTiff").Create(src2_filename, 1, 1, 3)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).Fill(3)
|
|
src2_ds.GetRasterBand(2).Fill(4)
|
|
src2_ds.GetRasterBand(3).Fill(5)
|
|
src2_ds = None
|
|
|
|
ds = gdal.BuildVRT(
|
|
"",
|
|
[src1_filename, src2_filename],
|
|
separate=True,
|
|
)
|
|
assert ds.RasterCount == 5
|
|
for i in range(ds.RasterCount):
|
|
assert ds.GetRasterBand(i + 1).Checksum() == i + 1
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_multiband_band_selection():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 2)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).Fill(1)
|
|
src1_ds.GetRasterBand(2).Fill(2)
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 3)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).Fill(3)
|
|
src2_ds.GetRasterBand(2).Fill(4)
|
|
src2_ds.GetRasterBand(3).Fill(5)
|
|
|
|
ds = gdal.BuildVRT(
|
|
"",
|
|
[src1_ds, src2_ds],
|
|
separate=True,
|
|
bandList=[2, 1],
|
|
)
|
|
assert ds.RasterCount == 4
|
|
assert ds.GetRasterBand(1).Checksum() == 2
|
|
assert ds.GetRasterBand(2).Checksum() == 1
|
|
assert ds.GetRasterBand(3).Checksum() == 4
|
|
assert ds.GetRasterBand(4).Checksum() == 3
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_separate_multiband_band_selection_error():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("foo", 1, 1, 2)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).Fill(1)
|
|
src1_ds.GetRasterBand(2).Fill(2)
|
|
|
|
with gdal.quiet_errors():
|
|
ds = gdal.BuildVRT(
|
|
"",
|
|
[src1_ds],
|
|
separate=True,
|
|
bandList=[1, 2, 3],
|
|
)
|
|
assert ds is None
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_usemaskband_on_mask_band():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("src1", 3, 1)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).Fill(255)
|
|
src1_ds.CreateMaskBand(0)
|
|
src1_ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 1, 1, b"\xff")
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("src2", 3, 1)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).Fill(127)
|
|
src2_ds.CreateMaskBand(0)
|
|
src2_ds.GetRasterBand(1).GetMaskBand().WriteRaster(1, 0, 1, 1, b"\xff")
|
|
|
|
ds = gdal.BuildVRT("", [src1_ds, src2_ds])
|
|
assert struct.unpack("B" * 3, ds.ReadRaster()) == (255, 127, 0)
|
|
assert struct.unpack("B" * 3, ds.GetRasterBand(1).GetMaskBand().ReadRaster()) == (
|
|
255,
|
|
255,
|
|
0,
|
|
)
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_usemaskband_on_alpha_band():
|
|
|
|
src1_ds = gdal.GetDriverByName("MEM").Create("src1", 3, 1, 2)
|
|
src1_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src1_ds.GetRasterBand(1).Fill(255)
|
|
src1_ds.GetRasterBand(2).SetColorInterpretation(gdal.GCI_AlphaBand)
|
|
src1_ds.GetRasterBand(2).WriteRaster(0, 0, 1, 1, b"\xff")
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("src2", 3, 1, 2)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src2_ds.GetRasterBand(1).Fill(127)
|
|
src2_ds.GetRasterBand(2).SetColorInterpretation(gdal.GCI_AlphaBand)
|
|
src2_ds.GetRasterBand(2).WriteRaster(1, 0, 1, 1, b"\xff")
|
|
|
|
ds = gdal.BuildVRT("", [src1_ds, src2_ds])
|
|
assert struct.unpack("B" * 3, ds.GetRasterBand(1).ReadRaster()) == (255, 127, 0)
|
|
assert struct.unpack("B" * 3, ds.GetRasterBand(2).ReadRaster()) == (255, 255, 0)
|
|
|
|
|
|
###############################################################################
|
|
# Test parsing all resampling methods
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"resampleAlg,resampleAlgStr",
|
|
[
|
|
(gdal.GRIORA_NearestNeighbour, "near"),
|
|
(gdal.GRIORA_Cubic, "cubic"),
|
|
(gdal.GRIORA_CubicSpline, "cubicspline"),
|
|
(gdal.GRIORA_Lanczos, "lanczos"),
|
|
(gdal.GRIORA_Average, "average"),
|
|
(gdal.GRIORA_RMS, "rms"),
|
|
(gdal.GRIORA_Mode, "mode"),
|
|
(gdal.GRIORA_Gauss, "gauss"),
|
|
],
|
|
)
|
|
def test_gdalbuildvrt_lib_resampling_methods(resampleAlg, resampleAlgStr):
|
|
|
|
option_list = gdal.BuildVRTOptions(
|
|
resampleAlg=resampleAlg, options="__RETURN_OPTION_LIST__"
|
|
)
|
|
assert option_list == ["-r", resampleAlgStr]
|
|
assert (
|
|
gdal.BuildVRT("", "../gcore/data/byte.tif", resampleAlg=resampleAlg) is not None
|
|
)
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_bandList():
|
|
|
|
src_ds = gdal.GetDriverByName("MEM").Create("src1", 3, 1, 2)
|
|
src_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src_ds.GetRasterBand(1).Fill(255)
|
|
src_ds.GetRasterBand(2).Fill(0)
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[2, 1] * 100)
|
|
assert vrt_ds.GetRasterBand(1).Checksum() == 0
|
|
assert vrt_ds.GetRasterBand(2).Checksum() != 0
|
|
assert vrt_ds.GetRasterBand(3).Checksum() == 0
|
|
|
|
with gdal.quiet_errors():
|
|
assert gdal.BuildVRT("", [src_ds], bandList=[3]) is None
|
|
|
|
src2_ds = gdal.GetDriverByName("MEM").Create("src2", 3, 1, 3)
|
|
src2_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
|
|
# If no explicit band list, we require all sources to have the same
|
|
# number of bands
|
|
with gdaltest.disable_exceptions(), gdaltest.error_handler():
|
|
assert gdal.BuildVRT("", [src_ds, src2_ds]) is not None
|
|
assert gdal.GetLastErrorType() != 0
|
|
|
|
with gdaltest.disable_exceptions(), gdaltest.error_handler():
|
|
gdal.ErrorReset()
|
|
assert gdal.BuildVRT("", [src2_ds, src_ds]) is not None
|
|
assert gdal.GetLastErrorType() != 0
|
|
|
|
# If explicit band list, we tolerate different band count, provided that
|
|
# all requested bands are available.
|
|
gdal.ErrorReset()
|
|
assert gdal.BuildVRT("", [src_ds, src2_ds], bandList=[1, 2]) is not None
|
|
assert gdal.GetLastErrorType() == 0
|
|
|
|
gdal.ErrorReset()
|
|
assert gdal.BuildVRT("", [src2_ds, src_ds], bandList=[1, 2]) is not None
|
|
assert gdal.GetLastErrorType() == 0
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_gdalbuildvrt_lib_bandList_subset_of_bands_from_multiple_band_source():
|
|
|
|
src_ds = gdal.GetDriverByName("MEM").Create("src", 1, 1, 3)
|
|
src_ds.SetGeoTransform([2, 0.001, 0, 49, 0, -0.001])
|
|
src_ds.GetRasterBand(1).Fill(10)
|
|
src_ds.GetRasterBand(2).Fill(20)
|
|
src_ds.GetRasterBand(3).Fill(30)
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[1])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 10
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[2])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 20
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[3])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 30
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[1, 2])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 10
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 20
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[1, 3])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 10
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 30
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[1, 2, 3])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 10
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 20
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(3).ReadRaster())[0] == 30
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[1, 3, 2])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 10
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 30
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(3).ReadRaster())[0] == 20
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[2, 1])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 20
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 10
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[2, 3])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 20
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 30
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[3, 1])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 30
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 10
|
|
|
|
vrt_ds = gdal.BuildVRT("", [src_ds], bandList=[3, 2])
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(1).ReadRaster())[0] == 30
|
|
assert struct.unpack("B", vrt_ds.GetRasterBand(2).ReadRaster())[0] == 20
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_warnings_and_custom_error_handler():
|
|
class GdalErrorHandler:
|
|
def __init__(self):
|
|
self.got_failure = False
|
|
self.got_warning = False
|
|
|
|
def handler(self, err_level, err_no, err_msg):
|
|
if err_level == gdal.CE_Failure:
|
|
self.got_failure = True
|
|
elif err_level == gdal.CE_Warning:
|
|
self.got_warning = True
|
|
|
|
# Heterogeneous band numbers should result in a warning from BuildVRT()
|
|
ds_one_band = gdal.Open("../gcore/data/byte.tif")
|
|
ds_two_band = gdal.Translate("", ds_one_band, bandList=[1, 1], format="VRT")
|
|
|
|
err_handler = GdalErrorHandler()
|
|
with gdaltest.error_handler(err_handler.handler):
|
|
with gdal.ExceptionMgr():
|
|
vrt_ds = gdal.BuildVRT("", [ds_one_band, ds_two_band])
|
|
assert vrt_ds
|
|
assert not err_handler.got_failure
|
|
assert err_handler.got_warning
|
|
|
|
err_handler = GdalErrorHandler()
|
|
with gdaltest.error_handler(err_handler.handler):
|
|
with gdal.ExceptionMgr():
|
|
vrt_ds = gdal.BuildVRT("", [ds_two_band, ds_one_band])
|
|
assert vrt_ds
|
|
assert not err_handler.got_failure
|
|
assert err_handler.got_warning
|
|
|
|
|
|
###############################################################################
|
|
def test_gdalbuildvrt_lib_strict_mode():
|
|
|
|
with gdal.ExceptionMgr():
|
|
with gdal.quiet_errors():
|
|
assert (
|
|
gdal.BuildVRT(
|
|
"", ["../gcore/data/byte.tif", "i_dont_exist.tif"], strict=False
|
|
)
|
|
is not None
|
|
)
|
|
|
|
with gdal.ExceptionMgr():
|
|
with pytest.raises(Exception):
|
|
gdal.BuildVRT(
|
|
"", ["../gcore/data/byte.tif", "i_dont_exist.tif"], strict=True
|
|
)
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not gdaltest.vrt_has_open_support(),
|
|
reason="VRT driver open missing",
|
|
)
|
|
def test_gdalbuildvrt_lib_te_touching_on_edge(tmp_vsimem):
|
|
|
|
tmp_filename = tmp_vsimem / "test_gdalbuildvrt_lib_te_touching_on_edge.vrt"
|
|
ds = gdal.BuildVRT(
|
|
tmp_filename,
|
|
"../gcore/data/byte.tif",
|
|
outputBounds=[440600, 3750000, 440720, 3750120],
|
|
xRes=60,
|
|
yRes=60,
|
|
)
|
|
assert ds is not None
|
|
ds = None
|
|
|
|
ds = gdal.Open(tmp_filename)
|
|
assert ds.GetRasterBand(1).Checksum() == 0
|
|
ds = None
|
|
|
|
|
|
###############################################################################
|
|
@pytest.mark.parametrize("num_bands_1,num_bands_2", [(3, 3), (3, 4), (4, 3), (4, 4)])
|
|
@pytest.mark.parametrize("drv_name", ["MEM", "GTiff"])
|
|
def test_gdalbuildvrt_lib_addAlpha(tmp_vsimem, num_bands_1, num_bands_2, drv_name):
|
|
fname1 = tmp_vsimem / "test_gdalbuildvrt_lib_addAlpha_1.tif"
|
|
fname2 = tmp_vsimem / "test_gdalbuildvrt_lib_addAlpha_2.tif"
|
|
|
|
src_ds1 = gdal.GetDriverByName(drv_name).Create(fname1, 1, 1, num_bands_1)
|
|
if num_bands_1 == 4:
|
|
src_ds1.GetRasterBand(src_ds1.RasterCount).SetColorInterpretation(
|
|
gdal.GCI_AlphaBand
|
|
)
|
|
for i in range(src_ds1.RasterCount):
|
|
src_ds1.GetRasterBand(i + 1).Fill(i + 1)
|
|
src_ds1.SetGeoTransform([2, 1, 0, 49, 0, -1])
|
|
|
|
src_ds2 = gdal.GetDriverByName(drv_name).Create(fname2, 1, 1, num_bands_2)
|
|
if num_bands_2 == 4:
|
|
src_ds2.GetRasterBand(src_ds2.RasterCount).SetColorInterpretation(
|
|
gdal.GCI_AlphaBand
|
|
)
|
|
for i in range(src_ds2.RasterCount):
|
|
src_ds2.GetRasterBand(i + 1).Fill(i + 1)
|
|
src_ds2.SetGeoTransform([3, 1, 0, 49, 0, -1])
|
|
|
|
if drv_name == "MEM":
|
|
ds = gdal.BuildVRT("", [src_ds1, src_ds2], addAlpha=True)
|
|
else:
|
|
src_ds1 = None
|
|
src_ds2 = None
|
|
ds = gdal.BuildVRT("", [fname1, fname2], addAlpha=True)
|
|
assert ds.RasterCount == 4
|
|
assert ds.GetRasterBand(4).GetColorInterpretation() == gdal.GCI_AlphaBand
|
|
assert ds.GetRasterBand(1).ReadRaster() == b"\x01\x01"
|
|
assert ds.GetRasterBand(2).ReadRaster() == b"\x02\x02"
|
|
assert ds.GetRasterBand(3).ReadRaster() == b"\x03\x03"
|
|
assert ds.GetRasterBand(4).ReadRaster() == (
|
|
b"\xff" if num_bands_1 == 3 else b"\x04"
|
|
) + (b"\xff" if num_bands_2 == 3 else b"\x04")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_gdalbuildvrt_lib_stable_average():
|
|
"""Tests that averaging resolution is stable. Cf https://github.com/OSGeo/gdal/issues/7502"""
|
|
|
|
gt = (
|
|
-5570.248248450553,
|
|
3.0004031511048237,
|
|
0.0,
|
|
5570.248248450553,
|
|
0.0,
|
|
-3.0004031511048237,
|
|
)
|
|
ds = gdal.GetDriverByName("MEM").Create("", 1, 1, 1, gdal.GDT_Float32)
|
|
ds.SetGeoTransform(gt)
|
|
|
|
vrt_ds = gdal.BuildVRT("", [ds] * 1000, separate=False)
|
|
vrt_gt = vrt_ds.GetGeoTransform()
|
|
|
|
assert vrt_gt == gt
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
def test_gdalbuildvrt_lib_nodataMaxMaskThreshold_rgba(tmp_vsimem):
|
|
|
|
ds = gdal.GetDriverByName("MEM").Create("", 2, 1, 4)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
# Test remapping of second valid pixel at 0 to 1
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, b"\x01\x00")
|
|
ds.GetRasterBand(2).WriteRaster(0, 0, 2, 1, b"\x02\x02")
|
|
ds.GetRasterBand(3).WriteRaster(0, 0, 2, 1, b"\x03\x03")
|
|
ds.GetRasterBand(4).WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.GetRasterBand(4).SetColorInterpretation(gdal.GCI_AlphaBand)
|
|
|
|
vrt_ds = gdal.BuildVRT("", [ds], nodataMaxMaskThreshold=128, VRTNodata=0)
|
|
assert vrt_ds.RasterCount == 3
|
|
assert vrt_ds.GetRasterBand(1).GetNoDataValue() == 0
|
|
assert vrt_ds.GetRasterBand(1).ReadRaster() == b"\x00\x01"
|
|
assert vrt_ds.GetRasterBand(2).GetNoDataValue() == 0
|
|
assert vrt_ds.GetRasterBand(2).ReadRaster() == b"\x00\x02"
|
|
assert vrt_ds.GetRasterBand(3).GetNoDataValue() == 0
|
|
assert vrt_ds.GetRasterBand(3).ReadRaster() == b"\x00\x03"
|
|
|
|
assert struct.unpack(
|
|
"h" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Int16)
|
|
) == (0, 1)
|
|
|
|
vrt_ds = gdal.BuildVRT("", [ds], nodataMaxMaskThreshold=128.5, VRTNodata=0)
|
|
assert vrt_ds.GetRasterBand(1).ReadRaster() == b"\x00\x01"
|
|
|
|
# VRTNodata=255, test remapping of 255 to 254
|
|
ds = gdal.GetDriverByName("MEM").Create("", 2, 1, 2)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, b"\x01\xFF")
|
|
ds.GetRasterBand(2).WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.GetRasterBand(2).SetColorInterpretation(gdal.GCI_AlphaBand)
|
|
|
|
vrt_ds = gdal.BuildVRT("", [ds], nodataMaxMaskThreshold=128, VRTNodata=255)
|
|
assert vrt_ds.GetRasterBand(1).ReadRaster() == b"\xFF\xFE"
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not gdaltest.vrt_has_open_support(),
|
|
reason="VRT driver open missing",
|
|
)
|
|
def test_gdalbuildvrt_lib_nodataMaxMaskThreshold_rgb_mask(tmp_vsimem):
|
|
|
|
# UInt16, VRTNodata=0
|
|
src_filename = str(tmp_vsimem / "src.tif")
|
|
ds = gdal.GetDriverByName("GTiff").Create(src_filename, 2, 1, 3, gdal.GDT_UInt16)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, struct.pack("H" * 2, 1, 0))
|
|
ds.GetRasterBand(2).WriteRaster(0, 0, 2, 1, struct.pack("H" * 2, 2, 2))
|
|
ds.GetRasterBand(3).WriteRaster(0, 0, 2, 1, struct.pack("H" * 2, 3, 2))
|
|
ds.GetRasterBand(1).CreateMaskBand(gdal.GMF_PER_DATASET)
|
|
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.Close()
|
|
|
|
vrt_filename = str(tmp_vsimem / "test.vrt")
|
|
gdal.BuildVRT(vrt_filename, [src_filename], nodataMaxMaskThreshold=128, VRTNodata=0)
|
|
vrt_ds = gdal.Open(vrt_filename)
|
|
assert struct.unpack(
|
|
"H" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_UInt16)
|
|
) == (0, 1)
|
|
|
|
assert struct.unpack(
|
|
"B" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Byte)
|
|
) == (0, 1)
|
|
|
|
# UInt16, VRTNodata=65535
|
|
src_filename = str(tmp_vsimem / "src.tif")
|
|
ds = gdal.GetDriverByName("GTiff").Create(src_filename, 2, 1, 1, gdal.GDT_UInt16)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, struct.pack("H" * 2, 1, 65535))
|
|
ds.GetRasterBand(1).CreateMaskBand(gdal.GMF_PER_DATASET)
|
|
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.Close()
|
|
|
|
vrt_filename = str(tmp_vsimem / "test.vrt")
|
|
gdal.BuildVRT(
|
|
vrt_filename, [src_filename], nodataMaxMaskThreshold=128, VRTNodata=65535
|
|
)
|
|
vrt_ds = gdal.Open(vrt_filename)
|
|
assert struct.unpack(
|
|
"H" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_UInt16)
|
|
) == (65535, 65534)
|
|
|
|
# Int16, VRTNodata=-32768
|
|
src_filename = str(tmp_vsimem / "src.tif")
|
|
ds = gdal.GetDriverByName("GTiff").Create(src_filename, 2, 1, 1, gdal.GDT_Int16)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, struct.pack("h" * 2, 1, -32768))
|
|
ds.GetRasterBand(1).CreateMaskBand(gdal.GMF_PER_DATASET)
|
|
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.Close()
|
|
|
|
vrt_filename = str(tmp_vsimem / "test.vrt")
|
|
gdal.BuildVRT(
|
|
vrt_filename, [src_filename], nodataMaxMaskThreshold=128, VRTNodata=-32768
|
|
)
|
|
vrt_ds = gdal.Open(vrt_filename)
|
|
assert struct.unpack(
|
|
"h" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Int16)
|
|
) == (-32768, -32767)
|
|
|
|
# Int16, VRTNodata=32767
|
|
src_filename = str(tmp_vsimem / "src.tif")
|
|
ds = gdal.GetDriverByName("GTiff").Create(src_filename, 2, 1, 1, gdal.GDT_Int16)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, struct.pack("h" * 2, 1, 32767))
|
|
ds.GetRasterBand(1).CreateMaskBand(gdal.GMF_PER_DATASET)
|
|
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.Close()
|
|
|
|
vrt_filename = str(tmp_vsimem / "test.vrt")
|
|
gdal.BuildVRT(
|
|
vrt_filename, [src_filename], nodataMaxMaskThreshold=128, VRTNodata=32767
|
|
)
|
|
vrt_ds = gdal.Open(vrt_filename)
|
|
assert struct.unpack(
|
|
"h" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Int16)
|
|
) == (32767, 32766)
|
|
|
|
# Float32, VRTNodata=0
|
|
src_filename = str(tmp_vsimem / "src.tif")
|
|
ds = gdal.GetDriverByName("GTiff").Create(src_filename, 2, 1, 1, gdal.GDT_Float32)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 2, 1, struct.pack("f" * 2, 1, 0))
|
|
ds.GetRasterBand(1).CreateMaskBand(gdal.GMF_PER_DATASET)
|
|
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 2, 1, b"\x00\xFF")
|
|
ds.Close()
|
|
|
|
vrt_filename = str(tmp_vsimem / "test.vrt")
|
|
gdal.BuildVRT(vrt_filename, [src_filename], nodataMaxMaskThreshold=128, VRTNodata=0)
|
|
vrt_ds = gdal.Open(vrt_filename)
|
|
assert struct.unpack(
|
|
"f" * 2, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Float32)
|
|
) == pytest.approx((0.0, 0.001))
|
|
|
|
# Float32, VRTNodata=1
|
|
src_filename = str(tmp_vsimem / "src.tif")
|
|
ds = gdal.GetDriverByName("GTiff").Create(src_filename, 3, 1, 1, gdal.GDT_Float32)
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
ds.GetRasterBand(1).WriteRaster(0, 0, 3, 1, struct.pack("f" * 3, 0, 1, 2))
|
|
ds.GetRasterBand(1).CreateMaskBand(gdal.GMF_PER_DATASET)
|
|
ds.GetRasterBand(1).GetMaskBand().WriteRaster(0, 0, 3, 1, b"\x00\xFF\xFF")
|
|
ds.Close()
|
|
|
|
vrt_filename = str(tmp_vsimem / "test.vrt")
|
|
gdal.BuildVRT(vrt_filename, [src_filename], nodataMaxMaskThreshold=128, VRTNodata=1)
|
|
vrt_ds = gdal.Open(vrt_filename)
|
|
assert struct.unpack(
|
|
"f" * 3, vrt_ds.GetRasterBand(1).ReadRaster(buf_type=gdal.GDT_Float32)
|
|
) == pytest.approx((1.0, 1.001, 2.0))
|