Next: , Up: Customized Arrays   [Contents][Index]


5.1 Multicomponent and complex arrays

Multicomponent arrays have elements which are vectors. Examples of such arrays are vector fields, colour images (which contain, say, RGB tuples), and multispectral images. Complex-valued arrays can also be regarded as multicomponent arrays, since each element is a 2-tuple of real values.

Here are some examples of multicomponent arrays:

// A 3-dimensional array; each element is a length 3 vector of float
Array<TinyVector<float,3>,3> A;  

// A complex 2-dimensional array
Array<complex<double>,2> B;

// A 2-dimensional image containing RGB tuples
struct RGB24 {
  unsigned char r, g, b;
};

Array<RGB24,2> C;

5.1.1 Extracting components

Blitz++ provides some special support for such arrays. The most important is the ability to extract a single component. For example:

Array<TinyVector<float,3>,2> A(128,128);
Array<float,2> B = A.extractComponent(float(), 1, 3);
B = 0;

The call to extractComponent returns an array of floats; this array is a view of the second component of each element of A. The arguments of extractComponent are: (1) the type of the component (in this example, float); (2) the component number to extract (numbered 0, 1, ... N-1); and (3) the number of components in the array.

This is a little bit messy, so Blitz++ provides a handy shortcut using operator[]:

Array<TinyVector<float,3>,2> A(128,128);
A[1] = 0;

The number inside the square brackets is the component number. However, for this operation to work, Blitz++ has to already know how many components there are, and what type they are. It knows this already for TinyVector and complex<T>. If you use your own type, though, you will have to tell Blitz++ this information using the macro BZ_DECLARE_MULTICOMPONENT_TYPE(). This macro has three arguments:

BZ_DECLARE_MULTICOMPONENT_TYPE(T_element, T_componentType, numComponents)

T_element is the element type of the array. T_componentType is the type of the components of that element. numComponents is the number of components in each element.

An example will clarify this. Suppose we wanted to make a colour image, stored in 24-bit HSV (hue-saturation-value) format. We can make a class HSV24 which represents a single pixel:

#include <blitz/array.h>

using namespace blitz;

class HSV24 {
public:
    // These constants will makes the code below cleaner; we can
    // refer to the components by name, rather than number.

    static const int hue=0, saturation=1, value=2;

    HSV24() { }
    HSV24(int hue, int saturation, int value)
      : h_(hue), s_(saturation), v_(value)
    { }

    // Some other stuff here, obviously

private:
    unsigned char h_, s_, v_;
};

Right after the class declaration, we will invoke the macro BZ_DECLARE_MULTICOMPONENT_TYPE to tell Blitz++ about HSV24:

// HSV24 has 3 components of type unsigned char
BZ_DECLARE_MULTICOMPONENT_TYPE(HSV24, unsigned char, 3);

Now we can create HSV images and modify the individual components:

int main()
{
    Array<HSV24,2> A(128,128);   // A 128x128 HSV image
    ...

    // Extract a greyscale version of the image
    Array<unsigned char,2> A_greyscale = A[HSV24::value];

    // Bump up the saturation component to get a
    // pastel effect
    A[HSV24::saturation] *= 1.3; 

    // Brighten up the middle of the image
    Range middle(32,96);
    A[HSV24::value](middle,middle) *= 1.2;
}

5.1.2 Special support for complex arrays

Since complex arrays are used frequently, Blitz++ provides two special methods for getting the real and imaginary components:

Array<complex<float>,2> A(32,32);

real(A) = 1.0;
imag(A) = 0.0;

The function real(A) returns an array view of the real component; imag(A) returns a view of the imaginary component.

Note: Blitz++ provides numerous math functions defined over complex-valued arrays, such as conj, polar, arg, abs, cos, pow, etc. See the section on math functions (Math functions 1) for details.

5.1.3 Zipping together expressions

Blitz++ provides a function zip() which lets you combine two or more expressions into a single component. For example, you can combine two real expressions into a complex expression, or three integer expressions into an HSV24 expression. The function has this syntax:

resultexpr zip(expr1, expr2, T_element)
resultexpr zip(expr1, expr2, expr3, T_element)         ** not available yet
resultexpr zip(expr1, expr2, expr3, expr4, T_element)  ** not available yet

The types resultexpr, expr1 and expr2 are array expressions. The third argument is the type you want to create. For example:

int N = 16;
Array<complex<float>,1> A(N);
Array<float,1> theta(N);

 ...

A = zip(cos(theta), sin(theta), complex<float>());

The above line is equivalent to:

for (int i=0; i < N; ++i)
   A[i] = complex<float>(cos(theta[i]), sin(theta[i]));

Next: , Up: Customized Arrays   [Contents][Index]