|
|
@@ -15,6 +15,8 @@ struct Gui {
|
|
15
|
15
|
haader::HdrImage hdr_image;
|
|
16
|
16
|
haader::ResponseFunction response_function;
|
|
17
|
17
|
haader::Image ldr_image;
|
|
|
18
|
+ haader::Histogram hdr_histogram;
|
|
|
19
|
+ haader::LdrHistogram ldr_histogram;
|
|
18
|
20
|
cairo_surface_t *surface;
|
|
19
|
21
|
double exposure_time;
|
|
20
|
22
|
double compression;
|
|
|
@@ -46,6 +48,7 @@ static cairo_surface_t* image_to_cairo_surface(const haader::Image &image) {
|
|
46
|
48
|
|
|
47
|
49
|
static void expose(Gui &gui) {
|
|
48
|
50
|
gui.ldr_image = gui.hdr_image.expose(gui.exposure_time, gui.response_function, gui.compression);
|
|
|
51
|
+ gui.ldr_histogram = gui.ldr_image.histogram();
|
|
49
|
52
|
if (gui.surface) {
|
|
50
|
53
|
cairo_surface_destroy(gui.surface);
|
|
51
|
54
|
gui.surface = NULL;
|
|
|
@@ -59,11 +62,72 @@ static gboolean canvas_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
|
59
|
62
|
cairo_paint(cr);
|
|
60
|
63
|
|
|
61
|
64
|
Gui *gui = (Gui*) user_data;
|
|
62
|
|
- if (gui->surface) {
|
|
63
|
|
- cairo_set_source_surface(cr, gui->surface, 0, 0);
|
|
64
|
|
- cairo_paint(cr);
|
|
|
65
|
+ if (!gui->surface) {
|
|
|
66
|
+ return false;
|
|
65
|
67
|
}
|
|
66
|
68
|
|
|
|
69
|
+ if (gui->hdr_histogram.m_bins.size() != 256) {
|
|
|
70
|
+ return false;
|
|
|
71
|
+ }
|
|
|
72
|
+
|
|
|
73
|
+ if (gui->ldr_histogram.m_bins.size() != 256) {
|
|
|
74
|
+ return false;
|
|
|
75
|
+ }
|
|
|
76
|
+
|
|
|
77
|
+ cairo_set_source_surface(cr, gui->surface, 5, 5);
|
|
|
78
|
+ cairo_paint(cr);
|
|
|
79
|
+
|
|
|
80
|
+ // canvas rect
|
|
|
81
|
+ double cx = gui->ldr_image.get_width() + 10.0;
|
|
|
82
|
+ double cy = 5.0;
|
|
|
83
|
+ double cw = 256;
|
|
|
84
|
+ double ch = 256;
|
|
|
85
|
+
|
|
|
86
|
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
|
|
|
87
|
+ cairo_rectangle(cr, cx, cy, cw, ch);
|
|
|
88
|
+ cairo_fill(cr);
|
|
|
89
|
+
|
|
|
90
|
+ {
|
|
|
91
|
+ double hist_scale = (256.0 / (double)(gui->hdr_histogram.m_max_freq));
|
|
|
92
|
+ for (unsigned int i = 0; i < 256; i++) {
|
|
|
93
|
+ double y = gui->hdr_histogram.m_bins[i] * hist_scale;
|
|
|
94
|
+ cairo_rectangle(cr, cx + i, cy + ch - y, 1, y);
|
|
|
95
|
+ }
|
|
|
96
|
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.2, 0.4);
|
|
|
97
|
+ cairo_fill(cr);
|
|
|
98
|
+ }
|
|
|
99
|
+
|
|
|
100
|
+ {
|
|
|
101
|
+ double hist_scale = (256.0 / (double)(gui->ldr_histogram.m_max_freq));
|
|
|
102
|
+ for (unsigned int i = 0; i < 256; i++) {
|
|
|
103
|
+ double y = gui->ldr_histogram.m_bins[i] * hist_scale;
|
|
|
104
|
+ cairo_rectangle(cr, cx + i, cy + ch - y, 1, y);
|
|
|
105
|
+ }
|
|
|
106
|
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.2, 0.9);
|
|
|
107
|
+ cairo_fill(cr);
|
|
|
108
|
+ }
|
|
|
109
|
+
|
|
|
110
|
+
|
|
|
111
|
+ double minl = gui->hdr_histogram.m_min_value;
|
|
|
112
|
+ double maxl = gui->hdr_histogram.m_max_value;
|
|
|
113
|
+ double log_exp = log(gui->exposure_time);
|
|
|
114
|
+ double scale = (maxl - minl) / 256.0;
|
|
|
115
|
+
|
|
|
116
|
+ for (int i = 0; i < 256; i++) {
|
|
|
117
|
+ double lum = minl + i * scale;
|
|
|
118
|
+ int ly = gui->response_function.lookup((lum + log_exp) * gui->compression);
|
|
|
119
|
+ cairo_line_to(cr, cx + i, cy + ch - ly);
|
|
|
120
|
+ }
|
|
|
121
|
+ cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.8);
|
|
|
122
|
+ cairo_set_line_width(cr, 1.0);
|
|
|
123
|
+ cairo_stroke_preserve(cr);
|
|
|
124
|
+
|
|
|
125
|
+ cairo_line_to(cr, cx + cw, cy + ch);
|
|
|
126
|
+ cairo_line_to(cr, cx, cy + ch);
|
|
|
127
|
+ cairo_close_path(cr);
|
|
|
128
|
+ cairo_set_source_rgba(cr, 0.0, 0.5, 1.0, 0.2);
|
|
|
129
|
+ cairo_fill(cr);
|
|
|
130
|
+
|
|
67
|
131
|
return FALSE;
|
|
68
|
132
|
}
|
|
69
|
133
|
|
|
|
@@ -102,36 +166,42 @@ void file_select_clicked(GtkButton *button, gpointer user_data) {
|
|
102
|
166
|
|
|
103
|
167
|
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(dialog), true);
|
|
104
|
168
|
|
|
105
|
|
- int res = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
106
|
|
- if (res == GTK_RESPONSE_ACCEPT) {
|
|
|
169
|
+ bool ok = true;
|
|
|
170
|
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
|
107
|
171
|
GSList *list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
|
108
|
172
|
vector<string> new_list;
|
|
109
|
173
|
|
|
110
|
174
|
GSList *element = list;
|
|
111
|
175
|
while (element != NULL) {
|
|
112
|
|
- //TODO handle errors
|
|
113
|
|
- gui->stack.add_from_file_path((const char*)(element->data));
|
|
|
176
|
+ ok = ok && gui->stack.add_from_file_path((const char*)(element->data));
|
|
114
|
177
|
g_free(element->data);
|
|
115
|
178
|
element = g_slist_next(element);
|
|
|
179
|
+ if (!ok) {
|
|
|
180
|
+ break;
|
|
|
181
|
+ }
|
|
116
|
182
|
}
|
|
117
|
183
|
|
|
118
|
184
|
g_slist_free(list);
|
|
119
|
185
|
}
|
|
120
|
186
|
|
|
121
|
|
- // create HDR-image
|
|
122
|
|
- haader::InverseResponseFunction irf;
|
|
123
|
|
- if (gui->stack.get_inverse_response_function(irf, 4096)) {
|
|
124
|
|
- gui->hdr_image = gui->stack.get_hdr_image(irf);
|
|
125
|
|
- gui->ldr_image = gui->hdr_image.get_log_image();
|
|
126
|
|
- if (gui->surface) {
|
|
127
|
|
- cairo_surface_destroy(gui->surface);
|
|
128
|
|
- gui->surface = NULL;
|
|
|
187
|
+ if (ok) {
|
|
|
188
|
+ // create HDR-image
|
|
|
189
|
+ haader::InverseResponseFunction irf;
|
|
|
190
|
+ if (gui->stack.get_inverse_response_function(irf, 4096)) {
|
|
|
191
|
+ gui->hdr_image = gui->stack.get_hdr_image(irf);
|
|
|
192
|
+ gui->ldr_image = gui->hdr_image.get_log_image();
|
|
|
193
|
+ gui->hdr_histogram = gui->hdr_image.histogram(256);
|
|
|
194
|
+ gui->ldr_histogram = gui->ldr_image.histogram();
|
|
|
195
|
+ if (gui->surface) {
|
|
|
196
|
+ cairo_surface_destroy(gui->surface);
|
|
|
197
|
+ gui->surface = NULL;
|
|
|
198
|
+ }
|
|
|
199
|
+ gui->surface = image_to_cairo_surface(gui->ldr_image);
|
|
|
200
|
+ gui->response_function = irf.to_response_function(1024);
|
|
129
|
201
|
}
|
|
130
|
|
- gui->surface = image_to_cairo_surface(gui->ldr_image);
|
|
131
|
|
- gui->response_function = irf.to_response_function(1024);
|
|
132
|
|
- }
|
|
133
|
202
|
|
|
134
|
|
- gtk_widget_queue_draw(gui->canvas);
|
|
|
203
|
+ gtk_widget_queue_draw(gui->canvas);
|
|
|
204
|
+ }
|
|
135
|
205
|
|
|
136
|
206
|
gtk_widget_destroy (dialog);
|
|
137
|
207
|
}
|
|
|
@@ -152,15 +222,33 @@ int main(int argc, char *argv[])
|
|
152
|
222
|
GtkWidget *file_button = gtk_button_new_with_label("Select files");
|
|
153
|
223
|
gui.canvas = gtk_drawing_area_new();
|
|
154
|
224
|
GtkWidget *scale_exposure = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -20.0, 4.0, 0.001);
|
|
|
225
|
+ gtk_range_set_value(GTK_RANGE(scale_exposure), log(gui.exposure_time) / log(2));
|
|
|
226
|
+
|
|
155
|
227
|
GtkWidget *scale_compression = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -4, 4.0, 0.001);
|
|
|
228
|
+ gtk_range_set_value(GTK_RANGE(scale_compression), log(gui.compression) / log(2));
|
|
156
|
229
|
|
|
157
|
230
|
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
|
158
|
231
|
|
|
159
|
232
|
gtk_container_add(GTK_CONTAINER(gui.window), vbox);
|
|
160
|
233
|
gtk_box_pack_start(GTK_BOX(vbox), file_button, false, false, 0);
|
|
161
|
234
|
gtk_box_pack_start(GTK_BOX(vbox), gui.canvas, true, true, 0);
|
|
162
|
|
- gtk_box_pack_start(GTK_BOX(vbox), scale_exposure, false, false, 0);
|
|
163
|
|
- gtk_box_pack_start(GTK_BOX(vbox), scale_compression, false, false, 0);
|
|
|
235
|
+
|
|
|
236
|
+ GtkWidget *grid = gtk_grid_new();
|
|
|
237
|
+ gtk_box_pack_start(GTK_BOX(vbox), grid, false, false, 0);
|
|
|
238
|
+
|
|
|
239
|
+ {
|
|
|
240
|
+ GtkWidget *label = gtk_label_new("Exposure");
|
|
|
241
|
+ gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
|
|
|
242
|
+ gtk_widget_set_size_request(scale_exposure, 600, -1);
|
|
|
243
|
+ gtk_grid_attach(GTK_GRID(grid), scale_exposure, 1, 0, 1, 1);
|
|
|
244
|
+ }
|
|
|
245
|
+
|
|
|
246
|
+ {
|
|
|
247
|
+ GtkWidget *label = gtk_label_new("Compression");
|
|
|
248
|
+ gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
|
|
|
249
|
+ gtk_widget_set_size_request(scale_compression, 600, -1);
|
|
|
250
|
+ gtk_grid_attach(GTK_GRID(grid), scale_compression, 1, 1, 1, 1);
|
|
|
251
|
+ }
|
|
164
|
252
|
|
|
165
|
253
|
g_signal_connect(gui.window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
|
166
|
254
|
g_signal_connect(gui.canvas, "draw", G_CALLBACK(canvas_draw), &gui);
|