ProConcepts Raster - kataya/arcgis-pro-sdk GitHub Wiki

Raster related functionality in ArcGIS Pro can be found in two namespaces within two separate assemblies. The ArcGIS.Core.Data.Raster namespace within ArcGIS.Core.dll provides the raster classes and members to work with raster datasets, in memory rasters, pixel blocks and cursors. The ArcGIS.Desktop.Mapping namespace within ArcGIS.Desktop.Mapping.dll provides the classes and members to work with raster layers and colorizers.

Language:      C#
Subject:       Raster
Contributor:   ArcGIS Pro SDK Team <[email protected]>
Organization:  Esri, http://www.esri.com
Date:          11/24/2020
ArcGIS Pro:    2.7
Visual Studio: 2017, 2019

In this topic

Raster Datasets

The RasterDataset class represents a raster dataset stored in a storage media, file system or a geodatabase. A RasterDataset is a file raster dataset if it is opened from a file system and it is a database raster dataset if it is opened from a file geodatabase or an enterprise geodatabase. A file raster dataset and a geodatabase raster dataset behave the same except for some minor differences.

A RasterDataset has properties associated with it that can accessed using the RasterDefinition class. The RasterDatasetDefinition associated with a RasterDataset can be obtained using the GetDefinition method. A RasterDataset is composed of one or more persistent raster bands. You can get a RasterBand from a RasterDataset by using the GetBand and GetBandByName methods. A RasterBand has properties associated with it that can accessed using the RasterBandDefinition class. The RasterBandDefinition associated with a RasterBand can be obtained using the GetDefinition method.

// Get the RasterDatasetDefinition from the raster dataset.
RasterDatasetDefinition rasterDatasetDefinition = rasterDataset.GetDefinition();
// Get the number of bands from the raster band definition.
int bandCount = rasterDatasetDefinition.GetBandCount();
// Get a RasterBand from the raster dataset.
RasterBand rasterBand = rasterDataset.GetBand(0);
// Get the RasterBandDefinition from the raster band.
RasterBandDefinition rasterBandDefinition = rasterBand.GetDefinition();
// Get the name of the raster band from the raster band.
string bandName = rasterBandDefinition.GetName();

The RasterDataset class can be used to create a Raster using the CreateDefaultRaster, CreateRaster and CreateFullRaster methods.

  • The CreateFullRaster method creates a raster with all the properties from the raster dataset, such as number of bands and width and height of the raster dataset.
  • The CreateDefaultRaster method creates a raster that has a square cell size and contains only three raster bands even if the dataset has more than three bands. The three bands are the default bands used in the raster RGB colorizer.
  • The CreateRaster method creates a raster that has the same properties and the given list of bands from a raster dataset.

Opening Raster Datasets

A RasterDataset can be opened using the FileSystemDataStore class for a file raster dataset or Geodatabase class for a geodatabase raster dataset.

// Create a FileSystemConnectionPath using the folder path.
FileSystemConnectionPath connectionPath = 
  new FileSystemConnectionPath(new System.Uri(@"C:\Temp"), FileSystemDatastoreType.Raster);
// Create a new FileSystemDatastore using the FileSystemConnectionPath.
FileSystemDatastore dataStore = new FileSystemDatastore(connectionPath);
// Open the raster dataset.
RasterDataset fileRasterDataset = dataStore.OpenDataset<RasterDataset>("Sample.tif");
// Create a FileGeodatabaseConnectionPath using the path to the gdb. Note: This can be a path to a .sde file.
FileGeodatabaseConnectionPath geodatabaseConnectionPath = 
  new FileGeodatabaseConnectionPath(new Uri(@"C:\Temp\rasters.gdb"));
// Create a new Geodatabase object using the FileGeodatabaseConnectionPath.
Geodatabase geodatabase = new Geodatabase(geodatabaseConnectionPath);
// Open the raster dataset.
RasterDataset gdbRasterDataset = geodatabase.OpenDataset<RasterDataset>("sample");

In addition to being accessed through a workspace, the RasterDataset can also be retrieved from a Raster using the GetRasterDataset method.

Mosaic Datasets

The MosaicDataset class represents a mosaic dataset on disk or in a geodatabase. A flag indicating whether a MosaicDataset is referenced can accessed using the MosaicDatasetDefinition class. The MosaicDatasetDefinition associated with a MosaicDataset can be obtained using the GetDefinition method.

Opening Mosaic Datasets

A MosaicDataset can be opened using the FileSystemDataStore class for a file raster dataset or Geodatabase class for a geodatabase raster dataset.

// Create a FileGeodatabaseConnectionPath using the path to the gdb.
FileGeodatabaseConnectionPath connectionPath = new FileGeodatabaseConnectionPath(new System.Uri(dataStorePath));
// Create a new Geodatabase object using the FileGeodatabaseConnectionPath.
Geodatabase gdb = new Geodatabase(connectionPath);
// Open the Mosaic dataset.
MosaicDataset mosaicDatasetToOpen = gdb.OpenDataset<MosaicDataset>(name);
// Create a FileSystemConnectionPath using the path to the folder.
FileSystemConnectionPath connectionPath = 
    new FileSystemConnectionPath(new System.Uri(@"c:\test"), FileSystemDatastoreType.Raster);
