struct pointer to a 2D array

Discussion in 'C Programming' started by Mark Feller, Jul 12, 2005.

  1. Mark Feller

    Mark Feller Guest

    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.
     
    Mark Feller, Jul 12, 2005
    #1
    1. Advertising

  2. Mark Feller

    Jirka Klaue Guest

    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
     
    Jirka Klaue, Jul 12, 2005
    #2
    1. Advertising

  3. Mark Feller wrote:
    > 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]

    --
    Peter
     
    Peter Nilsson, Jul 12, 2005
    #3
  4. Mark Feller

    Allan Bruce Guest

    "Mark Feller" <> wrote in message
    news:LmQAe.603$...
    >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
     
    Allan Bruce, Jul 12, 2005
    #4
  5. Mark Feller

    Malcolm Guest

    "Mark Feller" <> wrote
    >
    > 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.
     
    Malcolm, Jul 12, 2005
    #5
  6. Mark Feller

    Netocrat Guest

    On Tue, 12 Jul 2005 08:06:32 -0700, Peter Nilsson wrote:

    > Mark Feller wrote:
    >> 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]);
    }
     
    Netocrat, Jul 13, 2005
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fogelklou
    Replies:
    36
    Views:
    1,391
    Chris Fogelklou
    Apr 20, 2004
  2. beetle
    Replies:
    2
    Views:
    913
    beetle
    Jan 25, 2005
  3. Zero
    Replies:
    16
    Views:
    659
    Barry Schwarz
    Nov 19, 2005
  4. Tuan  Bui
    Replies:
    14
    Views:
    477
    it_says_BALLS_on_your forehead
    Jul 29, 2005
  5. aleksa

    Struct pointer vs. struct array pointer

    aleksa, Feb 20, 2013, in forum: C Programming
    Replies:
    16
    Views:
    471
    Shao Miller
    Feb 20, 2013
Loading...

Share This Page