struct pointer to a 2D array

M

Mark Feller

I have an embedded application where malloc( ) is not available. So I
declare images as globals, but want to be able to pass image information
including a pointer in a structure, as in the following:

unsigned short image[640][480];

typedef struct{
unsigned short** img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

int foo(IMAGE* x);

The "unsigned short**" is the wrong way to do this, but I am still looking
for the correct way. Thanks for any advice.
 
J

Jirka Klaue

Mark Feller:
unsigned short image[640][480];

typedef struct{
unsigned short** img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE; ....
The "unsigned short**" is the wrong way to do this, but I am still
looking for the correct way.

typedef struct{
unsigned short (*img_ptr)[480];
unsigned short img_width;
unsigned short img_height;
} IMAGE;

Jirka
 
P

Peter Nilsson

Mark said:
I have an embedded application where malloc( ) is not available.
So I declare images as globals, but want to be able to pass image
information including a pointer in a structure, as in the following:

unsigned short image[640][480];

typedef struct{
unsigned short** img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

int foo(IMAGE* x);

The "unsigned short**" is the wrong way to do this, but I am still
looking for the correct way.

I'd say...

unsigned short (*img_ptr)[480];

....but since you include img_width and img_height, I'm guessing you
may have more than one image, and those images may have different
dimensions.

If so, then you need to resort to the more primitive...

typedef struct{
unsigned short *img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

unsigned short image1[640][480];
unsigned short image2[320][240];

IMAGE IMAGE1 = { &image1[0][0], 640, 480 };
IMAGE IMAGE2 = { &image2[0][0], 320, 240 };

In which case, foo will have to traverse the image rows 'manually'...

int foo(IMAGE* x)
{
unsigned short row, col;
size_t pixel = 0;
for (row = 0; row < x->img_height; row++)
for (col = 0; col < x->img_width ; col++, pixel++)
{
/* x->image[pixel] is pixel at (col, row) */
}
}

In other words the pixel at (col, row) is...

x->image[col + (size_t) row * x->img_width]
 
A

Allan Bruce

Mark Feller said:
I have an embedded application where malloc( ) is not available. So I
declare images as globals, but want to be able to pass image information
including a pointer in a structure, as in the following:

unsigned short image[640][480];

typedef struct{
unsigned short** img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

int foo(IMAGE* x);

The "unsigned short**" is the wrong way to do this, but I am still looking
for the correct way. Thanks for any advice.

Something like this would offer multiple resolution images:

#define MAX_X_RES 1024
#define MAX_Y_RES 768

typedef struct{
unsigned short img_data[MAX_X_RES * MAX_Y_RES];
unsigned short img_width;
unsigned short img_height;
} IMAGE;

unsigned short getPixel(unsigned x, unsigned y, IMAGE *image)
{
return image->img_data[y*image->img_width + x];
}

void setPixel(unsigned x, unsigned y, unsigned short pixelData, IMAGE
*image)
{
image->img_data[y*image->img_width + x] = pixelData;
}

HTH
Allan
 
M

Malcolm

Mark Feller said:
unsigned short image[640][480];

typedef struct{
unsigned short** img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

int foo(IMAGE* x);

The "unsigned short**" is the wrong way to do this, but I am still looking
for the correct way. Thanks for any advice.
Make it an unsigned short *.

Point it at a buffer in global memory, then calculate the x y coordinates by
"hand" in your drawing functions, writing them so that they can accept an
image of any dimensions.
 
N

Netocrat

Mark said:
I have an embedded application where malloc( ) is not available. So I
declare images as globals, but want to be able to pass image information
including a pointer in a structure, as in the following:

unsigned short image[640][480];

typedef struct{
unsigned short** img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

int foo(IMAGE* x);

The "unsigned short**" is the wrong way to do this, but I am still
looking for the correct way.

I'd say...

unsigned short (*img_ptr)[480];

...but since you include img_width and img_height, I'm guessing you may
have more than one image, and those images may have different dimensions.

If so, then you need to resort to the more primitive...

typedef struct{
unsigned short *img_ptr;
unsigned short img_width;
unsigned short img_height;
} IMAGE;

unsigned short image1[640][480];
unsigned short image2[320][240];

IMAGE IMAGE1 = { &image1[0][0], 640, 480 }; IMAGE IMAGE2 = {
&image2[0][0], 320, 240 };

In which case, foo will have to traverse the image rows 'manually'...

int foo(IMAGE* x)
{
unsigned short row, col;
size_t pixel = 0;
for (row = 0; row < x->img_height; row++) for (col = 0; col <
x->img_width ; col++, pixel++) {
/* x->image[pixel] is pixel at (col, row) */
}
}
}

That's a good technique if you are limited to C90. I noticed a couple of
semantic problems with your code though. The loop ordering is inverted
since row varies fastest (your code stores the second dimension into the
img_height member so semantically row indexes the second dimension).
In other words the pixel at (col, row) is...

x->image[col + (size_t) row * x->img_width]

That should be:

x->image[row + (size_t) col * x->img_height]

This is because the fastest varying dimension is the second dimension
(row) so it should not be multiplied by anything, and the first dimension
(col) which varies slowest can be thought of as representing the number of
fully completed 2nd dimensions (rows), so it should be multiplied by the
number of elements in each 2nd dimension (row), and that number of
elements is stored in x->img_height.

What I want to suggest is that if the OP has access to a C99 compatible
compiler or one that otherwise lets you specify an array dimension at
runtime, he could modify your foo function to this:

void foo(IMAGE* x)
{
unsigned short row, col;
unsigned short (*image)[x->img_height] =
(unsigned short(*)[x->img_height])x->img_ptr;

/* Now you can access the image array stored in x->img_ptr as
* image[col][row]; abeit without bounds checking on the first dimension
*/

for (col = 0; col < x->img_width ; col++)
for (row = 0; row < x->img_height; row++)
printf("image[%hu][%hu] == %hu\n", col, row, image[col][row]);
}
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top