473,544 Members | 1,955 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Design of image & view classes?

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);
};
Jul 22 '05 #1
8 2598
> * 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?
class view;
class image
{
public:
view& operator(view); // implement in .cpp file
}

* 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.
Do not store pointers to the image's memory, but provide a function
that returns a pointer to the memory - temporarily.
* 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.


why not deriving both from a class: image_base ?
-Gernot
Jul 22 '05 #2
Gernot Frisch wrote:
* 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?

class view;
class image
{
public:
view& operator(view); // implement in .cpp file
}


Is this approach better then providing the additional constructors? It
is probably a typo, but shouldn't this operator return by value instead
of by reference?
* 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.

Do not store pointers to the image's memory, but provide a function
that returns a pointer to the memory - temporarily.


That would solve the resizing. But it still won't work if the original
image is destroyed. And to make this work, the view should contain a
reference (or pointer) to the original image. But this will prevent me
from creating a 2D view from a 3D image/view. Currently I'm thinking
about some reference counting mechanism.
* 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.

why not deriving both from a class: image_base ?


I don't see how this could help. To be usefull, every common member
function (indexing, mathematical operators,...) should be implemented in
the image_base class. But how does this class know if it should access
the memory continuous (image) or with strides (view)? Or am I wrong?
Could you provide a small example?
Jul 22 '05 #3
class view;
class image
{
public:
view& operator(view); // implement in .cpp file
void AddView(view* pView);
void DeleteView(view * pView) {pView->pImage=NULL; }
view& GetView(int index);
private:
int num_views;
view* pViews;
}

class view
{
public:
view(image* pImg) {pImage=pImg; pImg->AddView(this); }
bool IsValidView() {return pImage ? true:false;}
image* GetAttachedImag e() {return pImage;}
void SetView(int x, int y, int width, int height);
image GetViewedImage( ); // image in range x,y,width, height
image operator(image) {return GetViewedImage( );}

private:
image* pImage;
}

image img1, img2;
view vw1(img1);
You have an image, and can have attached a set of views. A view can
only exist with an image (See IsValid function of view).
An image can exist without a view.

Is this what you want? Don't I understand you correctly?
Jul 22 '05 #4
Gernot Frisch wrote:
class view;
class image
{
public:
view& operator(view); // implement in .cpp file
void AddView(view* pView);
void DeleteView(view * pView) {pView->pImage=NULL; }
view& GetView(int index);
private:
int num_views;
view* pViews;
}

class view
{
public:
view(image* pImg) {pImage=pImg; pImg->AddView(this); }
bool IsValidView() {return pImage ? true:false;}
image* GetAttachedImag e() {return pImage;}
void SetView(int x, int y, int width, int height);
image GetViewedImage( ); // image in range x,y,width, height
image operator(image) {return GetViewedImage( );}

private:
image* pImage;
}

image img1, img2;
view vw1(img1);
You have an image, and can have attached a set of views. A view can
only exist with an image (See IsValid function of view).
An image can exist without a view.

Is this what you want? Don't I understand you correctly?


This is more or less correct. An image contains its own (continuous)
memory and has some member functions to manipulate this memory. A view
is used to look at the memory of this image in a different way (e.g.
subimage), or the same way. The view should have the same member
functions as the image, but they should operate on the data in the view.
Only the copy constructor of the view should behave different (not the
underlying data, but the way of viewing should be copied).

An example for a small 4 x 4 image that look like this:

1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4

// Create 2 subimages of size 2x2
range ra(0,2),rb(2,4) ;
view va = img(ra,ra); // Upper left part
view vb = img(rb,rb); // Lower right part
view vc = vb; // Lower right part

va = 0;
// Original image will now contain:
0 0 2 2
0 0 2 2
3 3 4 4
3 3 4 4

va = vb;
// Original image will now contain:
4 4 2 2
4 4 2 2
3 3 4 4
3 3 4 4

img(0,0) = 0;
img(1,1) = 0;
vc(0,0) = 1;
vc(1,1) = 1;
// Original image will now contain:
0 4 2 2
4 0 2 2
3 3 1 4
3 3 4 1

Jul 22 '05 #5
> This is more or less correct. An image contains its own (continuous)
memory and has some member functions to manipulate this memory. A
view is used to look at the memory of this image in a different way
(e.g. subimage), or the same way. The view should have the same
member functions as the image, but they should operate on the data
in the view. Only the copy constructor of the view should behave
different (not the underlying data, but the way of viewing should be
copied).


So, implement the image class's functions. Then do:

((image)a_view) .call_image_fun ction();

That's what you want, no? You only have to code stuff once for the
image, if the view has an image cast operator.
-Gernot
Jul 22 '05 #6
Gernot Frisch wrote:
This is more or less correct. An image contains its own (continuous)
memory and has some member functions to manipulate this memory. A
view is used to look at the memory of this image in a different way
(e.g. subimage), or the same way. The view should have the same
member functions as the image, but they should operate on the data
in the view. Only the copy constructor of the view should behave
different (not the underlying data, but the way of viewing should be
copied).

So, implement the image class's functions. Then do:

((image)a_view) .call_image_fun ction();

That's what you want, no? You only have to code stuff once for the
image, if the view has an image cast operator.


This won't work, because casting the view to an image should create a
new image (with its own memory). Applying the call_image_func tion on
this new image will not modify the memory of the original image anymore.

My small example image again:

image ima =
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4

// Create a view to the upper left part
view v = img(range(0,2), range(0,2));
// Cast view to a new image
image imb = v;
// The content of imb should be a real copy
// of the upper left part of the original image.
// 1 1
// 1 1
// Changing imb should leave the original image intact.
imb = 0;
// Results in
imb =
0 0
0 0
ima =
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
Jul 22 '05 #7

