switch from raw pointer to vector container

M

markww

Hi,

I want to use the vector container class to store pixel data. Currently
I have some memory allocated using c++'s new operator. I allocate the
memory differently based on if the pixel type is unsigned char or
unsigned short like this:

int nPixelType = ?; // unsigned short, or unsigned char?
BYTE *pByte = NULL;
switch (nPixelType) {
case UNSIGNED_SHORT:
pBtye = (BYTE *)new unsigned char[256 * 256];
break;

case UNSIGNED_CHAR:
pByte = (BYTE *)new unsigned char[256 * 256];
break;
}

Then I whenever I was doing image processing tasks, I would create a
temporary pointer to the data and cast it to the correct type:

unsigned short *p = (unsigned short *)pByte;
or
unsigned char *p = (unsigned char *)pByte;

Now it was suggested to me that I stop using raw pointers like this in
favor of vector containers. Can I translate the above into a vector of
BYTE and accomplish the same thing? Would it be possible to get around
having to cast the pointer before accessing it everytime?

vector<BYTE> vNew;
vNew.resize(256 * 256);

Thanks
 
R

Ron Natalie

markww said:
Hi,

I want to use the vector container class to store pixel data. Currently
I have some memory allocated using c++'s new operator. I allocate the
memory differently based on if the pixel type is unsigned char or
unsigned short like this:

int nPixelType = ?; // unsigned short, or unsigned char?
BYTE *pByte = NULL;
switch (nPixelType) {
case UNSIGNED_SHORT:
pBtye = (BYTE *)new unsigned char[256 * 256];
break;

case UNSIGNED_CHAR:
pByte = (BYTE *)new unsigned char[256 * 256];
break;
}
This is C++ after all. What's with all the casting and switch
statements. Either make an abstract base:

class PixelData {
public:
virtual void* GetRawData() = 0;
virtual void Resize(int width, int height);
};

class UnsignedCharPixelData : public PixelData {
vector<unsigned char> uc_data;
public:
virtual void Resize(int width, int height) {
uc_data.resize(width*height);
}
virtual void* GetRawData() { return &uc_data[0]; }
};

or use a templated class:

template <typename PixelType > class PixelData {
vector<PixelType> pdata;
public:
void* GetRawData() { return &pdata[0]; }
void Resize(int w, int h) {
pdata.resize(w*h);
}
};
 
J

Jim Langston

markww said:
Hi,

I want to use the vector container class to store pixel data. Currently
I have some memory allocated using c++'s new operator. I allocate the
memory differently based on if the pixel type is unsigned char or
unsigned short like this:

int nPixelType = ?; // unsigned short, or unsigned char?
BYTE *pByte = NULL;
switch (nPixelType) {
case UNSIGNED_SHORT:
pBtye = (BYTE *)new unsigned char[256 * 256];
break;

case UNSIGNED_CHAR:
pByte = (BYTE *)new unsigned char[256 * 256];
break;
}

Then I whenever I was doing image processing tasks, I would create a
temporary pointer to the data and cast it to the correct type:

unsigned short *p = (unsigned short *)pByte;
or
unsigned char *p = (unsigned char *)pByte;

Now it was suggested to me that I stop using raw pointers like this in
favor of vector containers. Can I translate the above into a vector of
BYTE and accomplish the same thing? Would it be possible to get around
having to cast the pointer before accessing it everytime?

vector<BYTE> vNew;
vNew.resize(256 * 256);

Thanks

There are a few ways to accomplish this, including a class that keeps track
of the type of data it is and allocates appropriately, or templates, or
polymorphism (Pixel as base class, PixelShort or PixelChar as derived
classes), etc...

A vector container, itself, isn't a solution other than storing the data.
You still have to decide what type of data to store.
 
M

markww

Jim said:
markww said:
Hi,

I want to use the vector container class to store pixel data. Currently
I have some memory allocated using c++'s new operator. I allocate the
memory differently based on if the pixel type is unsigned char or
unsigned short like this:

