Use calibration for preview

This commit is contained in:
Martijn Braam
2023-07-23 16:29:59 +02:00
parent 6e3f592b08
commit e9681e1eea
7 changed files with 112 additions and 23 deletions

View File

@@ -4,6 +4,7 @@ precision highp float;
uniform sampler2D texture;
uniform mat3 color_matrix;
uniform float inv_gamma;
#ifdef BITS_10
uniform float row_length;
uniform float padding_ratio;
@@ -62,13 +63,13 @@ main()
// should be an uniform
vec3 corrected = color - 0.02;
#if defined(COLORSPACE_RAW)
/*
// Fast SRGB estimate. See https://mimosa-pudica.net/fast-gamma/
vec3 srgb_color =
vec3 gamma_color =
(vec3(1.138) * inversesqrt(corrected) - vec3(0.138)) * corrected;
*/
color = color * color_matrix;
gl_FragColor = vec4(srgb_color, 1);
#elif defined(COLORSPACE_SRGB)
gl_FragColor = vec4(color, 1);
#endif
vec3 gamma_color = pow(color, vec3(inv_gamma));
gl_FragColor = vec4(gamma_color, 1);
}

View File

@@ -1,8 +1,10 @@
#include "dcp.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned int
get_int32(const unsigned char *buffer, size_t offset)
@@ -147,3 +149,63 @@ parse_calibration_file(const char *path)
return result;
}
bool
find_calibration_by_model(char *conffile, char *model, const char *sensor)
{
// Check config/%model,%sensor.dcp in the current working directory
sprintf(conffile, "config/%s,%s.dcp", model, sensor);
if (access(conffile, F_OK) != -1) {
printf("Found calibration file at %s\n", conffile);
return true;
}
// Check user overridden /etc/megapixels/config/%model,%sensor.dcp
sprintf(conffile,
"%s/megapixels/config/%s,%s.dcp",
SYSCONFDIR,
model,
sensor);
if (access(conffile, F_OK) != -1) {
printf("Found calibration file at %s\n", conffile);
return true;
}
// Check packaged /usr/share/megapixels/config/%model,%sensor.ini
sprintf(conffile, "%s/megapixels/config/%s,%s.dcp", DATADIR, model, sensor);
if (access(conffile, F_OK) != -1) {
printf("Found calibration file at %s\n", conffile);
return true;
}
printf("No calibration found for %s,%s\n", model, sensor);
return false;
}
bool
find_calibration(char *conffile, const char *sensor)
{
char model[512];
FILE *fp;
if (access("/proc/device-tree/compatible", F_OK) == -1) {
return false;
}
fp = fopen("/proc/device-tree/compatible", "r");
char *modelptr = model;
while (1) {
int c = fgetc(fp);
if (c == EOF) {
*(modelptr) = '\0';
return find_calibration_by_model(conffile, model, sensor);
}
*(modelptr++) = (char)c;
if (c == 0) {
bool res =
find_calibration_by_model(conffile, model, sensor);
if (res) {
return true;
}
modelptr = model;
}
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <stdbool.h>
#include <stdio.h>
struct MPCameraCalibration {
@@ -28,3 +29,5 @@ struct MPCameraCalibration {
#define DCPTAG_FORWARD_MATRIX_2 50965
struct MPCameraCalibration parse_calibration_file(const char *path);
bool find_calibration(char *conffile, const char *sensor);

View File

@@ -1,6 +1,7 @@
#include "gles2_debayer.h"
#include "camera.h"
#include "dcp.h"
#include "gl_util.h"
#include <stdlib.h>
@@ -18,12 +19,13 @@ struct _GLES2Debayer {
GLuint uniform_texture;
GLuint uniform_color_matrix;
GLuint uniform_row_length;
GLuint uniform_inv_gamma;
GLuint quad;
};
GLES2Debayer *
gles2_debayer_new(int format, int xfer)
gles2_debayer_new(int format)
{
uint32_t pixfmt = libmegapixels_format_to_v4l_pixfmt(format);
if (pixfmt != V4L2_PIX_FMT_SBGGR8 && pixfmt != V4L2_PIX_FMT_SGBRG8 &&
@@ -37,14 +39,12 @@ gles2_debayer_new(int format, int xfer)
glGenFramebuffers(1, &frame_buffer);
check_gl();
char format_def[96];
bool is_srgb = xfer == LIBMEGAPIXELS_XFER_SRGB;
char format_def[64];
snprintf(format_def,
96,
"#define CFA_%s\n#define BITS_%d\n#define COLORSPACE_%s\n",
64,
"#define CFA_%s\n#define BITS_%d\n",
libmegapixels_format_cfa(format),
libmegapixels_format_bits_per_pixel(format),
is_srgb ? "SRGB" : "RAW");
libmegapixels_format_bits_per_pixel(format));
const GLchar *def[1] = { format_def };
@@ -77,6 +77,7 @@ gles2_debayer_new(int format, int xfer)
self->uniform_texture = glGetUniformLocation(self->program, "texture");
self->uniform_color_matrix =
glGetUniformLocation(self->program, "color_matrix");
self->uniform_inv_gamma = glGetUniformLocation(self->program, "inv_gamma");
if (libmegapixels_format_bits_per_pixel(self->format) == 10)
self->uniform_row_length =
glGetUniformLocation(self->program, "row_length");
@@ -115,8 +116,7 @@ gles2_debayer_configure(GLES2Debayer *self,
const uint32_t src_height,
const uint32_t rotation,
const bool mirrored,
const float *colormatrix,
const uint8_t blacklevel)
struct MPCameraCalibration calibration)
{
glViewport(0, 0, (int)dst_width, (int)dst_height);
check_gl();
@@ -142,11 +142,21 @@ gles2_debayer_configure(GLES2Debayer *self,
glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y);
check_gl();
if (colormatrix) {
float gamma = 1.0f;
for (int i = 0; i < calibration.tone_curve_length * 2; i += 2) {
float g = calibration.tone_curve[i + 1] / calibration.tone_curve[i];
if (g > gamma) {
gamma = g;
}
}
glUniform1f(self->uniform_inv_gamma, 1.0f / gamma);
if (calibration.color_matrix_1[0]) {
GLfloat transposed[9];
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
transposed[i + j * 3] = colormatrix[j + i * 3];
transposed[i + j * 3] =
calibration.color_matrix_1[j + i * 3];
glUniformMatrix3fv(
self->uniform_color_matrix, 1, GL_FALSE, transposed);

View File

@@ -1,11 +1,13 @@
#include "camera.h"
#include "dcp.h"
#include "gl_util.h"
#include <assert.h>
#include <stdio.h>
typedef struct _GLES2Debayer GLES2Debayer;
GLES2Debayer *gles2_debayer_new(int format, int xfer);
GLES2Debayer *gles2_debayer_new(int format);
void gles2_debayer_free(GLES2Debayer *self);
void gles2_debayer_use(GLES2Debayer *self);
@@ -17,7 +19,6 @@ void gles2_debayer_configure(GLES2Debayer *self,
const uint32_t src_height,
const uint32_t rotation,
const bool mirrored,
const float *colormatrix,
const uint8_t blacklevel);
struct MPCameraCalibration calibration);
void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id);

View File

@@ -927,7 +927,7 @@ on_output_changed(bool format_changed)
if (gles2_debayer)
gles2_debayer_free(gles2_debayer);
gles2_debayer = gles2_debayer_new(state_proc.mode->format, state_proc.mode->xfer);
gles2_debayer = gles2_debayer_new(state_proc.mode->format);
check_gl();
gles2_debayer_use(gles2_debayer);
@@ -940,8 +940,7 @@ on_output_changed(bool format_changed)
state_proc.mode->height,
state_proc.mode->rotation,
0,
NULL,
0);
state_proc.calibration);
}
static int
@@ -954,6 +953,7 @@ mod(int a, int b)
static void
update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
{
bool camera_changed = state_proc.camera != new_state->camera;
state_proc.configuration = new_state->configuration;
state_proc.camera = new_state->camera;
@@ -1008,6 +1008,15 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
on_output_changed(format_changed);
}
if (camera_changed) {
char *cf;
if (find_calibration(cf, state_proc.camera->name)) {
state_proc.calibration = parse_calibration_file(cf);
} else {
printf("No calibration for %s\n", state_proc.camera->name);
}
}
mp_state_main new_main = {
.camera = pr_camera,
.has_auto_focus_continuous = false,

View File

@@ -1,4 +1,5 @@
#pragma once
#include "dcp.h"
#include <libmegapixels.h>
#include <stdbool.h>
@@ -91,4 +92,6 @@ typedef struct state_proc {
controlstate gain;
controlstate exposure;
controlstate focus;
struct MPCameraCalibration calibration;
} mp_state_proc;