Przeglądaj źródła

GUI: Draw histograms and response function, ...

...handle errors and change layout.
Johannes Hofmann 7 lat temu
rodzic
commit
2d507d2e64
1 zmienionych plików z 109 dodań i 21 usunięć
  1. 109
    21
      haader_gui.cpp

+ 109
- 21
haader_gui.cpp Wyświetl plik

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