int nPixelType = ?; // unsigned short, or unsigned char?
BYTE *pByte = NULL;
switch (nPixelType) {
case UNSIGNED_SHORT:
pBtye = (BYTE *)new unsigned char[256 * 256];
break;

case UNSIGNED_CHAR:
pByte = (BYTE *)new unsigned char[256 * 256];
break;
}

Then I whenever I was doing image processing tasks, I would create a
temporary pointer to the data and cast it to the correct type:

unsigned short *p = (unsigned short *)pByte;
or
unsigned char *p = (unsigned char *)pByte;

Now it was suggested to me that I stop using raw pointers like this in
favor of vector containers. Can I translate the above into a vector of
BYTE and accomplish the same thing? Would it be possible to get around
having to cast the pointer before accessing it everytime?

vector<BYTE> vNew;
vNew.resize(256 * 256);

Thanks

There are a few ways to accomplish this, including a class that keeps track
of the type of data it is and allocates appropriately, or templates, or
polymorphism (Pixel as base class, PixelShort or PixelChar as derived
classes), etc...

A vector container, itself, isn't a solution other than storing the data.
You still have to decide what type of data to store.

Hi guys,

If I write a class to do it like posted, how could I keep a list of
them - eventually I want to keep the following:

vector<CPixelContainerClass> vImageStack;

the first image in the stack might have to be allocated as unsigned
char, the second might have to be allocated as unsigned short.
 
D

David Harmon

On 30 Aug 2006 16:44:23 -0700 in comp.lang.c++, "markww"
If I write a class to do it like posted, how could I keep a list of
them - eventually I want to keep the following:

vector<CPixelContainerClass> vImageStack;

First let me say that I agree with several other posters -- if you
have those casts scattered all over your code, and deal with both
shorts and chars all over your code, your life will be miserable.
You really need to encapsulate all that into a family of classes.

Your base class would probably have something like virtual
get_pixel() and put_pixel() functions, and derived classes would
convert a common pixel representation to and from whatever more
compact form they were using internally in the implementation of
those functions.

So your vector will probably know only about an abstract base class.
And that means it has to store some kind of pointer, so that it can
point to instances of your derived classes.