// Create a new FileSystemDatastore using the FileSystemConnectionPath.
FileSystemDatastore dataStore = new FileSystemDatastore(connectionPath);
// Open the Mosaic dataset.
MosaicDataset mosaicDatasetToOpen = dataStore.OpenDataset<MosaicDataset>("testmosaicdataset.amd");

The MosaicDataset class has methods that allow you to access the tables associated with a mosaic dataset:

  • GetCatalog: This method returns a feature class representing the catalog (attribute) table of the mosaic dataset.
  • GetBoundary: This method returns a feature class representing the boundary table of the mosaic dataset.
  • GetSeamline: This method returns a feature class representing the seamline table of the mosaic dataset if it exists.
  • GetStereoTable: This method returns a feature class representing the stereo table of the mosaic dataset if it exists.

To access the image related properties of the mosaic dataset, cast the MosaicDataset class to the Raster class. This will allow you to access image related properties and pixels of the mosaiced image.

To access the raster dataset from the raster field of the mosac dataset catalog table, use the RasterValue class.

// Get the catalog table from the mosaic dataset
FeatureClass mdCatalog = mosaicDataset.GetCatalog();
// Use the row cursor to get rows from the catalog.
RowCursor catalogCursor = mdCatalog.Search();
while (catalogCursor.MoveNext())
{
    // Get the feature from the current row.
    Feature currFeature = catalogCursor.Current as Feature;
    // Get the value for the Raster field.
    var rasterFieldVal = currFeature["RASTER"];
    RasterValue rasterVal = rasterFieldVal as RasterValue;
    // Use the RasterValue class to get the raster dataset.
    RasterDataset rasterValrasterDataset = rasterVal.GetRasterDataset();
}

Raster

The Raster class, in contrast to the static RasterDataset and RasterBand classes, is transient in nature and can be modified without affecting the source data. This allows the raster to represent what you want—for example, you can set a transformation on a raster, specify a projection or extent, and set other properties without changing the underlying raster dataset. If you want to persist the change, the modified raster can be saved to another raster dataset using the SaveAs method. As such, a Raster is most easily understood as a vehicle to provide re sampling, transformation, and data type conversion from one or more raster bands to a desired output coordinate system.

A Raster can be used to get and set properties such as extent, width, height, spatial reference, pixel type, and NoData value. Re-sampling occurs when the raster is changed geometrically, such as setting an extent, a spatial reference, or a geodata transformation. In this case, the SetResampleType method can be used to specify the re-sampling method, and it will be applied during SaveAs or during raster display.

You can get the cell size of a raster using the GetMeanCellSize method. However, setting a cell size for a raster should be done by adjusting the width, height, and extent of the raster. If the height and/or width are changed, the cell size of the raster will be recalculated using the new height and width to divide the current raster extent. In this case, it will most likely result in a raster with non-square cell size.

The MapToPixel and PixelToMap methods are used to perform a transformation between pixel and map space. You can get the column and row in pixel space by passing x and y coordinates in map space and vice versa. The GetPixelValue method can be used to identify a pixel value on a raster by specifying the column and row of the pixel.

A raster can be obtained from a RasterLayer, MosaicLayer or ImageServiceLayer using the GetRaster method. The raster obtained in this way represents the raster that is rendered using the Colorizer associated with the layer. The raster dataset that the raster was created from can be obtained by using the GetRasterDataset method.

PixelBlock

The PixelBlock class is a container for pixel arrays. It has the properties of width, height, pixel type, and number of planes. Each plane is a pixel array corresponding to one raster band. The PixelBlock class can handle generic pixel arrays from any raster data source. To support different pixel types, PixelBlock transports pixels in an Array, which can contain many different data types.

The PixelBlock class is used to read, modify, and write pixel values or a portion of pixel values of the raster data. Create a pixel block from a raster using the CreatePixelBlock method. This initializes the size and other properties of the pixel block. Use the Read method to read the pixel values into the pixel block, then use the GetPixelData method to get and/or modify the pixel values of the pixel block. The Write and Erase methods can be used to write and erase the pixel block to the raster dataset respectively.

// Create a full raster from the raster dataset.
ArcGIS.Core.Data.Raster.Raster raster = rasterDataset.CreateFullRaster();

// Calculate size of pixel block to create. Use 128 or height/width of the raster, whichever is smaller.
int pixelBlockHeight = raster.GetHeight() > 128 ? 128 : raster.GetHeight();
int pixelBlockWidth = raster.GetWidth() > 128 ? 128 : raster.GetWidth();

// Create a new (blank) pixel block.
PixelBlock currentPixelBlock = raster.CreatePixelBlock(pixelBlockWidth, pixelBlockHeight);

