I am trying implement raster mosaicking to have a finer grain control over overlapping rasters.
From my limited research, I believe chaining raster functions seems the most promising approach but the documentation for this is confusing at best.
For example, MosaicDatasetRaster extends Raster but doesn't have the option to set the RasterFunction however there does seem to be an option on the AddRastersParameters class to provide a raster function template file. The documentation states "The path to the raster function template".
So my research leads me to ArcGIS desktop which has the ability to save such a template however every attempt I have made to load a file crashes with an Invalid argument: Failed to read 6107 bytes from <path>.
My first approach was to attempt the JSON, second attempt to use the XML schema.
So to summarise my question(s)
MosaicDatasetRaster rasterMosaic = MosaicDatasetRaster.Create(@"mosaic.sqlite", "mosaic_rasters", SpatialReferences.Wgs84);
rasterMosaic.LoadStatusChanged += async (s, e) =>
{
if (e.Status == Esri.ArcGISRuntime.LoadStatus.Loaded)
{
AddRastersParameters parameters = new()
{
InputDirectory = @"tiff",
RasterFunctionTemplateFile = @"mask_function.xml"
};
await rasterMosaic.AddRastersAsync(parameters);
}
};
await rasterMosaic.LoadAsync();
RasterLayer rasterLayer = new(rasterMosaic)
{
Opacity = 0.5
};
Map.OperationalLayers.Add(rasterLayer);
<RasterFunctionTemplate xsi:type='typens:RasterFunctionTemplate'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xs='http://www.w3.org/2001/XMLSchema'
xmlns:typens='http://www.esri.com/schemas/ArcGIS/3.3.0'>
<Name>Raster Function Template</Name>
<Description>xxcxdf</Description>
<Function xsi:type='typens:MaskFunction' id='ID1'>
<Name>Mask</Name>
<Description>Sets values that you do not want to display.</Description>
<PixelType>UNKNOWN</PixelType>
</Function>
<Arguments xsi:type='typens:MaskFunctionArguments' id='ID2'>
<Names xsi:type='typens:ArrayOfString' id='ID3'>
<String>Raster</String>
<String>NoDataInterpretation</String>
<String>NoDataValues</String>
<String>IncludedRanges</String>
<String>Invert</String>
</Names>
<Values xsi:type='typens:ArrayOfAnyType' id='ID4'>
<AnyType xsi:type='typens:Raster' id='ID5'>
<RasterBandCollectionNames xsi:type='typens:ArrayOfRasterBandCollectionName' id='ID6'>
<RasterBandCollectionName xsi:type='typens:RasterBandCollectionName' id='ID7'>
<NameString></NameString>
<DatasetName xsi:type='typens:RasterDatasetName' id='ID8'>
<WorkspaceName xsi:type='typens:WorkspaceName' id='ID9'>
<NameString>Raster Workspace = C:\Work\gtiff\;</NameString>
<PathName>C:\Work\gtiff\</PathName>
<BrowseName>Raster Data</BrowseName>
<WorkspaceFactoryProgID>esriDataSourcesRaster.RasterWorkspaceFactory</WorkspaceFactoryProgID>
<WorkspaceType>esriFileSystemWorkspace</WorkspaceType>
<ConnectionProperties xsi:type='typens:PropertySet' id='ID10'>
<PropertyArray xsi:type='typens:ArrayOfPropertySetProperty' id='ID11'>
<PropertySetProperty xsi:type='typens:PropertySetProperty' id='ID12'>
<Key>DATABASE</Key>
<Value xsi:type='xs:string'>C:\Work\gtiff\</Value>
</PropertySetProperty>
</PropertyArray>
</ConnectionProperties>
</WorkspaceName>
</DatasetName>
<BandIDs xsi:type='typens:ArrayOfInt' id='ID13'>
<Int>0</Int>
<Int>1</Int>
<Int>2</Int>
<Int>3</Int>
</BandIDs>
</RasterBandCollectionName>
</RasterBandCollectionNames>
</AnyType>
<AnyType xsi:type='typens:RasterFunctionVariable' id='ID14'>
<Name>NoDataInterpretation</Name>
<Description></Description>
<Value xsi:type='xs:int'>1</Value>
<IsDataset>false</IsDataset>
</AnyType>
<AnyType xsi:type='typens:RasterFunctionVariable' id='ID15'>
<Name>NoDataValues</Name>
<Description></Description>
<Value xsi:type='typens:ArrayOfString' id='ID16'>
<String>255</String>
<String>255</String>
<String>255</String>
<String>0</String>
</Value>
<IsDataset>false</IsDataset>
</AnyType>
<AnyType xsi:type='typens:RasterFunctionVariable' id='ID17'>
<Name>IncludedRanges</Name>
<Description></Description>
<Value xsi:type='typens:ArrayOfDouble' id='ID18'>
<Double>0</Double>
<Double>0</Double>
<Double>0</Double>
<Double>0</Double>
<Double>0</Double>
<Double>0</Double>
<Double>0</Double>
<Double>0</Double>
</Value>
<IsDataset>false</IsDataset>
</AnyType>
<AnyType xsi:type='typens:RasterFunctionVariable' id='ID19'>
<Name>Invert</Name>
<Description></Description>
<Value xsi:type='xs:boolean'>false</Value>
<IsDataset>false</IsDataset>
</AnyType>
</Values>
</Arguments>
<Help></Help>
<Type>0</Type>
<Thumbnail xsi:type='xs:string'></Thumbnail>
<Definition></Definition>
<Group></Group>
<Tag></Tag>
<ThumbnailEx></ThumbnailEx>
<Properties xsi:type='typens:PropertySet' id='ID20'>
<PropertyArray xsi:type='typens:ArrayOfPropertySetProperty' id='ID21'>
<PropertySetProperty xsi:type='typens:PropertySetProperty' id='ID22'>
<Key>MatchVariable</Key>
<Value xsi:type='typens:RasterFunctionVariable' id='ID23'>
<Name>MatchVariable</Name>
<Description></Description>
<Value xsi:type='xs:int'>1</Value>
<IsDataset>false</IsDataset>
</Value>
</PropertySetProperty>
<PropertySetProperty xsi:type='typens:PropertySetProperty' id='ID24'>
<Key>UnionDimension</Key>
<Value xsi:type='typens:RasterFunctionVariable' id='ID25'>
<Name>UnionDimension</Name>
<Description></Description>
<Value xsi:type='xs:int'>0</Value>
<IsDataset>false</IsDataset>
</Value>
</PropertySetProperty>
</PropertyArray>
</Properties>
</RasterFunctionTemplate>
Working example on a single raster using the Mask Function
RasterFunction rasterFunction = RasterFunction.FromJson(
@"
{
""raster_function"":{""type"":""Mask_function""},
""raster_function_arguments"":
{
""nodata_values"":
{
""double_array"":[255, 255, 255, 0],
""type"":""Raster_function_variable""
},
""nodata_interpretation"":
{
""nodata_interpretation"":""all"",
""type"":""Raster_function_variable""
},
""raster"":
{
""name"":""raster"",
""is_raster"":true,
""type"":""Raster_function_variable""
},
""type"":""Raster_function_arguments""
},
""type"":""Raster_function_template""
}"
);
IReadOnlyList<string> myRasterNames = rasterFunction.Arguments.GetRasterNames();
rasterFunction.Arguments.SetRaster(myRasterNames[0], new Raster(@"C:\Work\gtiff\raster.tiff"));
RasterLayer rasterLayer = new(new Raster(rasterFunction))
{
Opacity = 0.5
};
Map.OperationalLayers.Add(rasterLayer);