Browse Source

Use calibration for preview

Martijn Braam 1 year ago
parent
commit
e9681e1eea
7 changed files with 112 additions and 23 deletions
  1. 7 6
      data/debayer.frag
  2. 62 0
      src/dcp.c
  3. 3 0
      src/dcp.h
  4. 21 11
      src/gles2_debayer.c
  5. 4 3
      src/gles2_debayer.h
  6. 12 3
      src/process_pipeline.c
  7. 3 0
      src/state.h

+ 7 - 6
data/debayer.frag

@@ -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 - 0
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;
+                }
+        }
+}

+ 3 - 0
src/dcp.h

@@ -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);

+ 21 - 11
src/gles2_debayer.c

@@ -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);

+ 4 - 3
src/gles2_debayer.h

@@ -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);

+ 12 - 3
src/process_pipeline.c

@@ -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,

+ 3 - 0
src/state.h

@@ -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;