// Read pixel values from the raster dataset into the pixel block starting from the given top left corner.
raster.Read(0, 0, currentPixelBlock);

// Do something with the pixel block...

// Write the pixel block to the raster dataset starting from the given top left corner.
raster.Write(0, 0, currentPixelBlock);
await QueuedTask.Run(() =>
{
  // Read pixel values from the raster dataset into the pixel block starting from the given top left corner.
  raster.Read(0, 0, currentPixelBlock);

  // For each plane (band) in the pixel block
  for (int plane = 0; plane < currentPixelBlock.GetPlaneCount(); plane++)
  {
    // Get a copy of the array of pixels from the pixel block corresponding to the current plane.
    Array sourcePixels = currentPixelBlock.GetPixelData(plane, true);
    // Get the height and width of the pixel block.
    int pBHeight = currentPixelBlock.GetHeight();
    int pBWidth = currentPixelBlock.GetWidth();

    // Iterate through the pixels in the array.
    for (int i = 0; i < pBHeight; i++)
    {
      for (int j = 0; j < pBWidth; j++)
      {
        // Get the NoData mask value to see if the pixel is a valid pixel.
        if (Convert.ToByte(currentPixelBlock.GetNoDataMaskValue(plane, j, i)) == 1)
        {
          // Get the pixel value from the array and process it (add 5 to the value).
          // Note: This is assuming the pixel type is Unisigned 8bit.
          int pixelValue = Convert.ToInt16(sourcePixels.GetValue(j, i)) + 5;
          // Make sure the pixel value does not go above the range of the pixel type.
          pixelValue = pixelValue > 254 ? 254 : pixelValue;
          // Set the new pixel value to the array.
          // Note: This is assuming the pixel type is Unisigned 8bit.
          sourcePixels.SetValue(Convert.ToByte(pixelValue), j, i);
        }
      }
    }
    // Set the modified array of pixels back to the pixel block.
    currentPixelBlock.SetPixelData(plane, sourcePixels);
  }
  // Write the pixel block to the raster dataset starting from the given top left corner.
  raster.Write(0, 0, currentPixelBlock);
});

Raster Cursor

For a small raster dataset, the size of the pixel block can be the size of the entire dataset, which can usually be held in memory at one time. When working with a large amount of raster data, the best practice is to divide the raster into small pixel blocks and perform reading and writing pixels block by block using the RasterCursor class.

The CreateCursor method on the Raster class provides a simple way to create a RasterCursor with a user-specified pixel block size.

await QueuedTask.Run(() =>
{
  // Create a full raster from the raster dataset.
  ArcGIS.Core.Data.Raster.Raster raster = rasterDataset.CreateFullRaster();

  // Calculate size of pixel blocks to process. Use 1000 or height/width of the raster, whichever is smaller.
  int pixelBlockHeight = raster.GetHeight() > 1000 ? 1000 : raster.GetHeight();
  int pixelBlockWidth = raster.GetWidth() > 1000 ? 1000 : raster.GetWidth();

  // Create the raster cursor using the height and width calculated.
  RasterCursor rasterCursor = raster.CreateCursor(pixelBlockWidth, pixelBlockHeight);

  // Use a do while loop to iterate through the pixel blocks of the raster using the raster cursor.
  do
  {
    // Get the current pixel block from the cursor.
    PixelBlock currentPixelBlock = rasterCursor.Current;
    // Do something with the pixel block...

    // Once you are done, move to the next pixel block.
  }
  while (rasterCursor.MoveNext());
});

NoData

Pixels, or cells, in a raster dataset that are missing information are called NoData. For a file-based raster dataset, NoData is stored as a value in the raster dataset. The pixels that have the same value as the NoData value are NoData pixels. For a database raster dataset, NoData pixels are stored as a bit mask—a two-dimensional array of 0s and 1s, where 0 represents that the corresponding pixel is a NoData pixel.

The GetNoDataValue and SetNoDataValue` methods can be used to get and set the NoData value on a raster. The NoData value is used in saving (SaveAs) to a new dataset.

The GetNoDataValue can also be used to get the NoData value on a RasterBand.

The NoData value is used in writing pixel blocks to the raster dataset. For mask-based NoData, the SetNoDataMask method on the PixelBlock class can be used to set NoData when writing pixel blocks.

Visualizing Raster Data

Raster data can be visualized in ArcGIS Pro by adding it to a 2D or 3D map as a layer. The type of layer added to the map depends on the type of raster data.

Raster Layer

An image or pixel data on disk or in a geodatabase is represented as a RasterLayer. Learn more about raster layers.

Mosaic Layer

A mosaic dataset is represented as a special type of group layer called a MosaicLayer. Learn more about mosaic layers.

Image Service Layer

Raster data from an Image Service is represented as an ImageServiceLayer. Learn more about image service layers.

Colorizers

The way in which raster data is visualized is controlled by a colorizer. All raster layers (raster, mosaic and image service layers) have a colorizer associated with them. Learn more about colorizers.

⚠️ **GitHub.com Fallback** ⚠️