Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

pixeliterator

martin schouwenburg edited this page Apr 9, 2014 · 9 revisions

The primary access method to the raster (layers) is through the pixeliterator

Design Rationale

There are two main reasons for the introduction of the PixelIterator

  • It allows for an abstracttion of the actual organization of the pixels in a raster. Making the formulation of algorithms significantly easier. This is of course not true for all cases but a very significant portion benefits from it.
  • It allows for much easier intergration with the STL algorithms of C++. The pixeliterator is a random access read/write iterator in C++ terms.

Description

The pixeliterator abstracts the movement through the rows, columns and layers by representing the whole set of raster layers as one linear array of pixels. Within this space a traditional(c++) random access iterator has been defined with all the methods and operators traditionally associated with such a concept. Particularly (see the class for the full interface)

  • Operators ‘++’and ‘—‘ , moving one step in the data-array.
  • Operator ‘*’accessing data
  • Operator ‘[]’ random access

Because this mechanism hides the actual organization of rows, columns and layers, it allows in a large number of cases for the very efficient formulating of algorithms. For those who don’t know how an iterator(in this case) functions. An iterator is an object that abstracts the movement over a (usually linear) container. The pixel iterator (in 2D) moves in the

pattern as indicated over the pixels of a raster. All operations on the iterator happen in the path that the iterator follows. So the index 7 is actual pixel the (1,1) pixel in the raster (0-based). For the 3D case the iterator simply increases the layer-index with one, if the iterator detects that is at the end of this layer and then follows the same pattern on the next layer. The ‘flow’ indicated above is the default XYZ flow. The iterators main axis of movement is the X axis, then the Y axis, then the Z axis. For some algorithms another flow might make more sense. For example for a clustering algorithm a ZXY flow might make more sense. The pattern followed is the same but rotated so that the main movement axis are now Z, then X, then Y. There are basically two flavors of the pixeliterator : the pixel iterator itself and the blockiterator. The pixeliterator moves over single pixels, the blockiterator moves over an [n x m x p] size block (some algorithms need this).

Usage

Suppose i want to know how many pixels have a value over 100. Below is a crude way of doing this

int count = 0;
IRasterCoverage myraster("file:///d:/data/ethiopia-20110322-0845.img");
PixelIterator iter(myraster);
while(iter != end(myraster)){
    if ( *iterator > 100)
       ++count;
}

One could also do

for(auto value : myraster)
   if ( value > 100) ++count;

which is a bit more compact. Values are returned by reference, so one can change them change them. E.g. all value below 100 to 0.

for( auto& value : myraster)
  if ( value < 100) value = 0;

If one doesnt need a full computation of the whole map, but only a window one can do

PixelIterator iter(myraster, BoundingBox(Pixel(234, 408), Pixel(2307, 4500));

or,

Geometry *geom = GeometryHelper::fromWKT("Polygon((23.5 4.67, ....))");
PixelIterator iter(myraster,geom);

In both cases it will only run over the content inside the 'container'. The bounding-box example can also be defined in 3D. If in the 'geometry' case the geometry is a line or a point it will only iterate over pixels covered by the line(s) or point(s).

Integration with the STL is seamless. Below is an example of copying content of a raster to a vector ( assuming there are no memory considerations).

std::vector<double> data(myraster.size().totalSize());
std::copy(begin(myraster), end(myraster), data.begin());
Clone this wiki locally