Closed clintsinger closed 10 months ago
Yes, you're using the wrong API. The VRTDataset type is internal to C++ and not exposed to any bindings. You need to use GdalDriver by specifying the "VRT" name. https://gdal.org/drivers/raster/vrt.html#creation-of-vrt-datasets
using var vrt = Gdal.GetDriverByName("VRT");
// do your work
Thanks for the reply but I'm not sure how it answers my question. I do start out with what you said, but there is some functionality that is missing that I'm asking about.
I'm trying to create the following. The parts that are commented out are what appears to be missing from the library and I am wondering if they can be added. This is being ported over from a managed C++ implementation that I had done.
private bool CreateRgbaVrt()
{
_ = this.inputDataset ?? throw new NullReferenceException("inputDataset is null");
//if (CSLCount(this.inputDataset.GetMetadata("SUBDATASETS")) > 0
// && this.inputDataset.GetRasterCount() == 0)
//{
// Console.WriteLine("Files with multiple datasets are not supported");
// return false;
//}
int xSize = this.inputDataset.RasterXSize;
int ySize = this.inputDataset.RasterYSize;
int bandCount = this.inputDataset.RasterCount;
if (bandCount == 0)
{
Console.WriteLine("Input has no bands so cannot be translated");
return false;
}
var panBandList = new int[bandCount];
for (int i = 0; i < bandCount; i++)
{
panBandList[i] = i + 1;
}
var vrtDriver = Gdal.GetDriverByName("VRT");
if (vrtDriver == null)
{
throw new GeospatialException("Error creating VRT output driver");
}
using var poVDS = vrtDriver.Create("", xSize, ySize, 4, DataType.GDT_Byte, null);
string pszProjection = this.inputDataset.GetProjectionRef();
if (pszProjection != null && pszProjection.Length > 0)
{
poVDS.SetProjection(pszProjection);
}
var adfGeoTransform = new double[6];
if (MapTools.GetTransform(this.inputDataset, adfGeoTransform) == CPLErr.CE_None)
{
poVDS.SetGeoTransform(adfGeoTransform);
}
if (this.inputDataset.GetGCPCount() > 0)
{
int nGCPs = this.inputDataset.GetGCPCount();
GCP[] pasGCPs = this.inputDataset.GetGCPs();
poVDS.SetGCPs(pasGCPs, this.inputDataset.GetGCPProjection());
}
var papszMetadata = this.inputDataset.GetMetadata(null);
poVDS.SetMetadata(papszMetadata, null);
var pszInterleave = this.inputDataset.GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE");
if (pszInterleave != null)
{
poVDS.SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
}
var papszMD = this.inputDataset.GetMetadata("RPC");
if (papszMD != null)
{
poVDS.SetMetadata(papszMD, "RPC");
}
papszMD = this.inputDataset.GetMetadata("GEOLOCATION");
if (papszMD != null)
{
poVDS.SetMetadata(papszMD, "GEOLOCATION");
}
int nSrcBandCount = bandCount;
var poSrcBand = this.inputDataset.GetRasterBand(Math.Abs(panBandList[0]));
if (panBandList[0] < 0)
{
poSrcBand = poSrcBand.GetMaskBand();
}
var poColorTable = poSrcBand.GetColorTable();
if (poColorTable == null)
{
throw new GeospatialException(string.Format("Band {0} has no color table", Math.Abs(panBandList[0])));
}
// Move band count to 4 for RGBA
bandCount = RGBA_BAND_COUNT;
for (int i = 0; i < bandCount; i++)
{
// There doesn't appear to be an implementation of VRTSourcedRasterBand
//VRTSourcedRasterBand poVRTBand;
int nComponent = 0;
int nSrcBand;
if (nSrcBandCount == 2 && i == 3)
{
nSrcBand = panBandList[1];
}
else
{
nSrcBand = panBandList[0];
nComponent = i + 1;
}
poSrcBand = this.inputDataset.GetRasterBand(Math.Abs(nSrcBand));
poVDS.AddBand(poSrcBand.DataType, null);
//poVRTBand = (VRTSourcedRasterBand)poVDS.GetRasterBand(i + 1);
if (nSrcBand < 0)
{
//poVRTBand.AddMaskBandSource(poSrcBand);
continue;
}
double dfScale = 1.0, dfOffset = 0.0;
if (i < RGBA_BAND_COUNT)
{
//poVRTBand.AddComplexSource(poSrcBand,
// 0, 0,
// xSize, ySize,
// 0, 0, xSize, ySize,
// 0.0, 1.0,
// VRT_NODATA_UNSET,
// nComponent);
}
else
{
//poVRTBand.AddSimpleSource(poSrcBand,
// 0, 0,
// xSize, ySize,
// 0, 0, xSize, ySize);
}
if (i < RGBA_BAND_COUNT)
{
poVRTBand.SetColorInterpretation((ColorInterp)((int)GdalConst.GCI_RedBand) + i);
}
else
{
//CopyBandInfo(poSrcBand, poVRTBand, FALSE, TRUE, FALSE);
}
if ((this.inputDataset.GetRasterBand(1).GetMaskFlags() & GdalConst.GMF_PER_DATASET) == 0 &&
(poSrcBand.GetMaskFlags() & (GdalConst.GMF_ALL_VALID | GdalConst.GMF_NODATA)) == 0)
{
if (poVRTBand.CreateMaskBand(poSrcBand.GetMaskFlags()) == CPLErr.CE_None)
{
//VRTSourcedRasterBand hMaskVRTBand = (VRTSourcedRasterBand)poVRTBand.GetMaskBand();
//hMaskVRTBand.AddMaskBandSource(poSrcBand,
// 0, 0,
// xSize, ySize,
// 0, 0, xSize, ySize);
}
}
}
this.tempRgbaVrtFile = Path.ChangeExtension(Path.GetTempFileName(), "vrt");
Dataset vrtOutput = vrtDriver.CreateCopy(this.tempRgbaVrtFile, poVDS, 0, null, null, null);
if (vrtOutput == null)
{
return false;
}
vrtOutput.FlushCache();
// Open the RGBA VRT file for the new input
this.inputDataset = Gdal.Open(this.tempRgbaVrtFile, Access.GA_ReadOnly);
if (this.inputDataset == null)
{
Console.WriteLine("Unable to open temporary VRT file");
return false;
}
return true;
}
@clintsinger again, they are not missing. My packages have the identical interface as the official GDAL packages. This repo is only a builder and it doesn't extend GDAL functionality.
You can review the SWIG interface in the GDAL repo - here. If you need any additional functionality consider to request it in official GDAL repo.
I'm in the process of porting some of the
gdal_translate
functionality to convert a raster to RGBA format. To do so I need to use the functions invrtdataset.h
, such asVRTSourcedRasterBand
andCopyBandInfo
.It appears these are not available. Is the
vrtdataset
not included with this build or am I looking in the wrong area?In the C++ world, I'm using things like the following (among other functions from the same lib)
I'm looking for the equivalent in C#