This directory contains two projects (since August 2004). They
both do exactly the same but are designed totally differently:

The first one (ws_2001_2002) can be dated back to the year 2001
where there was no possibility to attach VIGRA algorithms to
the image classes of the TUVision library. It contains custom,
non-generic classes for building a horizontal average/difference
of an image, even without subclassing but with a special enum
for the internal state.

This design may look quite straightforward as it is simple and
almost no prerequisites apart from knowing how images are stored
in memory and the C++-language are necessary. However, such code
is modular and may lead to irritating rewrites (copy & paste of code)
later when developing own methods, e.g. as soon as a detail of the
algorithm or the image type changes - from black to RGB or something
similar.

The second one (ws_2001_2002_vigra) heavily uses the VIGRA routines
which are designed in a highly modular way. It may be interesting to
compare the two examples and realize that image processing methods
can be split up into different aspects which are *totally* uncorrelated:

- Image navigation (the image is processed from upper left two lower
  right when building averages/difference), but it may be the case
  that the same algorithm (building averages/differences) is needed
  later for other regions than the whole image, e.g. only "regions of
  interest". In the old example, the code for navigation across the
  image can be found in the four "for"-loops which basically encode
  the same behavior, i.e. looping across the whole image. This is bad as
  the code in case of an algorithmic change has to be modified at
  four different places! Image Iterators which are used in VIGRA provide
  a much better way. They only implement functionality which is related to
  image navigation, nothing more and nothing less. Hence then can be
  used as modular blocks which can be exchanged easily later.
  In the new example, a special Iterator is used for accessing every
  second pixel only. It can be left as an excersize to change it
  such that the whole image is processed, i.e. a real low-pass-filter
  is applied.

- Pixel access (after navigating to the correct pixel to process,
  accessing it). In the old algorithm, the code can be used only
  for gray images. RGB images would be processed totally wrong, e.g.
  as the line

    outputrow[x]=abs(inputrow[2*x]-inputrow[2*x+1])/2;

  which does the work for the difference operator subtracts two
  adjacent bytes, i.e. when dealing with a color image, the R and G
  channel of an RGB pixel would be subtracted. This limitation is
  not necessary. VIGRA defined RGBValue<> as a template for an
  RGB pixel (of an arbitrary datatype). It also defines the "-"-Operator
  and the abs()-function, so when dealing with RGB images, the same
  could can be taken. In the new example, pixel access explicitely can
  be seen as an object (grayaccess). For gray images, this is quite
  trivial, but for RGB images, other options are possible: Consider
  an RGB image of which the average/difference should be computed with
  respect to the gray value of each pixel. Usually, this requires a
  conversion step from RGB to gray first and building the
  average/difference is done with the converted image afterwards.
  With VIGRA this is not necessary as using a RGBtoGrayAccessor<> is
  defined for RGB images such that conversion gets done on-the-fly, i.e.
  when accessing the "gray value of an RGB pixel".
  
- Algorithm (building the difference/average). The algorithm is encapsulated
  as an expression template and is totally independent of navigation
  and/or access.