mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-19 14:15:21 -06:00
902 lines
36 KiB
Text
902 lines
36 KiB
Text
#ifndef DOXYGEN_SKIP
|
|
/* $Id: vrt_tutorial.dox 29342 2015-06-14 18:00:24Z rouault $ */
|
|
#endif /* DOXYGEN_SKIP */
|
|
|
|
/*!
|
|
|
|
\page gdal_vrttut GDAL Virtual Format Tutorial
|
|
|
|
\section gdal_vrttut_intro 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.<p>
|
|
|
|
An example of a simple .vrt file referring to a 512x512 dataset with one band
|
|
loaded from utm.tif might look like this:
|
|
|
|
\code
|
|
<VRTDataset rasterXSize="512" rasterYSize="512">
|
|
<GeoTransform>440720.0, 60.0, 0.0, 3751320.0, 0.0, -60.0</GeoTransform>
|
|
<VRTRasterBand dataType="Byte" band="1">
|
|
<ColorInterp>Gray</ColorInterp>
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">utm.tif</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<SrcRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
<DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
</SimpleSource>
|
|
</VRTRasterBand>
|
|
</VRTDataset>
|
|
\endcode
|
|
|
|
Many aspects of the VRT file are a direct XML encoding of the
|
|
<a href="gdal_datamodel.html">GDAL Data Model</a> which should be reviewed
|
|
for understanding of the semantics of various elements.<p>
|
|
|
|
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.<p>
|
|
|
|
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.<p>
|
|
|
|
\section gdal_vrttut_format .vrt Format
|
|
|
|
A <a href="http://svn.osgeo.org/gdal/trunk/gdal/data/gdalvrt.xsd">XML schema of the GDAL VRT format</a>
|
|
is available.<p>
|
|
|
|
Virtual files stored on disk are kept in an XML format with the following
|
|
elements.<p>
|
|
|
|
<b>VRTDataset</b>: This is the root element for the whole GDAL dataset.
|
|
It must have the attributes rasterXSize and rasterYSize describing the width
|
|
and height of the dataset in pixels. It may have SRS, GeoTransform,
|
|
GCPList, Metadata, MaskBand and VRTRasterBand subelements.
|
|
|
|
\code
|
|
<VRTDataset rasterXSize="512" rasterYSize="512">
|
|
\endcode
|
|
|
|
The allowed subelements for VRTDataset are :
|
|
|
|
<ul>
|
|
|
|
<li> <b>SRS</b>: This element contains the spatial reference system (coordinate
|
|
system) in OGC WKT format. Note that this must be appropriately escaped for
|
|
XML, so items like quotes will have the ampersand escape sequences substituted.
|
|
As as well WKT, and valid input to the SetFromUserInput() method (such as well
|
|
known GEOGCS names, and PROJ.4 format) is also allowed in the SRS element.
|
|
|
|
\code
|
|
<SRS>PROJCS["NAD27 / UTM zone 11N",GEOGCS["NAD27",DATUM["North_American_Datum_1927",SPHEROID["Clarke 1866",6378206.4,294.9786982139006,AUTHORITY["EPSG","7008"]],AUTHORITY["EPSG","6267"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4267"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-117],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","26711"]]</SRS>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>GeoTransform</b>: This element contains a six value affine
|
|
geotransformation for the dataset, mapping between pixel/line coordinates
|
|
and georeferenced coordinates.<P>
|
|
|
|
\code
|
|
<GeoTransform>440720.0, 60, 0.0, 3751320.0, 0.0, -60.0</GeoTransform>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>GCPList</b>: This element contains a list of Ground Control Points for
|
|
the dataset, mapping between pixel/line coordinates and georeferenced
|
|
coordinates. The Projection attribute should contain the SRS of the
|
|
georeferenced coordinates in the same format as the SRS element.<P>
|
|
|
|
\code
|
|
<GCPList Projection="EPSG:4326">
|
|
<GCP Id="1" Info="a" Pixel="0.5" Line="0.5" X="0.0" Y="0.0" Z="0.0" />
|
|
<GCP Id="2" Info="b" Pixel="13.5" Line="23.5" X="1.0" Y="2.0" Z="0.0" />
|
|
</GCPList>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>Metadata</b>: This element contains a list of metadata name/value
|
|
pairs associated with the VRTDataset as a whole, or a VRTRasterBand. It has
|
|
<MDI> (metadata item) subelements which have a "key" attribute and the value
|
|
as the data of the element. The Metadata element can be repeated multiple times,
|
|
in which case it must be accompanied with a "domain" attribute to indicate the
|
|
name of the metadata domain.
|
|
|
|
\code
|
|
<Metadata>
|
|
<MDI key="md_key">Metadata value</MDI>
|
|
</Metadata>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>MaskBand</b>: (GDAL >= 1.8.0) This element represents a mask band that is
|
|
shared between all bands on the dataset (see GMF_PER_DATASET in RFC 15).
|
|
It must contain a single VRTRasterBand child element, that is the description of
|
|
the mask band itself.
|
|
|
|
\code
|
|
<MaskBand>
|
|
<VRTRasterBand dataType="Byte">
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">utm.tif</SourceFilename>
|
|
<SourceBand>mask,1</SourceBand>
|
|
<SrcRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
<DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
</SimpleSource>
|
|
</VRTRasterBand>
|
|
</MaskBand>
|
|
\endcode
|
|
|
|
</li>
|
|
|
|
<li> <b>VRTRasterBand</b>: This represents one band of a dataset. It will
|
|
have a dataType attribute with the type of the pixel data associated with
|
|
this band (use names Byte, UInt16, Int16, UInt32, Int32, Float32, Float64,
|
|
CInt16, CInt32, CFloat32 or CFloat64) and the band this element represents
|
|
(1 based). This element may have Metadata, ColorInterp, NoDataValue, HideNoDataValue,
|
|
ColorTable, Description and MaskBand subelements as well as the various kinds of
|
|
source elements such as SimpleSource, ComplexSource, etc. A raster band may have many "sources"
|
|
indicating where the actual raster data should be fetched from, and how it
|
|
should be mapped into the raster bands pixel space.<p>
|
|
|
|
The allowed subelements for VRTRasterBand are :
|
|
|
|
<ul>
|
|
|
|
<li> <b>ColorInterp</b>: The data of this element should be the name of
|
|
a color interpretation type. One of Gray, Palette, Red, Green, Blue, Alpha,
|
|
Hue, Saturation, Lightness, Cyan, Magenta, Yellow, Black, or Unknown.<p>
|
|
|
|
\code
|
|
<ColorInterp>Gray</ColorInterp>:
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>NoDataValue</b>: If this element exists a raster band has a
|
|
nodata value associated with, of the value given as data in the element.
|
|
|
|
\code
|
|
<NoDataValue>-100.0</NoDataValue>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>HideNoDataValue</b>: If this value is 1, the nodata value will not be
|
|
reported. Essentially, the caller will not be aware of a nodata pixel when it
|
|
reads one. Any datasets copied/translated from this will not have a nodata
|
|
value. This is useful when you want to specify a fixed background value for
|
|
the dataset. The background will be the value specified by the NoDataValue
|
|
element.
|
|
|
|
Default value is 0 when this element is absent.
|
|
|
|
\code
|
|
<HideNoDataValue>1</HideNoDataValue>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>ColorTable</b>: This element is parent to a set of Entry
|
|
elements defining the entries in a color table. Currently only RGBA
|
|
color tables are supported with c1 being red, c2 being green, c3 being
|
|
blue and c4 being alpha. The entries are ordered and will be assumed
|
|
to start from color table entry 0.
|
|
|
|
\code
|
|
<ColorTable>
|
|
<Entry c1="0" c2="0" c3="0" c4="255"/>
|
|
<Entry c1="145" c2="78" c3="224" c4="255"/>
|
|
</ColorTable>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>Description</b>: This element contains the optional description
|
|
of a raster band as it's text value.
|
|
|
|
\code
|
|
<Description>Crop Classification Layer</Description>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>UnitType</b>: This optional element contains the vertical units for
|
|
elevation band data. One of "m" for meters or "ft" for feet. Default
|
|
assumption is meters.<p>
|
|
|
|
\code
|
|
<UnitType>ft</UnitType>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>Offset</b>: This optional element contains the offset that should be
|
|
applied when computing "real" pixel values from scaled pixel values on
|
|
a raster band. The default is 0.0.<p>
|
|
|
|
\code
|
|
<Offset>0.0</Offset>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>Scale</b>: This optional element contains the scale that should be
|
|
applied when computing "real" pixel values from scaled pixel values on a
|
|
raster band. The default is 1.0.<p>
|
|
|
|
\code
|
|
<Scale>0.0</Scale>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>Overview</b>: This optional element describes one overview level for
|
|
the band. It should have a child SourceFilename and SourceBand element. The
|
|
SourceFilename may have a relativeToVRT boolean attribute. Multiple elements
|
|
may be used to describe multiple overviews. <p>
|
|
|
|
\code
|
|
<Overview>
|
|
<SourceFilename relativeToVRT="1">yellowstone_2.1.ntf.r2</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
</Overview>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>CategoryNames</b>: This optional element contains a list of Category
|
|
subelements with the names of the categories for classified raster band. <p>
|
|
|
|
\code
|
|
<CategoryNames>
|
|
<Category>Missing</Category>
|
|
<Category>Non-Crop</Category>
|
|
<Category>Wheat</Category>
|
|
<Category>Corn</Category>
|
|
<Category>Soybeans</Category>
|
|
</CategoryNames>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>SimpleSource</b>: The SimpleSource indicates that raster data
|
|
should be read from a separate dataset, indicating the dataset, and band to be
|
|
read from, and how the data should map into this bands raster space.
|
|
The SimpleSource may have the SourceFilename, SourceBand, SrcRect, and DstRect
|
|
subelements. The SrcRect element will indicate what rectangle on the indicated
|
|
source file should be read, and the DstRect element indicates how that
|
|
rectangle of source data should be mapped into the VRTRasterBands space.
|
|
|
|
The relativeToVRT attribute on the SourceFilename indicates whether the
|
|
filename should be interpreted as relative to the .vrt file (value is 1)
|
|
or not relative to the .vrt file (value is 0). The default is 0.
|
|
|
|
The shared attribute, added in GDAL 2.0.0, on the SourceFilename indicates whether the
|
|
dataset should be shared (value is 1) or not (value is 0). The default is 1.
|
|
If several VRT datasets refering to the same underlying sources are used in a multithreaded context,
|
|
shared should be set to 0. Alternatively, the VRT_SHARED_SOURCE configuration
|
|
option can be set to 0 to force non-shared mode.
|
|
|
|
Some characteristics of the source band can be specified in the optional
|
|
SourceProperties tag to enable the VRT driver to differ the opening of the source
|
|
dataset until it really needs to read data from it. This is particularly useful
|
|
when building VRTs with a big number of source datasets. The needed parameters are the
|
|
raster dimensions, the size of the blocks and the data type. If the SourceProperties
|
|
tag is not present, the source dataset will be opened at the same time as the VRT itself.
|
|
|
|
Starting with GDAL 1.8.0, the content of the SourceBand subelement can refer to
|
|
a mask band. For example mask,1 means the the mask band of the first band of the source.
|
|
|
|
\code
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">utm.tif</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<SourceProperties RasterXSize="512" RasterYSize="512" DataType="Byte" BlockXSize="128" BlockYSize="128"/>
|
|
<SrcRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
<DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
</SimpleSource>
|
|
\endcode
|
|
|
|
Starting with GDAL 2.0, a OpenOptions subelement can be added to specify
|
|
the open options to apply when opening the source dataset. It has <OOI> (open option item)
|
|
subelements which have a "key" attribute and the value as the data of the element.
|
|
|
|
\code
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">utm.tif</SourceFilename>
|
|
<OpenOptions>
|
|
<OOI key="OVERVIEW_LEVEL">0</OOI>
|
|
</OpenOptions>
|
|
<SourceBand>1</SourceBand>
|
|
<SourceProperties RasterXSize="256" RasterYSize="256" DataType="Byte" BlockXSize="128" BlockYSize="128"/>
|
|
<SrcRect xOff="0" yOff="0" xSize="256" ySize="256"/>
|
|
<DstRect xOff="0" yOff="0" xSize="256" ySize="256"/>
|
|
</SimpleSource>
|
|
\endcode
|
|
|
|
Starting with GDAL 2.0, a resampling attribute can be specified on a SimpleSource
|
|
or ComplexSource element to specified the resampling algorithm used when the
|
|
size of the destination rectangle is not the same as the size of the source
|
|
rectangle. The values allowed for that attribute are : nearest,bilinear,cubic,
|
|
cubicspline,lanczos,average,mode.
|
|
|
|
\code
|
|
<SimpleSource resampling="cubic">
|
|
<SourceFilename relativeToVRT="1">utm.tif</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<SourceProperties RasterXSize="256" RasterYSize="256" DataType="Byte" BlockXSize="128" BlockYSize="128"/>
|
|
<SrcRect xOff="0" yOff="0" xSize="256" ySize="256"/>
|
|
<DstRect xOff="0" yOff="0" xSize="128" ySize="128"/>
|
|
</SimpleSource>
|
|
\endcode
|
|
|
|
</li>
|
|
|
|
<li> <b>AveragedSource</b>: The AveragedSource is derived from the
|
|
SimpleSource and shares the same properties except that it uses an averaging
|
|
resampling instead of a nearest neighbour algorithm as in SimpleSource, when
|
|
the size of the destination rectangle is not the same as the size of the source
|
|
rectangle. Note: starting with GDAL 2.0, a more general mechanism to specify
|
|
resampling algorithms can be used. See above paragraph about the 'resampling' attribute.
|
|
|
|
<li> <b>ComplexSource</b>: The ComplexSource is derived from the
|
|
SimpleSource (so it shares the SourceFilename, SourceBand, SrcRect and
|
|
DestRect elements), but it provides support to rescale and offset
|
|
the range of the source values. Certain regions of the source
|
|
can be masked by specifying the NODATA value.
|
|
|
|
Starting with GDAL 1.11, alternatively to linear scaling, non-linear
|
|
scaling using a power function can be used by specifying the Exponent,
|
|
SrcMin, SrcMax, DstMin and DstMax elements. If SrcMin and SrcMax are
|
|
not specified, they are computed from the source minimum and maximum
|
|
value (which might require analyzing the whole source dataset). Exponent
|
|
must be positive. (Those 5 values can be set with the -exponent and -scale
|
|
options of gdal_translate.)
|
|
|
|
The ComplexSource supports adding a custom lookup table to transform
|
|
the source values to the destination. The LUT can be specified using
|
|
the following form:
|
|
|
|
\code
|
|
<LUT>[src value 1]:[dest value 1],[src value 2]:[dest value 2],...</LUT>
|
|
\endcode
|
|
|
|
The intermediary values are calculated using a linear interpolation
|
|
between the bounding destination values of the corresponding range.
|
|
|
|
The ComplexSource supports fetching a color component from a source raster
|
|
band that has a color table. The ColorTableComponent value is the index of the
|
|
color component to extract : 1 for the red band, 2 for the green band, 3 for
|
|
the blue band or 4 for the alpha band.
|
|
|
|
When transforming the source values the operations are executed
|
|
in the following order:
|
|
|
|
<ol>
|
|
<li>Nodata masking</li>
|
|
<li>Color table expansion</li>
|
|
<li>For linear scaling, applying the scale ratio, then scale offset</li>
|
|
<li>For non-linear scaling, apply (DstMax-DstMin) * pow( (SrcValue-SrcMin) / (SrcMax-SrcMin), Exponent) + DstMin</li>
|
|
<li>Table lookup</li>
|
|
</ol>
|
|
|
|
\code
|
|
<ComplexSource>
|
|
<SourceFilename relativeToVRT="1">utm.tif</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<ScaleOffset>0</ScaleOffset>
|
|
<ScaleRatio>1</ScaleRatio>
|
|
<ColorTableComponent>1</ColorTableComponent>
|
|
<LUT>0:0,2345.12:64,56789.5:128,2364753.02:255</LUT>
|
|
<NODATA>0</NODATA>
|
|
<SrcRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
<DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
</ComplexSource>
|
|
\endcode
|
|
|
|
Non-linear scaling:
|
|
|
|
\code
|
|
<ComplexSource>
|
|
<SourceFilename relativeToVRT="1">16bit.tif</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<Exponent>0.75</Exponent>
|
|
<SrcMin>0</SrcMin>
|
|
<SrcMax>65535</SrcMax>
|
|
<DstMin>0</DstMin>
|
|
<DstMax>255</DstMax>
|
|
<SrcRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
<DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
|
|
</ComplexSource>
|
|
\endcode
|
|
|
|
</li>
|
|
|
|
<li> <b>KernelFilteredSource</b>: This is a pixel source derived from the
|
|
Simple Source (so it shares the SourceFilename, SourceBand, SrcRect and
|
|
DestRect elements, but it also passes the data through a simple filtering
|
|
kernel specified with the Kernel element. The Kernel element should have
|
|
two child elements, Size and Coefs and optionally the boolean attribute
|
|
normalized (defaults to false=0). The size must always be an odd number,
|
|
and the Coefs must have Size * Size entries separated by spaces.
|
|
|
|
\code
|
|
<KernelFilteredSource>
|
|
<SourceFilename>/debian/home/warmerda/openev/utm.tif</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<Kernel normalized="1">
|
|
<Size>3</Size>
|
|
<Coefs>0.11111111 0.11111111 0.11111111 0.11111111 0.11111111 0.11111111 0.11111111 0.11111111 0.11111111</Coefs>
|
|
</Kernel>
|
|
</KernelFilteredSource>
|
|
\endcode
|
|
</li>
|
|
|
|
<li> <b>MaskBand</b>: (GDAL >= 1.8.0) This element represents a mask band that is
|
|
specific to the VRTRasterBand it contains. It must contain a single VRTRasterBand
|
|
child element, that is the description of the mask band itself.
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</ul>
|
|
|
|
\section gdal_vrttut_vrt .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 <i>l2p3hhsso.img</i>. 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
|
|
<VRTDataset rasterXSize="1172" rasterYSize="1864">
|
|
<VRTRasterBand dataType="CFloat32" band="1" subClass="VRTRawRasterBand">
|
|
<SourceFilename relativetoVRT="1">l2p3hhsso.img</SourceFilename>
|
|
<ImageOffset>0</ImageOffset>
|
|
<PixelOffset>8</PixelOffset>
|
|
<LineOffset>9376</LineOffset>
|
|
<ByteOrder>MSB</ByteOrder>
|
|
</VRTRasterBand>
|
|
</VRTDataset>
|
|
\endcode
|
|
|
|
Some things to note are that the VRTRasterBand has a subClass specifier
|
|
of "VRTRawRasterBand". Also, the VRTRawRasterBand 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.
|
|
|
|
<ul>
|
|
|
|
<li> <b>SourceFilename</b>: The name of the raw file containing the
|
|
data for this band. The relativeToVRT attribute can be used to indicate
|
|
if the SourceFilename is relative to the .vrt file (1) or not (0).
|
|
|
|
<li> <b>ImageOffset</b>: The offset in bytes to the beginning of the first
|
|
pixel of data of this image band. Defaults to zero.
|
|
|
|
<li> <b>PixelOffset</b>: The offset in bytes from the beginning of one
|
|
pixel and the next on the same line. In packed single band data this will
|
|
be the size of the <b>dataType</b> in bytes.
|
|
|
|
<li> <b>LineOffset</b>: The offset in bytes from the beginning of one
|
|
scanline of data and the next scanline of data. In packed single band
|
|
data this will be PixelOffset * rasterXSize.
|
|
|
|
<li> <b>ByteOrder</b>: Defines the byte order of the data on disk.
|
|
Either LSB (Least Significant Byte first) such as the natural byte order
|
|
on Intel x86 systems or MSB (Most Significant Byte first) such as the natural
|
|
byte order on Motorola or Sparc systems. Defaults to being the local machine
|
|
order.
|
|
|
|
</ul>
|
|
|
|
A few other notes:
|
|
|
|
<ul>
|
|
|
|
<li> The image data on disk is assumed to be of the same data type as
|
|
the band <b>dataType</b> of the VRTRawRasterBand.
|
|
|
|
<li> All the non-source attributes of the VRTRasterBand are supported,
|
|
including color tables, metadata, nodata values, and color interpretation.
|
|
|
|
<li> The VRTRawRasterBand supports in place update of the raster, whereas
|
|
the source based VRTRasterBand is always read-only.
|
|
|
|
<li> The OpenEV tool includes a File menu option to input parameters
|
|
describing a raw raster file in a GUI and create the corresponding .vrt
|
|
file.
|
|
|
|
<li> Multiple bands in the one .vrt file can come from the same raw file.
|
|
Just ensure that the ImageOffset, PixelOffset, and LineOffset definition
|
|
for each band is appropriate for the pixels of that particular band.
|
|
|
|
</ul>
|
|
|
|
Another example, in this case a 400x300 RGB pixel interleaved image.
|
|
|
|
\code
|
|
<VRTDataset rasterXSize="400" rasterYSize="300">
|
|
<VRTRasterBand dataType="Byte" band="1" subClass="VRTRawRasterBand">
|
|
<ColorInterp>Red</ColorInterp>
|
|
<SourceFilename relativetoVRT="1">rgb.raw</SourceFilename>
|
|
<ImageOffset>0</ImageOffset>
|
|
<PixelOffset>3</PixelOffset>
|
|
<LineOffset>1200</LineOffset>
|
|
</VRTRasterBand>
|
|
<VRTRasterBand dataType="Byte" band="2" subClass="VRTRawRasterBand">
|
|
<ColorInterp>Green</ColorInterp>
|
|
<SourceFilename relativetoVRT="1">rgb.raw</SourceFilename>
|
|
<ImageOffset>1</ImageOffset>
|
|
<PixelOffset>3</PixelOffset>
|
|
<LineOffset>1200</LineOffset>
|
|
</VRTRasterBand>
|
|
<VRTRasterBand dataType="Byte" band="3" subClass="VRTRawRasterBand">
|
|
<ColorInterp>Blue</ColorInterp>
|
|
<SourceFilename relativetoVRT="1">rgb.raw</SourceFilename>
|
|
<ImageOffset>2</ImageOffset>
|
|
<PixelOffset>3</PixelOffset>
|
|
<LineOffset>1200</LineOffset>
|
|
</VRTRasterBand>
|
|
</VRTDataset>
|
|
\endcode
|
|
|
|
\section gdal_vrttut_creation 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.<p>
|
|
|
|
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 );
|
|
|
|
GDALClose((GDALDatasetH) poVRTDS);
|
|
GDALClose((GDALDatasetH) poSrcDS);
|
|
\endcode
|
|
|
|
Note the use of GDALOpenShared() when opening the source dataset. It is advised
|
|
to use GDALOpenShared() in this situation so that you are able to release
|
|
the explicit reference to it before closing the VRT dataset itself. In other
|
|
words, in the previous example, you could also invert the 2 last lines, whereas
|
|
if you open the source dataset with GDALOpen(), you'd need to close the VRT dataset
|
|
before closing the source dataset.
|
|
|
|
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 );
|
|
|
|
GDALClose((GDALDatasetH) poTiffDS);
|
|
\endcode
|
|
|
|
In the above example the nodata value is set as -999. You can set the
|
|
HideNoDataValue element in the VRT dataset's band using SetMetadataItem() on
|
|
that band.
|
|
|
|
\code
|
|
poVRTDS->GetRasterBand( 1 )->SetMetadataItem( "HideNoDataValue" , "1" );
|
|
\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 VRTRasterBand
|
|
(but not to VRTRawRasterBand) 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 =
|
|
"<KernelFilteredSource>"
|
|
" <SourceFilename>utm.tif</SourceFilename><SourceBand>1</SourceBand>"
|
|
" <Kernel>"
|
|
" <Size>3</Size>"
|
|
" <Coefs>0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111</Coefs>"
|
|
" </Kernel>"
|
|
"</KernelFilteredSource>";
|
|
|
|
// 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,
|
|
"<KernelFilteredSource>"
|
|
" <SourceFilename>%s</SourceFilename><SourceBand>%d</SourceBand>"
|
|
" <Kernel>"
|
|
" <Size>3</Size>"
|
|
" <Coefs>0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111</Coefs>"
|
|
" </Kernel>"
|
|
"</KernelFilteredSource>",
|
|
pszSourceFilename, nBand );
|
|
|
|
poBand->SetMetadataItem( "source_0", szFilterSourceXML, "vrt_sources" );
|
|
}
|
|
\endcode
|
|
|
|
The VRTDataset class is one of the few dataset implementations that supports the AddBand()
|
|
method. The options passed to the AddBand() method can be used to control the type of the
|
|
band created (VRTRasterBand, VRTRawRasterBand, VRTDerivedRasterBand), and in the case of
|
|
the VRTRawRasterBand to set its various parameters. For standard VRTRasterBand, sources
|
|
should be specified with the above SetMetadata() / SetMetadataItem() examples.
|
|
|
|
\code
|
|
GDALDriver *poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
|
|
GDALDataset *poVRTDS;
|
|
|
|
poVRTDS = poDriver->Create( "out.vrt", 512, 512, 0, GDT_Byte, NULL );
|
|
char** papszOptions = NULL;
|
|
papszOptions = CSLAddNameValue(papszOptions, "subclass", "VRTRawRasterBand"); // if not specified, default to VRTRasterBand
|
|
papszOptions = CSLAddNameValue(papszOptions, "SourceFilename", "src.tif"); // mandatory
|
|
papszOptions = CSLAddNameValue(papszOptions, "ImageOffset", "156"); // optionnal. default = 0
|
|
papszOptions = CSLAddNameValue(papszOptions, "PixelOffset", "2"); // optionnal. default = size of band type
|
|
papszOptions = CSLAddNameValue(papszOptions, "LineOffset", "1024"); // optionnal. default = size of band type * width
|
|
papszOptions = CSLAddNameValue(papszOptions, "ByteOrder", "LSB"); // optionnal. default = machine order
|
|
papszOptions = CSLAddNameValue(papszOptions, "relativeToVRT", "true"); // optionnal. default = false
|
|
poVRTDS->AddBand(GDT_Byte, papszOptions);
|
|
CSLDestroy(papszOptions);
|
|
|
|
delete poVRTDS;
|
|
\endcode
|
|
|
|
<h2>Using Derived Bands</h2>
|
|
|
|
A specialized type of band is a 'derived' band which derives its pixel
|
|
information from its source bands. With this type of band you must also
|
|
specify a pixel function, which has the responsibility of generating the
|
|
output raster. Pixel functions are created by an application and then
|
|
registered with GDAL using a unique key.
|
|
|
|
Using derived bands you can create VRT datasets that manipulate bands on
|
|
the fly without having to create new band files on disk. For example, you
|
|
might want to generate a band using four source bands from a nine band input
|
|
dataset (x0, x3, x4, and x8):
|
|
|
|
\code
|
|
band_value = sqrt((x3*x3+x4*x4)/(x0*x8));
|
|
\endcode
|
|
|
|
You could write the pixel function to compute this value and then register
|
|
it with GDAL with the name "MyFirstFunction". Then, the following VRT XML
|
|
could be used to display this derived band:
|
|
|
|
\code
|
|
<VRTDataset rasterXSize="1000" rasterYSize="1000">
|
|
<VRTRasterBand dataType="Float32" band="1" subClass="VRTDerivedRasterBand">
|
|
<Description>Magnitude</Description>
|
|
<PixelFunctionType>MyFirstFunction</PixelFunctionType>
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">nine_band.dat</SourceFilename>
|
|
<SourceBand>1</SourceBand>
|
|
<SrcRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
<DstRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
</SimpleSource>
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">nine_band.dat</SourceFilename>
|
|
<SourceBand>4</SourceBand>
|
|
<SrcRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
<DstRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
</SimpleSource>
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">nine_band.dat</SourceFilename>
|
|
<SourceBand>5</SourceBand>
|
|
<SrcRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
<DstRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
</SimpleSource>
|
|
<SimpleSource>
|
|
<SourceFilename relativeToVRT="1">nine_band.dat</SourceFilename>
|
|
<SourceBand>9</SourceBand>
|
|
<SrcRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
<DstRect xOff="0" yOff="0" xSize="1000" ySize="1000"/>
|
|
</SimpleSource>
|
|
</VRTRasterBand>
|
|
</VRTDataset>
|
|
\endcode
|
|
|
|
In addition to the subclass specification (VRTDerivedRasterBand) and
|
|
the PixelFunctionType value, there is another new parameter that can come
|
|
in handy: SourceTransferType. Typically the source rasters are obtained
|
|
using the data type of the derived band. There might be times,
|
|
however, when you want the pixel function to have access to
|
|
higher resolution source data than the data type being generated.
|
|
For example, you might have a derived band of type "Float", which takes
|
|
a single source of type "CFloat32" or "CFloat64", and returns the imaginary
|
|
portion. To accomplish this, set the SourceTransferType to "CFloat64".
|
|
Otherwise the source would be converted to "Float" prior to
|
|
calling the pixel function, and the imaginary portion would be lost.
|
|
|
|
\code
|
|
<VRTDataset rasterXSize="1000" rasterYSize="1000">
|
|
<VRTRasterBand dataType="Float32" band="1" subClass="VRTDerivedRasterBand">
|
|
<Description>Magnitude</Description>
|
|
<PixelFunctionType>MyFirstFunction</PixelFunctionType>
|
|
<SourceTransferType>CFloat64</SourceTransferType>
|
|
...
|
|
\endcode
|
|
|
|
<h3>Writing Pixel Functions</h3>
|
|
|
|
To register this function with GDAL (prior to accessing any VRT datasets
|
|
with derived bands that use this function), an application calls
|
|
GDALAddDerivedBandPixelFunc with a key and a GDALDerivedPixelFunc:
|
|
|
|
\code
|
|
GDALAddDerivedBandPixelFunc("MyFirstFunction", TestFunction);
|
|
\endcode
|
|
|
|
A good time to do this is at the beginning of an application when the
|
|
GDAL drivers are registered.
|
|
|
|
GDALDerivedPixelFunc is defined with a signature similar to IRasterIO:
|
|
|
|
@param papoSources A pointer to packed rasters; one per source. The
|
|
datatype of all will be the same, specified in the eSrcType parameter.
|
|
|
|
@param nSources The number of source rasters.
|
|
|
|
@param pData The buffer into which the data should be read, or from which
|
|
it should be written. This buffer must contain at least nBufXSize *
|
|
nBufYSize words of type eBufType. It is organized in left to right,
|
|
top to bottom pixel order. Spacing is controlled by the nPixelSpace,
|
|
and nLineSpace parameters.
|
|
|
|
@param nBufXSize The width of the buffer image into which the desired
|
|
region is to be read, or from which it is to be written.
|
|
|
|
@param nBufYSize The height of the buffer image into which the desired
|
|
region is to be read, or from which it is to be written.
|
|
|
|
@param eSrcType The type of the pixel values in the papoSources raster
|
|
array.
|
|
|
|
@param eBufType The type of the pixel values that the pixel function must
|
|
generate in the pData data buffer.
|
|
|
|
@param nPixelSpace The byte offset from the start of one pixel value in
|
|
pData to the start of the next pixel value within a scanline. If
|
|
defaulted (0) the size of the datatype eBufType is used.
|
|
|
|
@param nLineSpace The byte offset from the start of one scanline in
|
|
pData to the start of the next.
|
|
|
|
@return CE_Failure on failure, otherwise CE_None.
|
|
|
|
\code
|
|
typedef CPLErr
|
|
(*GDALDerivedPixelFunc)(void **papoSources, int nSources, void *pData,
|
|
int nXSize, int nYSize,
|
|
GDALDataType eSrcType, GDALDataType eBufType,
|
|
int nPixelSpace, int nLineSpace);
|
|
\endcode
|
|
|
|
The following is an implementation of the pixel function:
|
|
|
|
\code
|
|
#include "gdal.h"
|
|
|
|
CPLErr TestFunction(void **papoSources, int nSources, void *pData,
|
|
int nXSize, int nYSize,
|
|
GDALDataType eSrcType, GDALDataType eBufType,
|
|
int nPixelSpace, int nLineSpace)
|
|
{
|
|
int ii, iLine, iCol;
|
|
double pix_val;
|
|
double x0, x3, x4, x8;
|
|
|
|
// ---- Init ----
|
|
if (nSources != 4) return CE_Failure;
|
|
|
|
// ---- Set pixels ----
|
|
for( iLine = 0; iLine < nYSize; iLine++ )
|
|
{
|
|
for( iCol = 0; iCol < nXSize; iCol++ )
|
|
{
|
|
ii = iLine * nXSize + iCol;
|
|
/* Source raster pixels may be obtained with SRCVAL macro */
|
|
x0 = SRCVAL(papoSources[0], eSrcType, ii);
|
|
x3 = SRCVAL(papoSources[1], eSrcType, ii);
|
|
x4 = SRCVAL(papoSources[2], eSrcType, ii);
|
|
x8 = SRCVAL(papoSources[3], eSrcType, ii);
|
|
|
|
pix_val = sqrt((x3*x3+x4*x4)/(x0*x8));
|
|
|
|
GDALCopyWords(&pix_val, GDT_Float64, 0,
|
|
((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace,
|
|
eBufType, nPixelSpace, 1);
|
|
}
|
|
}
|
|
|
|
// ---- Return success ----
|
|
return CE_None;
|
|
}
|
|
\endcode
|
|
|
|
|
|
\section gdal_vrttut_mt Multi-threading issues
|
|
|
|
When using VRT datasets in a multi-threading environment, you should be
|
|
careful to open the VRT dataset by the thread that will use it afterwards. The
|
|
reason for that is that the VRT dataset uses GDALOpenShared when opening the
|
|
underlying datasets. So, if you open twice the same VRT dataset by the same
|
|
thread, both VRT datasets will share the same handles to the underlying
|
|
datasets.
|
|
|
|
The shared attribute, added in GDAL 2.0.0, on the SourceFilename indicates whether the
|
|
dataset should be shared (value is 1) or not (value is 0). The default is 1.
|
|
If several VRT datasets refering to the same underlying sources are used in a multithreaded context,
|
|
shared should be set to 0. Alternatively, the VRT_SHARED_SOURCE configuration
|
|
option can be set to 0 to force non-shared mode.
|
|
|
|
\section gdal_vrttut_perf Performance considerations
|
|
|
|
A VRT can reference many (hundreds, thousands, or more) datasets. Due to
|
|
operating system limitations, and for performance at opening time, it is
|
|
not reasonable/possible to open them all at the same time. GDAL has a "pool"
|
|
of datasets opened by VRT files whose maximum limit is 100 by default. When it
|
|
needs to access a dataset referenced by a VRT, it checks if it is already in
|
|
the pool of open datasets. If not, when the pool has reached its limit, it closes
|
|
the least recently used dataset to be able to open the new one. This maximum
|
|
limit of the pool can be increased by setting the GDAL_MAX_DATASET_POOL_SIZE
|
|
configuration option to a bigger value. Note that a typical user process on
|
|
Linux is limited to 1024 simultaneously opened files, and you should let some
|
|
margin for shared libraries, etc...
|
|
As of GDAL 2.0, gdal_translate and gdalwarp, by default, increase the pool size
|
|
to 450.
|
|
|
|
*/
|