Skip to content

Commit

Permalink
GDALBuildVRT(): in -separate mode, add support for sources such as ME…
Browse files Browse the repository at this point in the history
…M dataset or non-materialized VRT files

Similar to 13cfbf8 that applied only to non-separate mode
  • Loading branch information
rouault committed Mar 29, 2022
1 parent 67d0d23 commit 5dccc51
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 15 deletions.
48 changes: 33 additions & 15 deletions apps/gdalbuildvrt_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,19 +950,34 @@ void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)

GDALAddBand(hVRTDS, psDatasetProperties->firstBandType, nullptr);

GDALProxyPoolDatasetH hProxyDS =
GDALProxyPoolDatasetCreate(dsFileName,
psDatasetProperties->nRasterXSize,
psDatasetProperties->nRasterYSize,
GA_ReadOnly, TRUE, pszProjectionRef,
psDatasetProperties->adfGeoTransform);
reinterpret_cast<GDALProxyPoolDataset*>(hProxyDS)->
SetOpenOptions( papszOpenOptions );

GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
psDatasetProperties->firstBandType,
psDatasetProperties->nBlockXSize,
psDatasetProperties->nBlockYSize);

GDALDatasetH hSourceDS;
bool bDropRef = false;
if( nSrcDSCount == nInputFiles &&
GDALGetDatasetDriver(pahSrcDS[i]) != nullptr &&
( dsFileName[0] == '\0' || // could be a unnamed VRT file
EQUAL(GDALGetDescription(GDALGetDatasetDriver(pahSrcDS[i])), "MEM")) )
{
hSourceDS = pahSrcDS[i];
}
else
{
bDropRef = true;
GDALProxyPoolDatasetH hProxyDS =
GDALProxyPoolDatasetCreate(dsFileName,
psDatasetProperties->nRasterXSize,
psDatasetProperties->nRasterYSize,
GA_ReadOnly, TRUE, pszProjectionRef,
psDatasetProperties->adfGeoTransform);
hSourceDS = static_cast<GDALDatasetH>(hProxyDS);
reinterpret_cast<GDALProxyPoolDataset*>(hProxyDS)->
SetOpenOptions( papszOpenOptions );

GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
psDatasetProperties->firstBandType,
psDatasetProperties->nBlockXSize,
psDatasetProperties->nBlockYSize);
}

VRTSourcedRasterBandH hVRTBand =
static_cast<VRTSourcedRasterBandH>(GDALGetRasterBand(hVRTDS, iBand));
Expand Down Expand Up @@ -1015,7 +1030,7 @@ void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)
if( pszResampling )
poSimpleSource->SetResampling(pszResampling);
poVRTBand->ConfigureSource( poSimpleSource,
static_cast<GDALRasterBand*>(GDALGetRasterBand(static_cast<GDALDatasetH>(hProxyDS), 1)),
static_cast<GDALRasterBand*>(GDALGetRasterBand(hSourceDS, 1)),
FALSE,
dfSrcXOff, dfSrcYOff,
dfSrcXSize, dfSrcYSize,
Expand All @@ -1030,7 +1045,10 @@ void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)

poVRTBand->AddSource( poSimpleSource );

GDALDereferenceDataset(hProxyDS);
if( bDropRef )
{
GDALDereferenceDataset(hSourceDS);
}

iBand ++;
}
Expand Down
40 changes: 40 additions & 0 deletions autotest/utilities/test_gdalbuildvrt_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,46 @@ def get_vrt_of_vrt():
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

Expand Down

0 comments on commit 5dccc51

Please sign in to comment.