Use calibration for preview
This commit is contained in:
@@ -4,6 +4,7 @@ precision highp float;
|
|||||||
|
|
||||||
uniform sampler2D texture;
|
uniform sampler2D texture;
|
||||||
uniform mat3 color_matrix;
|
uniform mat3 color_matrix;
|
||||||
|
uniform float inv_gamma;
|
||||||
#ifdef BITS_10
|
#ifdef BITS_10
|
||||||
uniform float row_length;
|
uniform float row_length;
|
||||||
uniform float padding_ratio;
|
uniform float padding_ratio;
|
||||||
@@ -62,13 +63,13 @@ main()
|
|||||||
// should be an uniform
|
// should be an uniform
|
||||||
vec3 corrected = color - 0.02;
|
vec3 corrected = color - 0.02;
|
||||||
|
|
||||||
#if defined(COLORSPACE_RAW)
|
/*
|
||||||
// Fast SRGB estimate. See https://mimosa-pudica.net/fast-gamma/
|
// 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;
|
(vec3(1.138) * inversesqrt(corrected) - vec3(0.138)) * corrected;
|
||||||
|
*/
|
||||||
|
color = color * color_matrix;
|
||||||
|
|
||||||
gl_FragColor = vec4(srgb_color, 1);
|
vec3 gamma_color = pow(color, vec3(inv_gamma));
|
||||||
#elif defined(COLORSPACE_SRGB)
|
gl_FragColor = vec4(gamma_color, 1);
|
||||||
gl_FragColor = vec4(color, 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
62
src/dcp.c
62
src/dcp.c
@@ -1,8 +1,10 @@
|
|||||||
#include "dcp.h"
|
#include "dcp.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
get_int32(const unsigned char *buffer, size_t offset)
|
get_int32(const unsigned char *buffer, size_t offset)
|
||||||
@@ -147,3 +149,63 @@ parse_calibration_file(const char *path)
|
|||||||
|
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct MPCameraCalibration {
|
struct MPCameraCalibration {
|
||||||
@@ -28,3 +29,5 @@ struct MPCameraCalibration {
|
|||||||
#define DCPTAG_FORWARD_MATRIX_2 50965
|
#define DCPTAG_FORWARD_MATRIX_2 50965
|
||||||
|
|
||||||
struct MPCameraCalibration parse_calibration_file(const char *path);
|
struct MPCameraCalibration parse_calibration_file(const char *path);
|
||||||
|
|
||||||
|
bool find_calibration(char *conffile, const char *sensor);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "gles2_debayer.h"
|
#include "gles2_debayer.h"
|
||||||
|
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
#include "dcp.h"
|
||||||
#include "gl_util.h"
|
#include "gl_util.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -18,12 +19,13 @@ struct _GLES2Debayer {
|
|||||||
GLuint uniform_texture;
|
GLuint uniform_texture;
|
||||||
GLuint uniform_color_matrix;
|
GLuint uniform_color_matrix;
|
||||||
GLuint uniform_row_length;
|
GLuint uniform_row_length;
|
||||||
|
GLuint uniform_inv_gamma;
|
||||||
|
|
||||||
GLuint quad;
|
GLuint quad;
|
||||||
};
|
};
|
||||||
|
|
||||||
GLES2Debayer *
|
GLES2Debayer *
|
||||||
gles2_debayer_new(int format, int xfer)
|
gles2_debayer_new(int format)
|
||||||
{
|
{
|
||||||
uint32_t pixfmt = libmegapixels_format_to_v4l_pixfmt(format);
|
uint32_t pixfmt = libmegapixels_format_to_v4l_pixfmt(format);
|
||||||
if (pixfmt != V4L2_PIX_FMT_SBGGR8 && pixfmt != V4L2_PIX_FMT_SGBRG8 &&
|
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);
|
glGenFramebuffers(1, &frame_buffer);
|
||||||
check_gl();
|
check_gl();
|
||||||
|
|
||||||
char format_def[96];
|
char format_def[64];
|
||||||
bool is_srgb = xfer == LIBMEGAPIXELS_XFER_SRGB;
|
|
||||||
snprintf(format_def,
|
snprintf(format_def,
|
||||||
96,
|
64,
|
||||||
"#define CFA_%s\n#define BITS_%d\n#define COLORSPACE_%s\n",
|
"#define CFA_%s\n#define BITS_%d\n",
|
||||||
libmegapixels_format_cfa(format),
|
libmegapixels_format_cfa(format),
|
||||||
libmegapixels_format_bits_per_pixel(format),
|
libmegapixels_format_bits_per_pixel(format));
|
||||||
is_srgb ? "SRGB" : "RAW");
|
|
||||||
|
|
||||||
const GLchar *def[1] = { format_def };
|
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_texture = glGetUniformLocation(self->program, "texture");
|
||||||
self->uniform_color_matrix =
|
self->uniform_color_matrix =
|
||||||
glGetUniformLocation(self->program, "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)
|
if (libmegapixels_format_bits_per_pixel(self->format) == 10)
|
||||||
self->uniform_row_length =
|
self->uniform_row_length =
|
||||||
glGetUniformLocation(self->program, "row_length");
|
glGetUniformLocation(self->program, "row_length");
|
||||||
@@ -115,8 +116,7 @@ gles2_debayer_configure(GLES2Debayer *self,
|
|||||||
const uint32_t src_height,
|
const uint32_t src_height,
|
||||||
const uint32_t rotation,
|
const uint32_t rotation,
|
||||||
const bool mirrored,
|
const bool mirrored,
|
||||||
const float *colormatrix,
|
struct MPCameraCalibration calibration)
|
||||||
const uint8_t blacklevel)
|
|
||||||
{
|
{
|
||||||
glViewport(0, 0, (int)dst_width, (int)dst_height);
|
glViewport(0, 0, (int)dst_width, (int)dst_height);
|
||||||
check_gl();
|
check_gl();
|
||||||
@@ -142,11 +142,21 @@ gles2_debayer_configure(GLES2Debayer *self,
|
|||||||
glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y);
|
glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y);
|
||||||
check_gl();
|
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];
|
GLfloat transposed[9];
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
for (int j = 0; j < 3; ++j)
|
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(
|
glUniformMatrix3fv(
|
||||||
self->uniform_color_matrix, 1, GL_FALSE, transposed);
|
self->uniform_color_matrix, 1, GL_FALSE, transposed);
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
#include "dcp.h"
|
||||||
#include "gl_util.h"
|
#include "gl_util.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct _GLES2Debayer GLES2Debayer;
|
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_free(GLES2Debayer *self);
|
||||||
|
|
||||||
void gles2_debayer_use(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 src_height,
|
||||||
const uint32_t rotation,
|
const uint32_t rotation,
|
||||||
const bool mirrored,
|
const bool mirrored,
|
||||||
const float *colormatrix,
|
struct MPCameraCalibration calibration);
|
||||||
const uint8_t blacklevel);
|
|
||||||
|
|
||||||
void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id);
|
void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id);
|
||||||
|
@@ -927,7 +927,7 @@ on_output_changed(bool format_changed)
|
|||||||
if (gles2_debayer)
|
if (gles2_debayer)
|
||||||
gles2_debayer_free(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();
|
check_gl();
|
||||||
|
|
||||||
gles2_debayer_use(gles2_debayer);
|
gles2_debayer_use(gles2_debayer);
|
||||||
@@ -940,8 +940,7 @@ on_output_changed(bool format_changed)
|
|||||||
state_proc.mode->height,
|
state_proc.mode->height,
|
||||||
state_proc.mode->rotation,
|
state_proc.mode->rotation,
|
||||||
0,
|
0,
|
||||||
NULL,
|
state_proc.calibration);
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -954,6 +953,7 @@ mod(int a, int b)
|
|||||||
static void
|
static void
|
||||||
update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
|
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.configuration = new_state->configuration;
|
||||||
state_proc.camera = new_state->camera;
|
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);
|
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 = {
|
mp_state_main new_main = {
|
||||||
.camera = pr_camera,
|
.camera = pr_camera,
|
||||||
.has_auto_focus_continuous = false,
|
.has_auto_focus_continuous = false,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "dcp.h"
|
||||||
#include <libmegapixels.h>
|
#include <libmegapixels.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -91,4 +92,6 @@ typedef struct state_proc {
|
|||||||
controlstate gain;
|
controlstate gain;
|
||||||
controlstate exposure;
|
controlstate exposure;
|
||||||
controlstate focus;
|
controlstate focus;
|
||||||
|
|
||||||
|
struct MPCameraCalibration calibration;
|
||||||
} mp_state_proc;
|
} mp_state_proc;
|
Reference in New Issue
Block a user