To understand the RAW footer you need to look at the struct definitions. To write the data to the file we simply dump the struct's in memory representation to file.
typedef struct
{
unsigned char magic[4];
unsigned short xRes;
unsigned short yRes;
unsigned int frameSize;
unsigned int frameCount;
unsigned int frameSkip;
unsigned int sourceFpsx1000;
unsigned int reserved3;
unsigned int reserved4;
struct raw_info raw_info;
} lv_rec_file_footer_t;
Notice it references struct raw_info. So basically just insert raw_info struct at the end:
struct raw_info {
uint32_t api_version; // increase this when changing the structure
#if INTPTR_MAX == INT32_MAX // only works on 32-bit systems
void* buffer; // points to image data
#else
uint32_t do_not_use_this; // this can't work on 64-bit systems
#endif
int32_t height, width, pitch;
int32_t frame_size;
int32_t bits_per_pixel; // 14
int32_t black_level; // autodetected
int32_t white_level; // somewhere around 13000 - 16000, varies with camera, settings etc
// would be best to autodetect it, but we can't do this reliably yet
union // DNG JPEG info
{
struct
{
int32_t x, y; // DNG JPEG top left corner
int32_t width, height; // DNG JPEG size
} jpeg;
struct
{
int32_t origin[2];
int32_t size[2];
} crop;
};
union // DNG active sensor area (Y1, X1, Y2, X2)
{
struct
{
int32_t y1, x1, y2, x2;
} active_area;
int32_t dng_active_area[4];
};
int32_t exposure_bias[2]; // DNG Exposure Bias (idk what's that)
int32_t cfa_pattern; // stick to 0x02010100 (RGBG) if you can
int32_t calibration_illuminant1;
int32_t color_matrix1[18]; // DNG Color Matrix
int32_t dynamic_range; // EV x100, from analyzing black level and noise (very close to DxO)
};
Each field in the struct is stored one after another, and each field's size depends on the data type, so here's the sizes you need to know:
int, unsigned int, or int32_t: 4 bytes
short or unsigned short: 2 bytes
int32_t array[n]: 4 * n bytes
char array[n]: n bytes
a union is sort of like saying a particular memory location can have different names and data types that use up the same space. To simply things lets just leave out the unneeded extra interpretations, and merge these two definitions in the final resulting definition:
typedef struct
{
unsigned char magic[4];
unsigned short xRes;
unsigned short yRes;
unsigned int frameSize;
unsigned int frameCount;
unsigned int frameSkip;
unsigned int sourceFpsx1000;
unsigned int reserved3;
unsigned int reserved4;
uint32_t api_version; // increase this when changing the structure
uint32_t do_not_use_this;
int32_t height, width, pitch;
int32_t frame_size;
int32_t bits_per_pixel; // 14
int32_t black_level; // autodetected
int32_t white_level; // somewhere around 13000 - 16000, varies with camera, settings etc
int32_t jpeg.x;
int32_t jpeg.y; // DNG JPEG top left corner
int32_t jpeg.width;
int32_t jpeg.height;
int32_t active_area .y1;
int32_t active_area x1;
int32_t y2;
int32_t x2;
int32_t exposure_bias[2]; // DNG Exposure Bias (idk what's that)
int32_t cfa_pattern; // stick to 0x02010100 (RGBG) if you can
int32_t calibration_illuminant1;
int32_t color_matrix1[18]; // DNG Color Matrix
int32_t dynamic_range; // EV x100, from analyzing black level and noise (very close to DxO)
};
So, the first 4 bytes will be 'magic' (an identifier) and they are supposed to be set to "RAWM"
next is 2 bytes xRes, and 2 bytes yRes, 4 bytes frameCount, and so on and so fort.
It's important to note that the data is little endian, which means the bytes come in the backwards order that would probably make sense to you. The LSB is first. So a 4 byte int that appears in the file like: 0x010203040 that value is actually: 0x40302010 = 1076895760. Your hex editor probably has an option to display the little endian value of whatever you have selected.
MLV works the same way except the data starts at the beginning of the file. See mlv.h for the struct definitions.[/code]