[Insight-developers] Vigra data accessors
Luis Ibanez
ibanez at cs.unc.edu
Fri Oct 27 14:31:15 EDT 2000
Hi,
These are some extracts from the article
http://kogs-www.informatik.uni-hamburg.de/~koethe/papers/handbook.ps.gz
from the Vigra package home page:
http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/
The method used here is what Bill proposed during the tcon,
that is, adding another template parameter to the filter.
This extra parameter is a class that will specify which
part of the pixel structure will be used as input, and
what part of the output pixel structure will be written on.
======== "Begin of extract 1 from the paper" ===============
6.2.5 Data accessors
The idioms reported so far (generic data structures and algorithms, it
erators, and functors) are the basis of the STL. However, experience has
shown that algorithms and data structures are not su#ciently indepen
dent as long as we have only a single function
iterator::operator*()
to access the iterator's current data item. There are two fundamental
problems with this function: First, it assumes that all algorithms want
to see the entire data at the current position. This makes it
problematic
to operate on a subset of the actual data structure (such as a single
color band of an RGB image). Second, *iterator must be used for
both reading and writing the data. This means, operator*() must
return the data by reference if we want to overwrite it. This is di#cult
to implement for certain container implementations (e. g., a multiband
RGB image).
Therefore, additional interface objects, called data accessors, are
needed to encapsulate actual data access (Kühl and Weihe [3]). A data
accessor reads data at the current iterator position via a get()
function,
and writes them via a set() function. Within these functions, arbitrary
adaptations (such as extracting just the red band of an RGB pixel, of
transforming RGB to gray) can be performed. In general, a data accessor
looks like this:
template <typename VALUETYPE, typename ITERATOR>
struct SomeAccessor
{
typedef VALUETYPE value_type; // advertise your value
type
value_type get(ITERATOR & i) const; // read an item
void set(value_type v, ITERATOR & i) const; // write an item
};
Using this data accessor, we can implement a more general version
of the linear copy() algorithm like this:
template <typename SrcIterator, typename SrcAccessor,
typename DestIterator, typename SrcAccessor>
void copy(SrcIterator s, SrcIterator end, SrcAccessor sa,
DestIterator d, DestAccessor da)
{
for(; s != end; ++s, ++d) da.set(sa.get(s), d); // read/write via
accessor
}
Although it is probably hard to see the advantages of accessors
(and generic programming in general) in an algorithm as simple as
copy(), the same techniques can be applied to arbitrary complicated
algorithms, where reuse will really pay
=========== " end of extract 1 " ==========================
======== "Begin of extract 2 from the paper" ===============
Image data accessors
When we implemented an image iterator for the AbstractImage we
saw that it was impossible to provide data access operators (operator*
and operator()) that returned the current data item by reference. An
other common example for a data structure suffering from this prob
lem is the multiband RGB image. In a multiband RGB image, pixel val
ues are stored in three separate images (bands) for each of the three
color components, rather than in one image of compound RGBStructs
(as, for example, the RGBStructImage defined in section ``Generic pro
gramming''). A typical implementation of a multiband RGB image could
look like this:
class MultibandRGBImage
{
public:
unsigned char & red(int x, int y);
unsigned char & green(int x, int y);
unsigned char & blue(int x, int y);
//...
private:
unsigned char * redband, * greenband, * blueband;
};
The corresponding image iterator would simply mirror the access
functions of the image:
struct MultibandRGBImageIterator
{
// navigation functions not shown ...
unsigned char & red();
unsigned char & green();
unsigned char & blue();
/* this is difficult or impossible to implement
RGBStruct<unsigned char> & operator*();
RGBStruct<unsigned char> & operator()(int dx, int dy);
*/
};
Once again we can not implement the standard access functions
used within the STL, because the desired return type
RGBStruct<unsigned char>&
does not physically exist in the underlying image data structure. Thus,
while it is easy to define a uniform navigation interface for the itera
tors, we can not guarantee that all iterators have a uniform data access
interface. Kühl and Weihe [3] proposed an additional level of indirec
tion, the data accessor, to recover the desired uniform interface. As
was
mentioned earlier, data accessors provide a pair of get() and set()
functions which are INLINED by the compiler so that the additional in
direction does not a#ect performance. In cases where the iterator pro
vides operator*, get and set simply call it:
template <typename VALUETYPE, typename STANDARDITERATOR>
struct StandardAccessor
{
typedef VALUETYPE value_type; // advertise your value type
value_type get(STANDARDITERATOR & i) const {
return *i; // read current item
}
void set(value_type v, STANDARDITERATOR & i) const {
*i = v; // write current item
};
Since the AbstractImageIterator does not work this way, it needs
a different accessor that could look like this:
struct AbstractImageAccessor
{
typedef unsigned char value_type;
value_type get(AbstractImageIterator & i) const {
return i.get();
}
void set(value_type v, AbstractImageIterator & i) const {
i.set(v);
}
};
In addition to the standard get() and set() functions, an RGB ac
cessor provides functions to access each color separately. These func
tions will be used by algorithms which explicitly require RGB pixels.
For the multiband RGB image, such an accessor could be defined as
follows:
struct MultibandRGBImageAccessor
{
typedef RGBStruct<unsigned char> value_type;
typedef unsigned char component_type;
value_type get(MultibandRGBImageIterator & i) const {
return value_type(i.red(), i.green(), i.blue());
}
void set(value_type rgb, MultibandRGBImageIterator & i) const {
i.red() = v.red; // assume that the iterator
i.reen() = v.green; // mirrors the red(), green(),
i.blue() = v.blue; // blue() function of the image
} // which return data by reference
component_type getRed(MultibandRGBImageIterator & i) const {
return i.red();
}
void setRed(component_type v, MultibandRGBImageIterator & i) const {
i.red() = v;
}
// ...
};
Providing a uniform data access interface regardless of the under
lying image implementation is not the only advantage of introducing
accessors: they can also be used to perform an arbitrary transforma
tion before the algorithm actually sees the data (for instance, color to
gray conversion), or to restrict access to just a part of the current
item,
such as one color component of an RGB pixel. For example, we could
select just the red band of the RGBStructImage by using the following
accessor:
struct RedComponentAccessor
{
typedef unsigned char value_type;
value_type get(RGBStructImage::Iterator & i) {
return (*i).red;
}
void set(value_type v, RGBStructImage::Iterator & i) const {
(*i).red = v;
}
};
For example, we could now apply a scalar convolution to each color
component separately by calling the convolution algorithm (Sect. 6.5.3)
with red, green, and blue band accessors in turn. Without accessors,
this behavior would be di#cult to implement for the RGBStructImage,
whereas it would be easy for a MultibandRGBImage. Hence accessors
serve to smooth out the di#erences between various implementation
choices for the image data structures which would otherwise make uni
versally reusable algorithm implementations impossible.
=========== " end of extract 2 " ==========================
Luis
______________________________________________________________________
Luis Ibanez
Research Assistant Professor - Division of Neurosurgery
University of North Carolina at Chapel Hill
CB# 7060, Chapel Hill, NC 27599
email : ibanez at cs.unc.edu home : http://www.cs.unc.edu/~ibanez
phone : (919)-843-9961 fax : (919)-966-6627
______________________________________________________________________
More information about the Insight-developers
mailing list