"Jef Driesen" <je********@hot mail.com.nospam > schrieb im Newsbeitrag
news:cs******** *@ikaria.belnet .be...
Gernot Frisch wrote:
This is more or less correct. An image contains its own
(continuou s) memory and has some member functions to manipulate
this memory. A view is used to look at the memory of this image in
a different way (e.g. subimage), or the same way. The view should
have the same member functions as the image, but they should
operate on the data in the view. Only the copy constructor of the
view should behave different (not the underlying data, but the way
of viewing should be copied).

So, implement the image class's functions. Then do:

((image)a_view) .call_image_fun ction();

That's what you want, no? You only have to code stuff once for the
image, if the view has an image cast operator.


This won't work, because casting the view to an image should create
a new image (with its own memory). Applying the call_image_func tion
on this new image will not modify the memory of the original image
anymore.


OK. Then make the image be accessable through a view only. If you want
to operate on the image directly, cast the image to a view and use the
view's functions (fullsize) for manipulating the pixels.
-Gernot
Jul 22 '05 #8
Gernot Frisch wrote:
"Jef Driesen" <je********@hot mail.com.nospam > schrieb im Newsbeitrag
news:cs******** *@ikaria.belnet .be...
Gernot Frisch wrote:
This is more or less correct. An image contains its own
(continuous ) memory and has some member functions to manipulate
this memory. A view is used to look at the memory of this image in
a different way (e.g. subimage), or the same way. The view should
have the same member functions as the image, but they should
operate on the data in the view. Only the copy constructor of the
view should behave different (not the underlying data, but the way
of viewing should be copied).
So, implement the image class's functions. Then do:

((image)a_vi ew).call_image_ function();

That's what you want, no? You only have to code stuff once for the
image, if the view has an image cast operator.


This won't work, because casting the view to an image should create
a new image (with its own memory). Applying the call_image_func tion
on this new image will not modify the memory of the original image
anymore.

OK. Then make the image be accessable through a view only. If you want
to operate on the image directly, cast the image to a view and use the
view's functions (fullsize) for manipulating the pixels.


This works, but the downside is that accessing pixels in a view is
slower compared to pixels in an image. For example operator= is
implemented like this for an image and a view:

image& image::operator =(const value_type& rhs)
{
std::fill(m_dat a, m_data + m_datasize, rhs);
return *this;
}

view& view::operator= (const value_type& rhs)
{
for (size_type i = 0; i < m_rows; ++i) {
value_type *p = m_origin + i * m_rstride;
for (size_type j = 0; j < m_columns; ++j) {
*p = rhs; p += m_cstride;
}
}
return *this;
}

This way, there is almost no reason anymore for the image class to
exist. The only difference that will remain with this approach is the
copy constructor (shallow vs deep copy).
Jul 22 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
1793
by: Code4u | last post by:
I need to design data storage classes and operators for an image processing system that must support a range of basic data types of different lengths i.e. float, int, char, double. I have a template class that stores the data. The problem with this design is the inability to treat image data generically- I have a set of specialized classes...
0
1890
by: Edward Diener | last post by:
In Borland's VCL it was possible to divide a component into design time and run time DLLs. The design time DLL would only be necessary when the programmer was setting a component's properties or events in the Object Inspector, the equivalent to the VS .NET Windows form designer. The run-time DLL would only contain the code necessary at...
17
2674
by: tshad | last post by:
Many (if not most) have said that code-behind is best if working in teams - which does seem logical. How do you deal with the flow of the work? I have someone who is good at designing, but know nothing about ASP. He can build the design of the pages in HTML with tables, labels, textboxes etc. But then I would need to change them to...
1
1743
by: automation | last post by:
I have a web-page consisting of a listbox & image buttons. I want to post to the appropriate PHP script based on which list_item and image button combination is selected, where the logic is determined by JavaScript. So far, I can determine what list_item has been selected, but how do I determine what image button was selected? The current PHP...
0
2493
by: YellowFin Announcements | last post by:
Introduction Usability and relevance have been identified as the major factors preventing mass adoption of Business Intelligence applications. What we have today are traditional BI tools that don't work nearly as well as they should, even for analysts and power users. The reason they haven't reached the masses is because most of the tools...
6
2221
by: googletired | last post by:
Hello, I haven't made a XSL in quite sometime so i am very rusty. Basicly i want the XSL to display a defined image if one is not present in the XML. here is my current XSL and XML will be below that, hope you can help. <?xml version='1.0' encoding='utf-8' ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" ...
1
2008
by: sravani1 | last post by:
This code runs like when i submit the form it takes the image and displayed and top of the image a map will displayed. But actually i want that when i give the image it checks the location in the map and after displayed it.plz tell that how to start the logic. <?php // Connect to database $errmsg = "";if (!...
21
1542
by: DP | last post by:
Hi, I'm not sure if this is the right group to ask. I am developing a small image library and I don't know how to hide the actual path to the image. So I go to the stock photo library websites to see how they hide their images. This is what I see from gettyimages.com <img src="http://cache2.asset-cache.net/xc/200186170-001.jpg?...
4
2447
by: Ken Fine | last post by:
I've been living with a frustrating issue with VS.NET for some months now and I need to figure out what the problem is. Hopefully someone has run into the same issue and can suggest a fix. I suspect some permissions problem. I'm running VS.NET 2008 in Vista. Symptoms and observations: * ASP.NET's native ImageMap and Image controls work...
0
7420
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7602
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7764
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
7704
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5904
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
4911
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3407
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1837
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
657
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.