Browse Source

Move thumbnail generation to processing pipeline

This ensures the thumbnail is properly created from the captured frame
instead of whatever the current preview is when the post-processing
finishes.
Benjamin Schaaf 4 years ago
parent
commit
3f8ee6227f
3 changed files with 51 additions and 25 deletions
  1. 17 17
      main.c
  2. 6 1
      main.h
  3. 28 7
      process_pipeline.c

+ 17 - 17
main.c

@@ -148,7 +148,7 @@ mp_main_set_preview(cairo_surface_t *image)
 				   (GSourceFunc)set_preview, image, NULL);
 }
 
-static void
+void
 draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height,
 			     cairo_surface_t *surface)
 {
@@ -168,35 +168,35 @@ draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_heigh
 	cairo_restore(cr);
 }
 
+struct capture_completed_args {
+	cairo_surface_t *thumb;
+	char *fname;
+};
+
 static bool
-capture_completed(const char *fname)
+capture_completed(struct capture_completed_args *args)
 {
-	strncpy(last_path, fname, 259);
-
-	// Create a thumbnail from the current surface
-	cairo_surface_t *thumb =
-		cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 24, 24);
+	strncpy(last_path, args->fname, 259);
 
-	cairo_t *cr = cairo_create(thumb);
-	draw_surface_scaled_centered(cr, 24, 24, surface);
-	cairo_destroy(cr);
-
-	gtk_image_set_from_surface(GTK_IMAGE(thumb_last), thumb);
+	gtk_image_set_from_surface(GTK_IMAGE(thumb_last), args->thumb);
 
 	gtk_spinner_stop(GTK_SPINNER(process_spinner));
 	gtk_stack_set_visible_child(GTK_STACK(open_last_stack), thumb_last);
 
-	cairo_surface_destroy(thumb);
+	cairo_surface_destroy(args->thumb);
+	g_free(args->fname);
+
 	return false;
 }
 
 void
-mp_main_capture_completed(const char *fname)
+mp_main_capture_completed(cairo_surface_t *thumb, const char *fname)
 {
-	gchar *name = g_strdup(fname);
-
+	struct capture_completed_args *args = malloc(sizeof(struct capture_completed_args));
+	args->thumb = thumb;
+	args->fname = g_strdup(fname);
 	g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE,
-				   (GSourceFunc)capture_completed, name, g_free);
+				   (GSourceFunc)capture_completed, args, free);
 }
 
 static void

+ 6 - 1
main.h

@@ -3,6 +3,8 @@
 #include "camera_config.h"
 #include "gtk/gtk.h"
 
+#define MP_MAIN_THUMB_SIZE 24
+
 struct mp_main_state {
 	const struct mp_camera_config *camera;
 	MPCameraMode mode;
@@ -21,6 +23,9 @@ struct mp_main_state {
 void mp_main_update_state(const struct mp_main_state *state);
 
 void mp_main_set_preview(cairo_surface_t *image);
-void mp_main_capture_completed(const char *fname);
+void mp_main_capture_completed(cairo_surface_t *thumb, const char *fname);
 
 int remap(int value, int input_min, int input_max, int output_min, int output_max);
+
+void draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height,
+			          cairo_surface_t *surface);

+ 28 - 7
process_pipeline.c

@@ -128,7 +128,7 @@ mp_process_pipeline_stop()
 	mp_pipeline_free(pipeline);
 }
 
-static void
+static cairo_surface_t *
 process_image_for_preview(const MPImage *image)
 {
 	uint32_t surface_width, surface_height, skip;
@@ -147,7 +147,23 @@ process_image_for_preview(const MPImage *image)
 		      camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix,
 		      camera->blacklevel, skip);
 
+	// Create a thumbnail from the preview for the last capture
+	cairo_surface_t *thumb = NULL;
+	if (captures_remaining == 1) {
+		printf("Making thumbnail\n");
+		thumb = cairo_image_surface_create(
+			CAIRO_FORMAT_ARGB32, MP_MAIN_THUMB_SIZE, MP_MAIN_THUMB_SIZE);
+
+		cairo_t *cr = cairo_create(thumb);
+		draw_surface_scaled_centered(
+			cr, MP_MAIN_THUMB_SIZE, MP_MAIN_THUMB_SIZE, surface);
+		cairo_destroy(cr);
+	}
+
+	// Pass processed preview to main
 	mp_main_set_preview(surface);
+
+	return thumb;
 }
 
 static void
@@ -302,7 +318,7 @@ process_image_for_capture(const MPImage *image, int count)
 }
 
 static void
-post_process_finished(GSubprocess *proc, GAsyncResult *res, gpointer user_data)
+post_process_finished(GSubprocess *proc, GAsyncResult *res, cairo_surface_t *thumb)
 {
 	char *stdout;
 	g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL);
@@ -320,11 +336,11 @@ post_process_finished(GSubprocess *proc, GAsyncResult *res, gpointer user_data)
 		--path;
 	} while (path > stdout);
 
-	mp_main_capture_completed(path);
+	mp_main_capture_completed(thumb, path);
 }
 
 static void
-process_capture_burst()
+process_capture_burst(cairo_surface_t *thumb)
 {
 	time_t rawtime;
 	time(&rawtime);
@@ -357,7 +373,7 @@ process_capture_burst()
 		NULL,
 		NULL,
 		(GAsyncReadyCallback)post_process_finished,
-		NULL);
+		thumb);
 }
 
 static void
@@ -365,7 +381,7 @@ process_image(MPPipeline *pipeline, const MPImage *image)
 {
 	assert(image->width == mode.width && image->height == mode.height);
 
-	process_image_for_preview(image);
+	cairo_surface_t *thumb = process_image_for_preview(image);
 
 	if (captures_remaining > 0) {
 		int count = burst_length - captures_remaining;
@@ -374,8 +390,13 @@ process_image(MPPipeline *pipeline, const MPImage *image)
 		process_image_for_capture(image, count);
 
 		if (captures_remaining == 0) {
-			process_capture_burst();
+			assert(thumb);
+			process_capture_burst(thumb);
+		} else {
+			assert(!thumb);
 		}
+	} else {
+		assert(!thumb);
 	}
 
 	free(image->data);