After describing the new image structures, I wrote that a C++ overlay may be nice, mainly for functions overloading. It would also make sense when reading an image from a file; think about a TIFF file; is it binary? 8bit? 16bit? You can't know fore sure before you actually open the file.
Actually, it is possible to make some sort of overloading in C, with unions. It's not elegant code, and may not be transparent for the user, but it's possible, and worth trying. I tried it.
image
So, here is the generic image structure; I don't know if it will
stay in the code, we'll see.
This structure is defined in [[mw4f lib/src/image.h]], with the implementation details in [[mw4f lib/src/image.c]] :
/**
* xx_image union
*/
typedef union u_xximage
{
mw_u8image u8; /**< uint8 image */
mw_u16image u16; /**< uint16 image */
mw_f32image f32; /**< uint32 image */
} xximage;
/**
* gray level image
*/
typedef struct s_image
{
char dtype; /**< data type stored */
xximage img; /**< image union, for all supported dtypes */
} mw_image;
/* create an image */
mw_image * mw_new_image(uint16, uint16, char);
/* delete an image */
void mw_del_image(mw_image *);
/* copy an array to an image */
mw_image * mw_setdata_image(mw_image *, const void *);
/* copy an image into an existing one */
mw_image * mw_copy_image(mw_image *, mw_image *);
/* copy an image into a new one */
mw_image * mw_clone_image(mw_image *);
/* get one value of an image */
flt32 mw_getdot_image(mw_image *, uint16, uint16);
/* set one value of an image */
flt32 mw_setdot_image(mw_image *, uint16, uint16, flt32);
/* fill an image */
void * mw_fill_image(mw_image *, flt32);
/* write a text representation of an image to a file */
int32 mw_fwrite_image(FILE *, mw_image *);
/* read a text representation of an image from a file */
mw_image * mw_fread_image(FILE *);
the structure
dtypeis a marker, to know which kind of image we are dealing withimgis an union ofmw_u8imge,mw_u16imageofmw_f32image
That's it. With that, depending on the value of dtype, we'll switch
to the correct functions. Note that it doesn't increase the memory
size, as all the `mw_xximage structures have exactly the same
size. All it takes is, basically, one more allocation test, one
switch () test and one more function call for each mw_xxx_image()
function.
the functions
mw_new_u8image,mw_del_image,mw_{setdata|copy|clone}_imageare the same, nothing changed from the user point of view, except that you choose which kind of data type you want to usemw_{getdot|setdot|fill}_u8imagecan't be identical; in order to provide an unique interface, they take or returnflt32values; an user cast may be required heremw_{fwrite|fread}_u8imagedidn't change; we just embed the type-dependant format with some extra information :
{ "dtype" = "MW_UINT8", "img" = { "ncol" = 42, "nrow" = 42, gray = [ 1, 2, 3, ... ] } }, and we get a all-type image file format.
notes
By the way, all this code compiles perfectly on x86 and x86_64 systems (PC 32 and 64 bits) and HP-PA too; I should be able to test on some other architectures soon.