I'm implementing some image processing algorithms in C++. I created a

class called 'image' (see declaration below), that will take care of the

memory allocations and some basic (mathematical) stuff. The class will

behave like a std::vector (copy constructor and assignment create a deep

copy), but with 2D indexing.

Now I also need a 'view' class that will behave like a reference to an

'image' (can only be constructed from an existing image, copy

constructor creates a shallow copy and assignment operator a deep copy).

And it should have the additional property that it may contain only a

portion of the original image. I will show some examples to make clear

what I need:

// For images:

image<int> ima, imb(512,512), imc = imb; // Create some images

point p(3,3); // Create the point (3,3)

ima = 0; // Set all pixels to zero

ima = imb; // Copy all pixels

ima += 64; // Elementwise mathematical operators (+,-,* and /)

ima += imb; // Elementwise mathematical operators (+,-,* and /)

ima(0,0) = 255; // Indexing

ima(p) = 128; // Indexing with point

// For views:

range r(0,256,1) // Create the range [0,256[ with stride 1

view<int> va = ima(r,r), vb = imb(r,r); // Create subimages

view<int> vc = vb; // Create a shallow copy

va = 0; // Set all pixels (in the subimage) to zero

va = vb; // Copy all pixels (in the subimages)

.... // Indexing, mathematical operators

// For mixed images and views:

view<int> vd = ima; // Create a shallow copy

image<int> imd = vd; // Create a deep copy

ima = vb; vb = ima; // Copy all pixels

I created my first view class (see declaration below). The class does

not allocate or deallocate memory, it only keeps a pointer to the memory

obtained from the source image. But there are some problems:

* There are no conversions possible from image <--> view. I think I can

solve this with two additional constructors image(const view<T>& rhs)

and view(const image<T>& rhs)? And also for the other member functions?

* If the original image is destroyed or new memory is allocated

(resizing, assignment with different size), all associated views will

now point to invalid memory. It is also not possible to return a view

from a function, if it was created from a local image. This would be

usefull to prevent unnecessary copying, since copying an image object is

expensive, while copying a view is not.

* And the most important: I will have to duplicate every algorithm to

work on both images and views. Or even more code for mixed cases. Maybe

I could solve this by deriving the view class from the image class and

making all member functions virtual? But won't this approach slow down

the trivial functions, like operator(), due to the overhead of a virtual

function call? And these functions will be called very frequently in loops.

Any suggestions to solve these problems or to improve my classes are

welcome. Maybe there is already an existing framework that has this

functionality? Keep in mind that I will need 3D planar images as well

(extra template parameter N?).

template <typename T>

class image {

public: // Typedefs

typedef T value_type;

typedef std::size_t size_type;

typedef std::ptrdiff_t difference_type ;

protected: // Data members

value_type *m_data;

size_type m_datasize;

size_type m_rows, m_columns;

public:

// Constructors and destructor.

image();

image(size_type m, size_type n);

image(size_type m, size_type n, const value_type& init);

image(const image<T>& rhs);

~image();

// Assignment operators.

image<T>& operator=(const image<T>& rhs);

image<T>& operator=(const value_type& rhs);

// Indexing operators.

value_type& operator()(size _type i, size_type j);

value_type& operator()(poin t p);

view<T> operator()(rang e i, range j);

const value_type& operator()(size _type i, size_type j) const;

const value_type& operator()(poin t p) const;

const view<T> operator()(rang e i, range j) const;

// Size functions.

size_type size() const;

size_type rows() const;

size_type columns() const;

// Elementwise mathematical operators

image<T>& operator+=(cons t image<T>& rhs);

image<T>& operator-=(const image<T>& rhs);

image<T>& operator*=(cons t image<T>& rhs);

image<T>& operator/=(const image<T>& rhs);

image<T>& operator+=(cons t value_type& rhs);

image<T>& operator-=(const value_type& rhs);

image<T>& operator*=(cons t value_type& rhs);

image<T>& operator/=(const value_type& rhs);

};

template <typename T>

class view {

public: // Typedefs

typedef T value_type;

typedef std::size_t size_type;

typedef std::ptrdiff_t difference_type ;

protected: // Data members

value_type *m_origin;

size_type m_rows, m_columns;

difference_type m_rstride, m_cstride;

public:

// Constructors and destructor.

view(const view<T>& rhs);

~view();

// Assignment operators.

view<T>& operator=(const view<T>& rhs);

view<T>& operator=(const value_type& rhs);

// Indexing operators.

value_type& operator()(size _type i, size_type j);

value_type& operator()(poin t p);

view<T> operator()(rang e i, range j);

const value_type& operator()(size _type i, size_type j) const;

const value_type& operator()(poin t p) const;

const view<T> operator()(rang e i, range j) const;

// Size functions.

size_type size() const;

size_type rows() const;

size_type columns() const;

// Elementwise mathematical operators

view<T>& operator+=(cons t view<T>& rhs);

view<T>& operator-=(const view<T>& rhs);

view<T>& operator*=(cons t view<T>& rhs);

view<T>& operator/=(const view<T>& rhs);

view<T>& operator+=(cons t value_type& rhs);

view<T>& operator-=(const value_type& rhs);

view<T>& operator*=(cons t value_type& rhs);

view<T>& operator/=(const value_type& rhs);

};