If I make an array like this

GLubyte bufImage[100][100][3];

I can pass bufImage to a function and then get the values using:

r = bufImage[im_x][im_y][0];
g = bufImage[im_x][im_y][1];
b = bufImage[im_x][im_y][2];

However, if I don't know Width and Height at runtime, this does not work. I tried to do this:

GLubyte*** bufImage = new GLubyte**[Width];

	for(unsigned int i = 0; i < Width; ++i)
	{
		bufImage[i] = new GLubyte*[Height];
		for(unsigned int j = 0; j < Height; ++j)
		{
			bufImage[i][j] = new GLubyte[3];
		}
	}

but it crashes when I try to access them. Can someone help me make this 2d array at runtime?

Thanks,
Dave

Recommended Answers

All 7 Replies

Try this:

struct RGB {
    GLubyte r, g, b;
};

RGB **bufImg;

bufImg = new RGB*[height];
for (int i = 0; i < width; ++i)
    bufImg[i] = new RGB[width];

On this line

r = bufImage[im_x][im_y][0];

it says "error: no match for 'operator[]'

Please show the full function in which that occurs. One line out of context can be hard to debug.

I changed the structure. It's not a 3D array anymore, but a 2D array of RGB structures. So you access it like this: r = bufImage[im_x][im_y].r;

nucleon - unfortunately I'd like to keep it in the same structure because I have many other functions that work with this 2d array.

I put together a stand alone example:

#include <iostream>

using namespace std;

void FixedLength();
void VariableLength();

void FillAndRead(unsigned char* buffer, const unsigned int Width, const unsigned int Height);

int main()
{
	FixedLength();
	VariableLength();
	
	return 0;
}

void FillAndRead(unsigned char* buffer, const unsigned int Width, const unsigned int Height)
{
	//fill
	for(unsigned int x = 0; x < Width; x++)
	{
		for(unsigned int y = 0; y < Height; y++)
		{
 			buffer[x][y][0] = 3;
 			buffer[x][y][1] = 4;
 			buffer[x][y][2] = 5;
		}
	}

	//read
	unsigned char r,g,b;
	for(unsigned int x = 0; x < Width; x++)
	{
		cout << endl;
		for(unsigned int y = 0; y < Height; y++)
		{
 			r = buffer[x][y][0];
 			g = buffer[x][y][1];
 			b = buffer[x][y][2];
 			cout << r << " " << g << " " << b << " | ";
		}
	}

	cout << endl;
	
}

void FixedLength()
{
	unsigned int Width = 100;
 	unsigned int Height = 100;
	
	unsigned char buffer[100][100][3];

	FillAndRead(buffer, Width, Height);

}

void VariableLength()
{
	unsigned int Width = 100;
 	unsigned int Height = 100;
 	
	//Want to do this: unsigned char bufImage[Width][Height][3];

 	unsigned char*** buffer = new unsigned char**[Width];

	for(unsigned int i = 0; i < Width; ++i)
	{
		buffer[i] = new unsigned char*[Height];
		for(unsigned int j = 0; j < Height; ++j)
		{
			buffer[i][j] = new unsigned char[3];
		}
	}
	
	FillAndRead(buffer, Width, Height);
}

It doesn't compile.. it has an error
"error: invalid types 'unsigned char[unsigned int]' for array subscript"
on this line

buffer[x][y][0] = 3;

Can you see what I'm trying to do?

You mean 3D array. In that case:

GLubyte ***bufImg;
    bufImg = new GLubyte** [height];
    for (int i = 0; i < height; ++i) {
        bufImg[i] = new GLubyte* [width];
        for (int j = 0; j < 3; ++j)
            bufImg[i][j] = new GLubyte[3];
    }

>Can you see what I'm trying to do?
You're trying to use the same function to properly handle two incompatible types. A three dimensional array is not the same as a pointer to a pointer to a pointer. A template is the ideal solution for this problem, assuming you can restrict yourself to only passing types that match the usage:

template <typename T>
void FillAndRead(T buffer, const unsigned int Width, const unsigned int Height)
{
	//fill
	for(unsigned int x = 0; x < Width; x++)
	{
		for(unsigned int y = 0; y < Height; y++)
		{
 			buffer[x][y][0] = 3;
 			buffer[x][y][1] = 4;
 			buffer[x][y][2] = 5;
		}
	}

	//read
	unsigned char r,g,b;
	for(unsigned int x = 0; x < Width; x++)
	{
		cout << endl;
		for(unsigned int y = 0; y < Height; y++)
		{
 			r = buffer[x][y][0];
 			g = buffer[x][y][1];
 			b = buffer[x][y][2];
 			cout << r << " " << g << " " << b << " | ";
		}
	}

	cout << endl;
}

If you can't use a template for some reason and you're willing to accept greatly broken code (that has a strong tendency to work) and vastly less convenient syntax, you can pun the incompatible types into a straight pointer and calculate the indices manually:

void FillAndRead(unsigned char* buffer, const unsigned int Width, const unsigned int Height)
{
	//fill
	for(unsigned int x = 0; x < Width; x++)
	{
		for(unsigned int y = 0; y < Height; y++)
		{
 			buffer[x * Width + y * Height + 0] = 3;
 			buffer[x * Width + y * Height + 1] = 4;
 			buffer[x * Width + y * Height + 2] = 5;
		}
	}

	//read
	unsigned char r,g,b;
	for(unsigned int x = 0; x < Width; x++)
	{
		cout << endl;
		for(unsigned int y = 0; y < Height; y++)
		{
 			r = buffer[x * Width + y * Height + 0];
 			g = buffer[x * Width + y * Height + 1];
 			b = buffer[x * Width + y * Height + 2];
 			cout << r << " " << g << " " << b << " | ";
		}
	}

	cout << endl;
}

I don't recommend this practice, but it's another way to solve the problem.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.