46#include <glib/gstdio.h>
61static const point_t bb_ref[] = {{.
x=.0, .y=.0}, {.x=1., .y=0.}, {.x=1., .y=1.}, {.x=0., .y=1.}};
240 const float denom = (y2 -
y3) * (x1 -
x3) + (
x3 - x2) * (y1 -
y3);
243 const float l3 = 1.0 -
l1 -
l2;
245 if(
l1 < 0.0 ||
l2 < 0.0 ||
l3 < 0.0)
260 for(
int i = 0;
i < 4;
i++)
262 const float d_x = (
x - bb[
i].
x);
263 const float d_y = (y - bb[
i].
y);
393 fprintf(
stderr,
"error creating cairo surface from `%s'\n", filename);
398 image->
surface = image_surface;
595 char *filename =
NULL;
621 char *
key = (
char *)
iter->data;
645 fprintf(fd,
" <num>%d</num>\n", num);
646 fprintf(fd,
" <module>%d</module>\n", op_version);
647 fprintf(fd,
" <operation>%s</operation>\n", operation);
648 fprintf(fd,
" <op_params>%s</op_params>\n", op_params);
649 fprintf(fd,
" <enabled>%d</enabled>\n", enabled);
650 fprintf(fd,
" <blendop_params>gz12eJxjYGBgkGAAgRNODESDBnsIHll8ANNSGQM=</blendop_params>\n");
651 fprintf(fd,
" <blendop_version>7</blendop_version>\n");
652 fprintf(fd,
" <multi_priority>0</multi_priority>\n");
653 fprintf(fd,
" <multi_name></multi_name>\n");
666 fprintf(fd,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
667 fprintf(fd,
"<darktable_style version=\"1.0\">\n");
678 "gz09eJxjYIAAM6vnNnqyn22E9n235b6aa3cy6rVdRaK9/Y970fYf95bbMzA0QPEoGEqADYnNhMQGAO0WEJo=",
FALSE);
700 fprintf(fd,
"</darktable_style>\n");
719 fprintf(fd,
"patch;L_source;a_source;b_source;L_reference;a_reference;b_reference\n");
765 const char *
key = (
char *)
iter->data;
787 fprintf(
stderr,
" %g %g %g -- %g %g %g\n", source_Lab[0], source_Lab[1], source_Lab[2],
796static void add_hdr_patches(
int *
N,
double **target_L,
double **target_a,
double **target_b,
803 for(
int j = 0;
j < *
N;
j++)
805 if((*target_L)[
j] == 100.0 && (*target_a)[
j] == 0.0 && (*target_b)[
j] == 0.0 && (*
colorchecker_Lab)[
j * 3] == 100.0
810 else if((*target_L)[
j] == 200.0 && (*target_a)[
j] == 0.0 && (*target_b)[
j] == 0.0 && (*
colorchecker_Lab)[
j * 3] == 200.0
883 memset(¶ms, 0,
sizeof(params));
884 params.tonecurve_autoscale_ab = 3;
886 params.tonecurve_type[0] = 2;
887 params.tonecurve_nodes[0] = 20;
888 for(
int k = 0;
k < 20;
k++)
890 const double x = (
k / 19.0) * (
k / 19.0);
891 params.tonecurve[0][
k].x =
x;
895 params.tonecurve_type[1] = 2;
896 params.tonecurve_nodes[1] = 2;
897 params.tonecurve[1][0].x = 0.0f;
898 params.tonecurve[1][0].y = 0.0f;
899 params.tonecurve[1][1].x = 1.0f;
900 params.tonecurve[1][1].y = 1.0f;
902 params.tonecurve_type[2] = 2;
903 params.tonecurve_nodes[2] = 2;
904 params.tonecurve[2][0].x = 0.0f;
905 params.tonecurve[2][0].y = 0.0f;
906 params.tonecurve[2][1].x = 1.0f;
907 params.tonecurve[2][1].y = 1.0f;
915#define MAX_PATCHES 49
928 memset(¶ms, 0,
sizeof(params));
931 params.num_patches = num;
933 for(
int k = 0;
k < num;
k++)
945 const float tmp = (a); \
950 for(
int k = 0;
k < num - 1;
k++)
951 for(
int j = 0;
j < num -
k - 1;
j++)
956 SWAP(params.source_L[
j], params.source_L[
j + 1]);
957 SWAP(params.source_a[
j], params.source_a[
j + 1]);
958 SWAP(params.source_b[
j], params.source_b[
j + 1]);
959 SWAP(params.target_L[
j], params.target_L[
j + 1]);
960 SWAP(params.target_a[
j], params.target_a[
j + 1]);
961 SWAP(params.target_b[
j], params.target_b[
j + 1]);
972 const double x = *(
const double *)
x_;
973 const double y = *(
const double *)
y_;
974 return x < y ? -1 : (
x > y ? +1 : 0);
981 double *cx =
malloc(
sizeof(
double)*
N);
982 double *cy =
malloc(
sizeof(
double)*
N);
995 target_a[
i] * target_a[
i] +
996 target_b[
i] * target_b[
i];
1009 fprintf(
stderr,
"detected %d/%d as gray patches for tonecurve computation\n",
cnt,
N);
1014 cx[0] = cy[0] = 0.0;
1015 cx[
cnt+1] = cy[
cnt+1] = 100.0;
1038 cx[0] = cy[0] = 0.0;
1054 for(
int k = 0;
k <
N;
k++)
1057 Lab[0] = target_L[
k];
1058 Lab[1] = target_a[
k];
1059 Lab[2] = target_b[
k];
1065 target_L[
k] =
Lab[0];
1066 target_a[
k] =
Lab[1];
1067 target_b[
k] =
Lab[2];
1072 const double *target[3] = { target_L, target_a, target_b };
1073 double *coeff_L =
malloc(
sizeof(
double) * (
N + 4) );
1074 double *coeff_a =
malloc(
sizeof(
double) * (
N + 4) );
1075 double *coeff_b =
malloc(
sizeof(
double) * (
N + 4) );
1076 double *
coeff[] = { coeff_L, coeff_a, coeff_b };
1094 int cperm[300] = { 0 };
1101 for(
int k = 0;
k <
sp;
k++)
1128 double *target_L = (
double *)
calloc(
sizeof(
double), (
N + 4));
1129 double *target_a = (
double *)
calloc(
sizeof(
double), (
N + 4));
1130 double *target_b = (
double *)
calloc(
sizeof(
double), (
N + 4));
1407 (
int)(patch->
rgb[1] * 255 + 0.5), (
int)(patch->
rgb[2] * 255 + 0.5));
1532 xyz[0] = xyz[1] = xyz[2] = 0.0;
1577 for(
int i = 0;
i < 4;
i++)
1667 for(
int y = 0; y <
height; y++)
1682 char *reference_filename =
NULL;
1687 reference_filename = argv[3];
1737#ifdef GDK_WINDOWING_QUARTZ
1768 char key[16] = {0},
value[256] = {0};
1772 fprintf(
stderr,
"error: expected `name' in the first line\n");
1782 fprintf(
stderr,
"error: expected `description' in the second line\n");
1802 double *target_L = (
double *)
calloc(
sizeof(
double), (
N + 4));
1803 double *target_a = (
double *)
calloc(
sizeof(
double), (
N + 4));
1804 double *target_b = (
double *)
calloc(
sizeof(
double), (
N + 4));
1805 double *source_Lab = (
double *)
calloc(
sizeof(
double) * 3,
N);
1812 for(
int i = 0;
i <
N;
i++)
1815 if(
fgets(line,
sizeof(line) /
sizeof(*line),
f) == 0)
break;
1837 const double d[3] = { target_L[
i], target_a[
i], target_b[
i] };
1841 sqrt(
d[0] *
d[0] +
d[1] *
d[1] +
d[2] *
d[2]));
1842 fprintf(
stderr,
" %g %g %g -- %g %g %g\n", source_Lab[3 *
i + 0], source_Lab[3 *
i + 1],
1843 source_Lab[3 *
i + 2], target_L[
i], target_a[
i], target_b[
i]);
1856 const int num_patches =
atoi(argv[3]);
1859 const int sparsity = num_patches + 4;
1899 fprintf(
stderr,
"Usage: %s [<input Lab pfm file>] [<cht file>] [<reference cgats/it8 or Lab pfm file>]\n"
1900 " %s --csv <csv file> <number patches> <output dtstyle file>\n",
static char * get_filename_base(const char *filename)
static void add_patches_to_array(dt_lut_t *self, GList *patch_names, int *N, int *i, double *target_L, double *target_a, double *target_b, double *colorchecker_Lab)
static gboolean handle_motion(GtkWidget *widget, GdkEventMotion *event, dt_lut_t *self, image_t *image)
static int main_gui(dt_lut_t *self, int argc, char *argv[])
static box_t * find_patch(GHashTable *table, gpointer key)
static void cht_state_callback(GtkWidget *widget, GtkStateFlags flags, gpointer user_data)
static void init_image(dt_lut_t *self, image_t *image, GCallback motion_cb)
static void get_Lab_from_box(box_t *box, float *Lab)
static int find_closest_corner(point_t *bb, float x, float y)
static void process_button_clicked_callback(GtkButton *button, gpointer user_data)
static box_t get_sample_box(chart_t *chart, box_t *outer_box, float shrink)
static point_t map_point_to_view(image_t *image, point_t p)
static void export_raw(dt_lut_t *self, char *filename, char *name, char *description)
static void reference_mode_changed_callback(GtkComboBox *widget, gpointer user_data)
static void reset_bb(image_t *image)
static int parse_csv(dt_lut_t *self, const char *filename, double **target_L_ptr, double **target_a_ptr, double **target_b_ptr, double **source_Lab_ptr, int *num_gray, char **name, char **description)
static void print_patches(dt_lut_t *self, FILE *fd, GList *patch_names)
static void get_pixel_region(const image_t *const image, const point_t *const corners, int *x_start, int *y_start, int *x_end, int *y_end)
static void collect_reference_patches(dt_lut_t *self)
static const point_t bb_ref[]
static int main_csv(dt_lut_t *self, int argc, char *argv[])
static char * encode_colorchecker(int num, const double *point, const double **target, int *permutation)
static void map_mouse_to_0_1(GtkWidget *widget, GdkEventMotion *event, image_t *image, float *x, float *y)
static void free_image(image_t *image)
static gboolean open_cht(dt_lut_t *self, const char *filename)
static void get_corners(const float *homography, box_t *box, point_t *corners)
static void export_style(dt_lut_t *self, const char *filename, const char *name, const char *description, gboolean include_basecurve, gboolean include_colorchecker, gboolean include_colorin, gboolean include_tonecurve)
static void collect_reference_patches_foreach(gpointer key, gpointer value, gpointer user_data)
static void get_xyz_sample_from_image(const image_t *const image, float shrink, box_t *box, float *xyz)
static gboolean draw_image_callback(GtkWidget *widget, cairo_t *cr, gpointer user_data)
static void export_button_clicked_callback(GtkButton *button, gpointer user_data)
static void show_usage(const char *exe)
static void export_raw_button_clicked_callback(GtkButton *button, gpointer user_data)
static gboolean open_it8(dt_lut_t *self, const char *filename)
static char * get_export_filename(dt_lut_t *self, const char *extension, char **name, char **description, gboolean *basecurve, gboolean *colorchecker, gboolean *colorin, gboolean *tonecurve)
static gboolean open_image(image_t *image, const char *filename)
static void init_table(dt_lut_t *self)
static void source_image_changed_callback(GtkFileChooserButton *widget, gpointer user_data)
static void size_allocate_callback(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
static void print_xml_plugin(FILE *fd, int num, int op_version, const char *operation, const char *op_params, gboolean enabled)
static void add_hdr_patches(int *N, double **target_L, double **target_a, double **target_b, double **colorchecker_Lab)
static void process_data(dt_lut_t *self, double *target_L, double *target_a, double *target_b, double *colorchecker_Lab, int N, int sparsity)
static GtkWidget * create_notebook_page_reference(dt_lut_t *self)
static gboolean motion_notify_callback_reference(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
static gboolean open_reference_image(dt_lut_t *self, const char *filename)
static void add_column(GtkTreeView *treeview, const char *title, int column_id, int sort_column)
static void collect_source_patches(dt_lut_t *self)
static void update_table(dt_lut_t *self)
static GtkWidget * create_notebook_page_process(dt_lut_t *self)
static void collect_source_patches_foreach(gpointer key, gpointer value, gpointer user_data)
static int compare_L_source(const void *x_, const void *y_)
static void ref_image_changed_callback(GtkFileChooserButton *widget, gpointer user_data)
static void cht_changed_callback(GtkFileChooserButton *widget, gpointer user_data)
static void image_lab_to_xyz(float *image, const int width, const int height)
static char * encode_tonecurve(const tonecurve_t *c)
static void update_corner(image_t *image, int which, float *x, float *y)
static GtkWidget * create_table(dt_lut_t *self)
static GtkWidget * create_notebook(dt_lut_t *self)
static void it8_changed_callback(GtkFileChooserButton *widget, gpointer user_data)
static GtkWidget * create_notebook_page_source(dt_lut_t *self)
static void map_boundingbox_to_view(image_t *image, point_t *bb)
static gboolean open_source_image(dt_lut_t *self, const char *filename)
static void shrink_changed_callback(GtkRange *range, gpointer user_data)
static void get_boundingbox(const image_t *const image, point_t *bb)
static gboolean motion_notify_callback_source(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
float * read_pfm(const char *filename, int *wd, int *ht)
double tonecurve_apply(const tonecurve_t *c, const double L)
double tonecurve_unapply(const tonecurve_t *c, const double L)
void tonecurve_delete(tonecurve_t *c)
void tonecurve_create(tonecurve_t *c, double *Lin, double *Lout, const int32_t num)
const char ** description(struct dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ void homography(float *homograph, const float angle, const float shift_v, const float shift_h, const float shear, const float f_length_kb, const float orthocorr, const float aspect, const int width, const int height, dt_iop_ashift_homodir_t dir)
const char * extension(dt_imageio_module_data_t *data)
chart_t * parse_cht(const char *filename)
void free_chart(chart_t *chart)
int parse_it8(const char *filename, chart_t *chart)
void checker_set_color(box_t *box, dt_colorspaces_color_profile_type_t color_space, float c0, float c1, float c2)
const float *const const float coeff[3]
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static dt_aligned_pixel_t rgb
static dt_aligned_pixel_t XYZ
static dt_aligned_pixel_t Lab
float dt_colorspaces_deltaE_1976(dt_aligned_pixel_t Lab0, dt_aligned_pixel_t Lab1)
float dt_colorspaces_deltaE_2000(dt_aligned_pixel_t Lab0, dt_aligned_pixel_t Lab1)
void draw_image(cairo_t *cr, image_t *image)
void draw_color_boxes_outline(cairo_t *cr, const float *homography, chart_t *chart)
void draw_no_image(cairo_t *cr, GtkWidget *widget)
void center_image(cairo_t *cr, image_t *image)
void stroke_boxes(cairo_t *cr, float line_width)
void clear_background(cairo_t *cr)
void draw_color_boxes_inside(cairo_t *cr, const float *homography, chart_t *chart, float shrink, float line_width, gboolean colored)
cairo_surface_t * cairo_surface_create_from_xyz_data(const float *const image, const int width, const int height)
void draw_f_boxes(cairo_t *cr, const float *homography, chart_t *chart)
void draw_boundingbox(cairo_t *cr, point_t *bb)
void draw_d_boxes(cairo_t *cr, const float *homography, chart_t *chart)
void set_offset_and_scale(image_t *image, float width, float height)
char * dt_exif_xmp_encode_internal(const unsigned char *input, const int len, int *output_len, gboolean do_compress)
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
point_t apply_homography(point_t p, const float *h)
int get_homography(const point_t *source, const point_t *target, float *h)
static const float colorchecker_Lab[]
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static void dt_free_gpointer(gpointer ptr)
dt_mipmap_buffer_dsc_flags flags
#define __OMP_PARALLEL_FOR__(...)
void dt_osx_focus_window()
void dt_osx_prepare_environment()
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
static const dt_aligned_pixel_simd_t value
dt_colorspaces_color_profile_type_t color_space
dt_iop_tonecurve_node_t tonecurve[3][20]
int tonecurve_autoscale_ab
char * colorchecker_encoded
GtkWidget * reference_image_box
char * reference_filename
GtkWidget * source_shrink
GtkWidget * reference_mode
GtkWidget * reference_shrink
GtkWidget * process_button
GtkWidget * reference_image_button
GtkWidget * reference_it8_box
GtkWidget * number_patches
GtkWidget * export_raw_button
GtkWidget * export_button
GHashTable * picked_source_patches
cairo_surface_t * surface
float thinplate_color_pos(float L, float a, float b)
int thinplate_match(const tonecurve_t *curve, int dim, int N, const double *point, const double **target, int S, int *permutation, double **coeff, double *avgerr, double *maxerr)