Changing type at runtime for image acquisition

D

Davide

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
 
J

James Kuyper

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;
}
 
D

Davide

James Kuyper wrote:

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
 
J

James Kuyper

James Kuyper wrote:

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*
 
K

Kaz Kylheku

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;
}
 
J

James Kuyper

James Kuyper wrote:

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.
 
B

BartC

Davide said:
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).
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top