Add DCP calibration files for sensors

Read .dcp files stored in the same directory as the camera configuration
files and copy over the calibration curves into the DNG files after
taking a picture.
This commit is contained in:
Martijn Braam
2023-03-07 18:42:48 +01:00
parent 92f5270f87
commit b5161db18e
10 changed files with 397 additions and 3 deletions

149
src/dcp.c Normal file
View File

@@ -0,0 +1,149 @@
#include "dcp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned int
get_int32(const unsigned char *buffer, size_t offset)
{
return (buffer[offset + 3] << 24) | (buffer[offset + 2] << 16) |
(buffer[offset + 1] << 8) | (buffer[offset]);
}
unsigned int
get_int16(const unsigned char *buffer, size_t offset)
{
return (buffer[offset + 1] << 8) | (buffer[offset]);
}
float
get_float(unsigned char *buffer, size_t offset)
{
float f;
unsigned char b[] = { buffer[offset + 0],
buffer[offset + 1],
buffer[offset + 2],
buffer[offset + 3] };
memcpy(&f, &b, sizeof(f));
return f;
}
float
get_srational(unsigned char *buffer, size_t offset)
{
int a = (int)get_int32(buffer, offset);
int b = (int)get_int32(buffer, offset + 4);
return (float)a / (float)b;
}
struct MPCameraCalibration
parse_calibration_file(const char *path)
{
FILE *fp;
size_t size;
unsigned char *buffer;
struct MPCameraCalibration result = { 0 };
fp = fopen(path, "rb");
if (fp == NULL) {
return result;
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
buffer = malloc(sizeof(char) * size);
size_t ret = fread(buffer, 1, size, fp);
if (ret != size) {
return result;
}
fclose(fp);
if (buffer[0] != 'I' || buffer[1] != 'I') {
fprintf(stderr, "Magic for DCP file incorrect\n");
return result;
}
if (buffer[2] != 0x52 || buffer[3] != 0x43) {
fprintf(stderr, "Invalid DCP version\n");
return result;
}
unsigned int ifd0 = get_int32(buffer, 4);
unsigned int tag_count = get_int16(buffer, ifd0);
for (int i = 0; i < tag_count; i++) {
int tag_offset = ifd0 + 2 + (i * 12);
unsigned int tag = get_int16(buffer, tag_offset + 0);
unsigned int type = get_int16(buffer, tag_offset + 2);
unsigned int count = get_int32(buffer, tag_offset + 4);
unsigned int offset = get_int32(buffer, tag_offset + 8);
switch (tag) {
case DCPTAG_COLOR_MATRIX_1:
for (int j = 0; j < 9; j++) {
float point =
get_srational(buffer, offset + (j * 8));
result.color_matrix_1[j] = point;
}
break;
case DCPTAG_COLOR_MATRIX_2:
for (int j = 0; j < 9; j++) {
float point =
get_srational(buffer, offset + (j * 8));
result.color_matrix_2[j] = point;
}
break;
case DCPTAG_FORWARD_MATRIX_1:
for (int j = 0; j < 9; j++) {
float point =
get_srational(buffer, offset + (j * 8));
result.forward_matrix_1[j] = point;
}
break;
case DCPTAG_FORWARD_MATRIX_2:
for (int j = 0; j < 9; j++) {
float point =
get_srational(buffer, offset + (j * 8));
result.forward_matrix_2[j] = point;
}
break;
case DCPTAG_CALIBRATION_ILLUMINANT_1:
result.illuminant_1 = offset;
break;
case DCPTAG_CALIBRATION_ILLUMINANT_2:
result.illuminant_2 = offset;
break;
case DCPTAG_PROFILE_TONE_CURVE:
result.tone_curve = malloc(count * sizeof(float));
result.tone_curve_length = count;
for (int j = 0; j < count; j++) {
result.tone_curve[j] =
get_float(buffer, offset + (j * 4));
}
break;
case DCPTAG_PROFILE_HUE_SAT_MAP_DIMS:
result.hue_sat_map_dims[0] = get_int32(buffer, offset);
result.hue_sat_map_dims[1] = get_int32(buffer, offset + 4);
result.hue_sat_map_dims[2] = get_int32(buffer, offset + 8);
break;
case DCPTAG_PROFILE_HUE_SAT_MAP_DATA_1:
result.hue_sat_map_data_1 = malloc(count * sizeof(float));
for (int j = 0; j < count; j++) {
result.hue_sat_map_data_1[j] =
get_float(buffer, offset + (j * 4));
}
break;
case DCPTAG_PROFILE_HUE_SAT_MAP_DATA_2:
result.hue_sat_map_data_2 = malloc(count * sizeof(float));
for (int j = 0; j < count; j++) {
result.hue_sat_map_data_2[j] =
get_float(buffer, offset + (j * 4));
}
break;
}
}
return result;
}