The vector can store raw pointers, but that means _all_ the memory
management is up to you. Or the vector can store some kind of smart
pointer class such as boost::scoped_ptr (http://boost.org) so that
it can clean up for itself automatically.
 
P

Pete Becker

David said:
The vector can store raw pointers, but that means _all_ the memory
management is up to you. Or the vector can store some kind of smart
pointer class such as boost::scoped_ptr (http://boost.org) so that
it can clean up for itself automatically.

Or std::tr1::shared_ptr.
 
D

David Harmon

The vector can store raw pointers, but that means _all_ the memory
management is up to you. Or the vector can store some kind of smart
pointer class such as boost::scoped_ptr (http://boost.org) so that
it can clean up for itself automatically.

Or std::tr1::shared_ptr.[/QUOTE]

But in this case it does not appear that sharing is needed.
Is there a tr1 scoped_ptr? Is tr1 a sports car from Triumph?
I know I can get a boost for free, but probably not a sports car.
 
J

Jim Langston

markww said:
Jim said:
markww said:
Hi,

I want to use the vector container class to store pixel data. Currently
I have some memory allocated using c++'s new operator. I allocate the
memory differently based on if the pixel type is unsigned char or
unsigned short like this:

int nPixelType = ?; // unsigned short, or unsigned char?
BYTE *pByte = NULL;
switch (nPixelType) {
case UNSIGNED_SHORT:
pBtye = (BYTE *)new unsigned char[256 * 256];
break;

case UNSIGNED_CHAR:
pByte = (BYTE *)new unsigned char[256 * 256];
break;
}

Then I whenever I was doing image processing tasks, I would create a
temporary pointer to the data and cast it to the correct type:

unsigned short *p = (unsigned short *)pByte;
or
unsigned char *p = (unsigned char *)pByte;

Now it was suggested to me that I stop using raw pointers like this in
favor of vector containers. Can I translate the above into a vector of
BYTE and accomplish the same thing? Would it be possible to get around
having to cast the pointer before accessing it everytime?

vector<BYTE> vNew;
vNew.resize(256 * 256);

Thanks

There are a few ways to accomplish this, including a class that keeps
track
of the type of data it is and allocates appropriately, or templates, or
polymorphism (Pixel as base class, PixelShort or PixelChar as derived
classes), etc...

A vector container, itself, isn't a solution other than storing the data.
You still have to decide what type of data to store.

Hi guys,

If I write a class to do it like posted, how could I keep a list of
them - eventually I want to keep the following:

vector<CPixelContainerClass> vImageStack;

the first image in the stack might have to be allocated as unsigned
char, the second might have to be allocated as unsigned short.

Well, if you want to store them that way, instead of pointers, then you
don't want to use polymorphism. So basically, just have your
CPixelContainerClass keep track of how it's stored.

enum PixelTypes
{
ShortPixels,
CharPixels
};

class CPixelContainerClass
{
public:
CPixelContainerClass( const PixelTypes pt ): PixelType_( pt ),
ShortPixel_( NULL ), CharPixel_( NULL ) {}
~CPixelContainerClass() { delete[] ShortPixel_; delete[] CharPixel_; }
PixelTypes Type() const { return PixelType_; }
void LoadData( char* Data, const int Size )
{
if ( PixelType_ == ShortPixels )
// Allocate and load data into ShortPixel_
else
// Allocate and load data into CharPixel_
}
private:
PixelTypes PixelType_;
unsigned short* ShortPixel_;
unsigned char* CharPixel_;
}

There are other ways to design this class, and maybe better ways, but you
should get the idea. You are encapsulating the data, so any class that uses
CPixelContainerClass shouldn't have to care if the data is stored in
unsigned short or unsigned char, let the class handle that trivia. If, at
some point, you do need to know outside the class, use .Type() to see how
it's stored.

This is not polymorphism, and I really don't think polymorphism is the way
to go. Personally, I might just use one pointer (unsigned char* as it's
only 1 byte) for all the data and just treat it different if PixelType_ ==
ShortPixels.

The advantage of this is you just have your vector of CPixelContainerClass
and it doesn't matter what type the data is inside of it, they are just
isntances of the same class.

I can think of off the top of my head 3 or 4 other ways to do the same
thing, such as having the pixel data itself stored in another class of
different types, etc...

It's hard to say without knowing your design constraints the best way to do
it.
 
D

David Harmon

On Thu, 31 Aug 2006 06:51:43 -0400 in comp.lang.c++, Pete Becker
TR1 is the first Technical Report on C++ Library Extensions.

So I have to buy _The C++ Standard Library Extensions: a Tutorial
and Reference_ in order to find out if it has scoped_ptr?
 
J

Jens Theisen

David said:
But in this case it does not appear that sharing is needed.

It's needed if you want to put it in a vector (CopyConstructible and
CopyAssignable requirements).

Jens
 
N

Noah Roberts

David said:
Or std::tr1::shared_ptr.

But in this case it does not appear that sharing is needed.
Is there a tr1 scoped_ptr?
No.

> Is tr1 a sports car from Triumph?[/QUOTE]

No, but Pete Becker works for Dinkumware, the only company you can get
the complete TR1 from. He also wrote what seems to be the only book on
the subject besides the TR1 document itself. However, you don't need
to buy either to get std::tr1::shared_ptr.
I know I can get a boost for free, but probably not a sports car.

std::tr1::shared_ptr is the same class as boost::shared_ptr. Much of
TR1 is from boost and can be downloaded with boost. Boost includes a
tr1 header implementation that includes the right classes and places
them in std::tr1. Things you don't get are the math functions and
according to the boost help the unordered associative containers.
 
D

David Harmon

But in this case it does not appear that sharing is needed.

It's needed if you want to put it in a vector (CopyConstructible and
CopyAssignable requirements).[/QUOTE]

Thanks for the correction. I was thinking the vector owns the whole
thing, so no need, but clearly that's not good enough when the
vector has to copy the pointer.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top