Use calibration for preview
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
62
src/dcp.c
62
src/dcp.c
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
Reference in New Issue
Block a user