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:
149
src/dcp.c
Normal file
149
src/dcp.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user