/*! \page gdal_vrttut
GDAL Virtual Format Tutorial

Introduction

The VRT driver is a format driver for GDAL that allows a virtual GDAL dataset to be composed from other GDAL datasets with repositioning, and algorithms potentially applied as well as various kinds of metadata altered or added. VRT descriptions of datasets can be saved in an XML format normally given the extension .vrt.

An example of a simple .vrt file referring to a 512x512 dataset with one band loaded from utm.tif might look like this: \code 440720.0, 60.0, 0.0, 3751320.0, 0.0, -60.0 Gray utm.tif 1 \endcode VRT files can be produced by translating to VRT format. The resulting file can then be edited to modify mappings, add metadata or other purposes. VRT files can also be produced programmatically by various means.

This tutorial will cover the .vrt file format (suitable for users editing .vrt files), and how .vrt files may be created and manipulated programmatically for developers.

.vrt Format

Virtual files stored on disk are kept in an XML format with the following elements.

.vrt Descriptions for Raw Files

So far we have described how to derive new virtual datasets from existing files supports by GDAL. However, it is also common to need to utilize raw binary raster files for which the regular layout of the data is known but for which no format specific driver exists. This can be accomplished by writing a .vrt file describing the raw file. For example, the following .vrt describes a raw raster file containing floating point complex pixels in a file called l2p3hhsso.img. The image data starts from the first byte (ImageOffset=0). The byte offset between pixels is 8 (PixelOffset=8), the size of a CFloat32. The byte offset from the start of one line to the start of the next is 9376 bytes (LineOffset=9376) which is the width (1172) times the size of a pixel (8). \code l2p3hhsso.img 0 8 9376 MSB \endcode Some things to note are that the VRTRasterBand has a subClass specifier of "VRTRawRasterBand". Also, the VRTRasterBand contains a number of previously unseen elements but no "source" information. VRTRawRasterBands may never have sources (ie. SimpleSource), but should contain the following elements in addition to all the normal "metadata" elements previously described which are still supported. A few other notes: Another example, in this case a 400x300 RGB pixel interleaved image. \code Red rgb.raw 0 3 1200 Green rgb.raw 1 3 1200 Blue rgb.raw 2 3 1200 \endcode

Programatic Creation of VRT Datasets

The VRT driver supports several methods of creating VRT datasets. As of GDAL 1.2.0 the vrtdataset.h include file should be installed with the core GDAL include files, allowing direct access to the VRT classes. However, even without that most capabilities remain available through standard GDAL interfaces.

To create a VRT dataset that is a clone of an existing dataset use the CreateCopy() method. For example to clone utm.tif into a wrk.vrt file in C++ the following could be used: \code GDALDriver *poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" ); GDALDataset *poSrcDS, *poVRTDS; poSrcDS = (GDALDataset *) GDALOpenShared( "utm.tif", GA_ReadOnly ); poVRTDS = poDriver->CreateCopy( "wrk.vrt", poSrcDS, FALSE, NULL, NULL, NULL ); delete poVRTDS; delete poSrcDS; \endcode To create a virtual copy of a dataset with some attributes added or changed such as metadata or coordinate system that are often hard to change on other formats, you might do the following. In this case, the virtual dataset is created "in memory" only by virtual of creating it with an empty filename, and then used as a modified source to pass to a CreateCopy() written out in TIFF format. \code poVRTDS = poDriver->CreateCopy( "", poSrcDS, FALSE, NULL, NULL, NULL ); poVRTDS->SetMetadataItem( "SourceAgency", "United States Geological Survey"); poVRTDS->SetMetadataItem( "SourceDate", "July 21, 2003" ); poVRTDS->GetRasterBand( 1 )->SetNoDataValue( -999.0 ); GDALDriver *poTIFFDriver = (GDALDriver *) GDALGetDriverByName( "GTiff" ); GDALDataset *poTiffDS; poTiffDS = poTIFFDriver->CreateCopy( "wrk.tif", poVRTDS, FALSE, NULL, NULL, NULL ); delete poTiffDS; \endcode In this example a virtual dataset is created with the Create() method, and adding bands and sources programmatically, but still via the "generic" API. A special attribute of VRT datasets is that sources can be added to the bands by passing the XML describing the source into SetMetadata() on the special domain target "new_vrt_sources". The domain target "vrt_sources" may also be used, in which case any existing sources will be discarded before adding the new ones. In this example we construct a simple averaging filter source instead of using the simple source. \code // construct XML for simple 3x3 average filter kernel source. const char *pszFilterSourceXML = "" " utm.tif11" " " " 3" " 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111" " " ""; // Create the virtual dataset. poVRTDS = poDriver->Create( "", 512, 512, 1, GDT_Byte, NULL ); poVRTDS->GetRasterBand(1)->SetMetadataItem("source_0",pszFilterSourceXML", "new_vrt_sources"); \endcode A more general form of this that will produce a 3x3 average filtered clone of any input datasource might look like the following. In this case we deliberately set the filtered datasource as in the "vrt_sources" domain to override the SimpleSource created by the CreateCopy() method. The fact that we used CreateCopy() ensures that all the other metadata, georeferencing and so forth is preserved from the source dataset ... the only thing we are changing is the data source for each band. \code int nBand; GDALDriver *poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" ); GDALDataset *poSrcDS, *poVRTDS; poSrcDS = (GDALDataset *) GDALOpenShared( pszSourceFilename, GA_ReadOnly ); poVRTDS = poDriver->CreateCopy( "", poSrcDS, FALSE, NULL, NULL, NULL ); for( nBand = 1; nBand <= poVRTDS->GetRasterCount(); nBand++ ) { char szFilterSourceXML[10000]; GDALRasterBand *poBand = poVRTDS->GetRasterBand( nBand ); sprintf( szFilterSourceXML, "" " %s1%d" " " " 3" " 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111" " " "", pszSourceFilename, nBand ); poBand->SetMetadataItem( "source_0", szFilterSourceXML, "vrt_sources" ); } \endcode */