|
|
@@ -12,6 +12,9 @@ using namespace std;
|
|
12
|
12
|
struct Gui {
|
|
13
|
13
|
GtkWidget *window;
|
|
14
|
14
|
GtkWidget *canvas;
|
|
|
15
|
+ GtkWidget *log_checkbox;
|
|
|
16
|
+ GtkWidget *scale_exposure;
|
|
|
17
|
+ GtkWidget *scale_compression;
|
|
15
|
18
|
haader::HdrImageStack stack;
|
|
16
|
19
|
haader::HdrImage hdr_image;
|
|
17
|
20
|
haader::ResponseFunction response_function;
|
|
|
@@ -57,6 +60,16 @@ static void expose(Gui &gui) {
|
|
57
|
60
|
gui.surface = image_to_cairo_surface(gui.ldr_image);
|
|
58
|
61
|
}
|
|
59
|
62
|
|
|
|
63
|
+static void create_log_image(Gui &gui) {
|
|
|
64
|
+ gui.ldr_image = gui.hdr_image.get_log_image();
|
|
|
65
|
+ gui.ldr_histogram = gui.ldr_image.histogram();
|
|
|
66
|
+ if (gui.surface) {
|
|
|
67
|
+ cairo_surface_destroy(gui.surface);
|
|
|
68
|
+ gui.surface = NULL;
|
|
|
69
|
+ }
|
|
|
70
|
+ gui.surface = image_to_cairo_surface(gui.ldr_image);
|
|
|
71
|
+}
|
|
|
72
|
+
|
|
60
|
73
|
static gboolean canvas_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
|
61
|
74
|
{
|
|
62
|
75
|
cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
|
|
|
@@ -108,30 +121,49 @@ static gboolean canvas_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
|
108
|
121
|
cairo_fill(cr);
|
|
109
|
122
|
}
|
|
110
|
123
|
|
|
|
124
|
+ if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gui->log_checkbox))) {
|
|
|
125
|
+ // Draw response function
|
|
111
|
126
|
|
|
112
|
|
- double minl = gui->hdr_histogram.m_min_value;
|
|
113
|
|
- double maxl = gui->hdr_histogram.m_max_value;
|
|
114
|
|
- double log_exp = log(gui->exposure_time);
|
|
115
|
|
- double scale = (maxl - minl) / 256.0;
|
|
|
127
|
+ double minl = gui->hdr_histogram.m_min_value;
|
|
|
128
|
+ double maxl = gui->hdr_histogram.m_max_value;
|
|
|
129
|
+ double log_exp = log(gui->exposure_time);
|
|
|
130
|
+ double scale = (maxl - minl) / 256.0;
|
|
116
|
131
|
|
|
117
|
|
- for (int i = 0; i < 256; i++) {
|
|
118
|
|
- double lum = minl + i * scale;
|
|
119
|
|
- int ly = gui->response_function.lookup((lum + log_exp) * gui->compression);
|
|
120
|
|
- cairo_line_to(cr, cx + i, cy + ch - ly);
|
|
|
132
|
+ for (int i = 0; i < 256; i++) {
|
|
|
133
|
+ double lum = minl + i * scale;
|
|
|
134
|
+ int ly = gui->response_function.lookup((lum + log_exp) * gui->compression);
|
|
|
135
|
+ cairo_line_to(cr, cx + i, cy + ch - ly);
|
|
|
136
|
+ }
|
|
|
137
|
+ cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.8);
|
|
|
138
|
+ cairo_set_line_width(cr, 1.0);
|
|
|
139
|
+ cairo_stroke_preserve(cr);
|
|
|
140
|
+
|
|
|
141
|
+ cairo_line_to(cr, cx + cw, cy + ch);
|
|
|
142
|
+ cairo_line_to(cr, cx, cy + ch);
|
|
|
143
|
+ cairo_close_path(cr);
|
|
|
144
|
+ cairo_set_source_rgba(cr, 0.0, 0.5, 1.0, 0.2);
|
|
|
145
|
+ cairo_fill(cr);
|
|
121
|
146
|
}
|
|
122
|
|
- cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.8);
|
|
123
|
|
- cairo_set_line_width(cr, 1.0);
|
|
124
|
|
- cairo_stroke_preserve(cr);
|
|
125
|
|
-
|
|
126
|
|
- cairo_line_to(cr, cx + cw, cy + ch);
|
|
127
|
|
- cairo_line_to(cr, cx, cy + ch);
|
|
128
|
|
- cairo_close_path(cr);
|
|
129
|
|
- cairo_set_source_rgba(cr, 0.0, 0.5, 1.0, 0.2);
|
|
130
|
|
- cairo_fill(cr);
|
|
131
|
147
|
|
|
132
|
148
|
return FALSE;
|
|
133
|
149
|
}
|
|
134
|
150
|
|
|
|
151
|
+void log_toggled(GtkToggleButton *button, gpointer user_data) {
|
|
|
152
|
+ Gui *gui = (Gui*) user_data;
|
|
|
153
|
+
|
|
|
154
|
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
|
|
|
155
|
+ gtk_widget_set_sensitive(gui->scale_exposure, false);
|
|
|
156
|
+ gtk_widget_set_sensitive(gui->scale_compression, false);
|
|
|
157
|
+ create_log_image(*gui);
|
|
|
158
|
+ } else {
|
|
|
159
|
+ gtk_widget_set_sensitive(gui->scale_exposure, true);
|
|
|
160
|
+ gtk_widget_set_sensitive(gui->scale_compression, true);
|
|
|
161
|
+ expose(*gui);
|
|
|
162
|
+ }
|
|
|
163
|
+
|
|
|
164
|
+ gtk_widget_queue_draw(gui->canvas);
|
|
|
165
|
+}
|
|
|
166
|
+
|
|
135
|
167
|
void scale_exposure_changed(GtkRange *range, gpointer user_data) {
|
|
136
|
168
|
Gui *gui = (Gui*) user_data;
|
|
137
|
169
|
|
|
|
@@ -169,8 +201,9 @@ void file_select_clicked(GtkButton *button, gpointer user_data) {
|
|
169
|
201
|
|
|
170
|
202
|
bool ok = true;
|
|
171
|
203
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
|
172
|
|
- vector<string> path_list;
|
|
|
204
|
+ gui->stack = haader::HdrImageStack();
|
|
173
|
205
|
|
|
|
206
|
+ vector<string> path_list;
|
|
174
|
207
|
{
|
|
175
|
208
|
GSList *list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
|
176
|
209
|
|
|
|
@@ -202,6 +235,7 @@ void file_select_clicked(GtkButton *button, gpointer user_data) {
|
|
202
|
235
|
if (gui->stack.get_inverse_response_function(irf, 4096)) {
|
|
203
|
236
|
gui->hdr_image = gui->stack.get_hdr_image(irf);
|
|
204
|
237
|
gui->ldr_image = gui->hdr_image.get_log_image();
|
|
|
238
|
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->log_checkbox), true);
|
|
205
|
239
|
gui->hdr_histogram = gui->hdr_image.histogram(256);
|
|
206
|
240
|
gui->ldr_histogram = gui->ldr_image.histogram();
|
|
207
|
241
|
if (gui->surface) {
|
|
|
@@ -224,7 +258,7 @@ int main(int argc, char *argv[])
|
|
224
|
258
|
|
|
225
|
259
|
Gui gui;
|
|
226
|
260
|
gui.surface = NULL;
|
|
227
|
|
- gui.exposure_time = 0.0;
|
|
|
261
|
+ gui.exposure_time = 0.125;
|
|
228
|
262
|
gui.compression = 1.0;
|
|
229
|
263
|
|
|
230
|
264
|
gui.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
|
@@ -233,11 +267,19 @@ int main(int argc, char *argv[])
|
|
233
|
267
|
|
|
234
|
268
|
GtkWidget *file_button = gtk_button_new_with_label("Select files");
|
|
235
|
269
|
gui.canvas = gtk_drawing_area_new();
|
|
236
|
|
- GtkWidget *scale_exposure = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -20.0, 4.0, 0.001);
|
|
237
|
|
- gtk_range_set_value(GTK_RANGE(scale_exposure), log(gui.exposure_time) / log(2));
|
|
238
|
270
|
|
|
239
|
|
- GtkWidget *scale_compression = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -4, 4.0, 0.001);
|
|
240
|
|
- gtk_range_set_value(GTK_RANGE(scale_compression), log(gui.compression) / log(2));
|
|
|
271
|
+ gui.log_checkbox = gtk_check_button_new_with_label("Logarithmic");
|
|
|
272
|
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.log_checkbox), true);
|
|
|
273
|
+
|
|
|
274
|
+ gui.scale_exposure = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -20.0, 4.0, 0.001);
|
|
|
275
|
+ gtk_range_set_value(GTK_RANGE(gui.scale_exposure), log(gui.exposure_time) / log(2));
|
|
|
276
|
+
|
|
|
277
|
+ gui.scale_compression = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -4, 4.0, 0.001);
|
|
|
278
|
+ gtk_scale_add_mark(GTK_SCALE(gui.scale_compression), 0.0, GTK_POS_BOTTOM, "0");
|
|
|
279
|
+ gtk_range_set_value(GTK_RANGE(gui.scale_compression), log(gui.compression) / log(2));
|
|
|
280
|
+
|
|
|
281
|
+ gtk_widget_set_sensitive(gui.scale_exposure, false);
|
|
|
282
|
+ gtk_widget_set_sensitive(gui.scale_compression, false);
|
|
241
|
283
|
|
|
242
|
284
|
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
|
243
|
285
|
|
|
|
@@ -248,25 +290,28 @@ int main(int argc, char *argv[])
|
|
248
|
290
|
GtkWidget *grid = gtk_grid_new();
|
|
249
|
291
|
gtk_box_pack_start(GTK_BOX(vbox), grid, false, false, 0);
|
|
250
|
292
|
|
|
|
293
|
+ gtk_grid_attach(GTK_GRID(grid), gui.log_checkbox, 1, 0, 1, 1);
|
|
|
294
|
+
|
|
251
|
295
|
{
|
|
252
|
296
|
GtkWidget *label = gtk_label_new("Exposure");
|
|
253
|
|
- gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
|
|
254
|
|
- gtk_widget_set_size_request(scale_exposure, 600, -1);
|
|
255
|
|
- gtk_grid_attach(GTK_GRID(grid), scale_exposure, 1, 0, 1, 1);
|
|
|
297
|
+ gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
|
|
|
298
|
+ gtk_widget_set_size_request(gui.scale_exposure, 600, -1);
|
|
|
299
|
+ gtk_grid_attach(GTK_GRID(grid), gui.scale_exposure, 1, 1, 1, 1);
|
|
256
|
300
|
}
|
|
257
|
301
|
|
|
258
|
302
|
{
|
|
259
|
303
|
GtkWidget *label = gtk_label_new("Compression");
|
|
260
|
|
- gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
|
|
261
|
|
- gtk_widget_set_size_request(scale_compression, 600, -1);
|
|
262
|
|
- gtk_grid_attach(GTK_GRID(grid), scale_compression, 1, 1, 1, 1);
|
|
|
304
|
+ gtk_grid_attach(GTK_GRID(grid), label, 0, 2, 1, 1);
|
|
|
305
|
+ gtk_widget_set_size_request(gui.scale_compression, 600, -1);
|
|
|
306
|
+ gtk_grid_attach(GTK_GRID(grid), gui.scale_compression, 1, 2, 1, 1);
|
|
263
|
307
|
}
|
|
264
|
308
|
|
|
265
|
309
|
g_signal_connect(gui.window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
|
266
|
310
|
g_signal_connect(gui.canvas, "draw", G_CALLBACK(canvas_draw), &gui);
|
|
267
|
311
|
g_signal_connect(file_button, "clicked", G_CALLBACK(file_select_clicked), &gui);
|
|
268
|
|
- g_signal_connect(scale_exposure, "value-changed", G_CALLBACK(scale_exposure_changed), &gui);
|
|
269
|
|
- g_signal_connect(scale_compression, "value-changed", G_CALLBACK(scale_compression_changed), &gui);
|
|
|
312
|
+ g_signal_connect(gui.log_checkbox, "toggled", G_CALLBACK(log_toggled), &gui);
|
|
|
313
|
+ g_signal_connect(gui.scale_exposure, "value-changed", G_CALLBACK(scale_exposure_changed), &gui);
|
|
|
314
|
+ g_signal_connect(gui.scale_compression, "value-changed", G_CALLBACK(scale_compression_changed), &gui);
|
|
270
|
315
|
|
|
271
|
316
|
gtk_widget_show_all(gui.window);
|
|
272
|
317
|
|