Sfoglia il codice sorgente

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 anni fa
parent
commit
3f8ee6227f
3 ha cambiato i file con 51 aggiunte e 25 eliminazioni
  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);