Changing type at runtime for image acquisition

Discussion in 'C Programming' started by Davide, Nov 21, 2011.

  1. Davide

    Davide Guest

    Dear comp.lang.c,
    I want to allocate a buffer to store 8bit or 16bit integers,
    depending on the color bitdepth of the images I want to capture.
    I allocate this buffer in a thread, so I have something like:

    #define UTYPE __int8
    ..
    ..

    UTYPE *internal_buffer;
    ..
    ..

    unsigned long __stdcall ThreadFunc(void *pContext)
    {
    if (!(internal_buffer = malloc(number_of_frames *
    frame_size_in_bytes))) {
    fprintf(stderr, "Failed to allocate internal memory buffer!\n");
    exit(EXIT_FAILURE);
    }
    return 0;
    }

    Now if I want to switch to a buffer of __int16, is there a way to get it
    using the same function? Is there a way to change the type of the pointer
    internal_buffer to __int16* at runtime? I would need that so i have a:

    __int8 *internal_buffer;

    when i need 8bit color frames, and a:

    __int16 *internal_buffer;

    for 14bit (i.e. 16bit) frames, but I want to use the same variable
    internal_buffer to manipulate my frames. Sorry if I use __int8, __int16,
    __stdcall, but I'm writing this program under win32 and these are microsoft
    reserved keywords.

    thank you
    Davide
     
    Davide, Nov 21, 2011
    #1
    1. Advertising

  2. Davide

    James Kuyper Guest

    On 11/21/2011 02:38 PM, Davide wrote:
    > Dear comp.lang.c,
    > I want to allocate a buffer to store 8bit or 16bit integers,
    > depending on the color bitdepth of the images I want to capture.
    > I allocate this buffer in a thread, so I have something like:
    >
    > #define UTYPE __int8
    > .
    > .
    >
    > UTYPE *internal_buffer;
    > .
    > .
    >
    > unsigned long __stdcall ThreadFunc(void *pContext)
    > {
    > if (!(internal_buffer = malloc(number_of_frames *
    > frame_size_in_bytes))) {
    > fprintf(stderr, "Failed to allocate internal memory buffer!\n");
    > exit(EXIT_FAILURE);
    > }
    > return 0;
    > }
    >
    > Now if I want to switch to a buffer of __int16, is there a way to get it
    > using the same function? Is there a way to change the type of the pointer
    > internal_buffer to __int16* at runtime? I would need that so i have a:
    >
    > __int8 *internal_buffer;
    >
    > when i need 8bit color frames, and a:
    >
    > __int16 *internal_buffer;
    >
    > for 14bit (i.e. 16bit) frames, but I want to use the same variable
    > internal_buffer to manipulate my frames. Sorry if I use __int8, __int16,
    > __stdcall, but I'm writing this program under win32 and these are microsoft
    > reserved keywords.


    You could use void* to store the pointer to the buffer, and convert to
    __int8 or __int16 as needed:

    if(eight_bit)
    n = ((__int8*)internal_buffer)[j];
    else
    n = ((__int16*)internal_buffer)[j];

    In some ways, that would be the cleanest approach. However, if that
    would require you to doing too many explicit conversions, then it might
    be easier to use a union:

    union {
    __int8 *pi8;
    __int16 *pi16;
    } internal_buffer;

    temp = malloc(....;
    if(temp)
    {
    if(eight_bit)
    internal_buffer.pi8 = temp;
    else
    internal_buffer.pi16 = temp;
    }
     
    James Kuyper, Nov 21, 2011
    #2
    1. Advertising

  3. Davide

    Davide Guest

    James Kuyper wrote:

    <snip>
    > You could use void* to store the pointer to the buffer, and convert to
    > __int8 or __int16 as needed:
    >
    > if(eight_bit)
    > n = ((__int8*)internal_buffer)[j];
    > else
    > n = ((__int16*)internal_buffer)[j];
    >
    > In some ways, that would be the cleanest approach. However, if that
    > would require you to doing too many explicit conversions, then it might
    > be easier to use a union:
    >
    > union {
    > __int8 *pi8;
    > __int16 *pi16;
    > } internal_buffer;
    >
    > temp = malloc(....;
    > if(temp)
    > {
    > if(eight_bit)
    > internal_buffer.pi8 = temp;
    > else
    > internal_buffer.pi16 = temp;
    > }


    Thank you very much. I understood your second approach with a union,
    but i have some doubts about the first one. What type should 'n' be?

    thank you
    Davide
     
    Davide, Nov 21, 2011
    #3
  4. Davide

    James Kuyper Guest

    On 11/21/2011 03:32 PM, Davide wrote:
    > James Kuyper wrote:
    >
    > <snip>
    >> You could use void* to store the pointer to the buffer, and convert to

    ^^^^^

    >> __int8 or __int16 as needed:
    >>
    >> if(eight_bit)
    >> n = ((__int8*)internal_buffer)[j];
    >> else
    >> n = ((__int16*)internal_buffer)[j];
    >>
    >> In some ways, that would be the cleanest approach. However, if that
    >> would require you to doing too many explicit conversions, then it might
    >> be easier to use a union:

    ....
    > but i have some doubts about the first one. What type should 'n' be?


    void*
     
    James Kuyper, Nov 21, 2011
    #4
  5. Davide

    Kaz Kylheku Guest

    On 2011-11-21, Davide <> wrote:
    > Dear comp.lang.c,
    > I want to allocate a buffer to store 8bit or 16bit integers,
    > depending on the color bitdepth of the images I want to capture.
    > I allocate this buffer in a thread, so I have something like:


    You're trading abstraction for storage density. How about defining a higher
    abstractio of an image as consisting of pixels in some color space? R G B
    triplets, or whatever.

    You could make a polymorphic type with abstract accessors so that you can
    achieve the storage density also. An 8 bit grayscale image could have
    its pixels stored as byte values ranging from 0 to 255; yet be accessible
    thorugh an interface where these pictures look like RGB triplets.

    You have to think through issues like: if images are mutable object, what
    happens if the program tries to put a red pixel into grayscale image?

    > #define UTYPE __int8
    > .
    > .
    >
    > UTYPE *internal_buffer;
    > .


    Here is a general gist of an idea hinting at a possible structure for a
    solution. Keep in mind that I'm painting in watercolor with a broad brush:

    It might be helpful to look at how some open source software handles images.

    #include <stdlib.h> /* for malloc */


    typedef struct rgba {
    int r, g, b, a;
    } rgba_t;

    struct image_operations {
    /* ... */
    rgba_t (*get_pixel_at)(struct image *, int x, int y);
    /* ... */
    }

    typedef enum image_type { IMG_GS8 /* ... */ } imgtype_t;

    struct abstract_image {
    struct image_operations *ops;
    int width, height;
    imgtype_t type;
    };

    struct gs8_image { /* grayscale 8 bit */
    /* common members from abstract image */
    struct image_operations *ops;
    int width, height;
    enum image_type type;
    /* specific members */
    array_of_bytes_t *data;
    }

    /* ... */

    union image {
    struct abtract image i;
    struct gs8_image image gs8;
    /* ... */
    };

    static rgba_t gs8_get_pixel_at(struct image *img, int x, int y)
    {
    /* check that img->i.type == IMG_GS8 */
    int gs8_pix = array_of_bytes(img->gs8.data, y * img->i.width + x);
    rgba_t ret = { gs8_pix, gs8_pix, gs8_pix, 255 }; /* a == 255 -> opaque */
    return ret;
    }

    static struct image_operations gs8_ops {
    /* ... */
    gs8_get_pixel_at
    /* ... */
    }

    static struct image *make_image(int width, int height, imgtype_t type,
    struct image_operations *ops)
    {
    struct image *img = (struct image *) malloc(sizeof *img);
    if (img) {
    img->ops = ops;
    img->width = width;
    img->height = height;
    img->type = type;
    }
    return img;
    }

    rgba_t *image_get_pixel_at(struct image *image, int x, int y)
    {
    return image->ops->get_pixel_at(image, x, y);
    }

    struct image *make_gs8_image(int width, int height, int fill, int fill_value)
    {
    struct image *img = make_image(width, height, IMG_GS8, &gs8_ops);
    array_of_bytes_t *a = make_array_of_bytes(width * height);

    if (img && a) {
    img->data = a;
    if (fill)
    fill_array_of_bytes(a, fill_value);

    return img;
    }

    free_image(img);
    free_array_of_bytes(a);
    return 0;
    }
     
    Kaz Kylheku, Nov 21, 2011
    #5
  6. Davide

    James Kuyper Guest

    On 11/21/2011 03:32 PM, Davide wrote:
    > James Kuyper wrote:
    >
    > <snip>
    >> You could use void* to store the pointer to the buffer, and convert to
    >> __int8 or __int16 as needed:
    >>
    >> if(eight_bit)
    >> n = ((__int8*)internal_buffer)[j];
    >> else
    >> n = ((__int16*)internal_buffer)[j];

    ....
    > Thank you very much. I understood your second approach with a union,
    > but i have some doubts about the first one. What type should 'n' be?


    It could be __int16, but int_fast16_t is more precisely what I'd want to
    use. However, I'd normally translate 'int_fast16_t' to 'int', simply
    because it's easier to type, unless speed is very important.
     
    James Kuyper, Nov 21, 2011
    #6
  7. Davide

    BartC Guest

    "Davide" <> wrote in message
    news:KMxyq.101324$...
    > Dear comp.lang.c,
    > I want to allocate a buffer to store 8bit or 16bit integers,
    > depending on the color bitdepth of the images I want to capture.
    > I allocate this buffer in a thread, so I have something like:
    >
    > #define UTYPE __int8
    > .
    > .
    >
    > UTYPE *internal_buffer;
    > .
    > .
    >
    > unsigned long __stdcall ThreadFunc(void *pContext)
    > {
    > if (!(internal_buffer = malloc(number_of_frames * frame_size_in_bytes)))
    > {


    If 'frame_size_in_bytes' contains the correct size for the image depth in
    use, this same function will work for both depths.

    However, when you dereference 'internal_buffer', you have to use the correct
    cast to make it point to a 8-bit or 16-bit target:

    (__int8*)internal_buffer
    (__int16*)internal_buffer

    C is statically typed so it's not possible to (easily) switch types at
    runtime; it's necessary to keep track of these things yourself.

    Depending on what you plan to do with these buffers, it might be feasible to
    just write two sets of functions, one for 8-bit and one for 16-bit, and
    switch function pointers to point to one or the other set. (This might be
    result in more streamlined code than having to check for colour depth at
    every pixel.)

    Although, if the colour depth forms part of the interface between these
    functions and the rest of the application, the problem won't entirely go
    away.

    But there are many ways of dealing with this sort of thing (for example, KK
    suggested - I think - using a single representation of the image, so that an
    8-bit image is converted to 16-bit, or just convert everything to 24/32-bit
    colour, if this is viable).

    --
    Bart C
     
    BartC, Nov 21, 2011
    #7
    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. jude
    Replies:
    7
    Views:
    960
    Brock Allen
    Mar 15, 2005
  2. Peter Szymanski
    Replies:
    0
    Views:
    870
    Peter Szymanski
    Jul 9, 2003
  3. yang su
    Replies:
    11
    Views:
    591
    Rolf Magnus
    Aug 10, 2004
  4. Jack
    Replies:
    0
    Views:
    245
  5. StepH
    Replies:
    3
    Views:
    453
    Alex Verstraeten
    May 17, 2005
Loading...

Share This Page