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.
This commit is contained in:
Benjamin Schaaf
2021-01-06 23:24:05 +11:00
parent 21547ed210
commit 3f8ee6227f
3 changed files with 51 additions and 25 deletions

34
main.c
View File

@@ -148,7 +148,7 @@ mp_main_set_preview(cairo_surface_t *image)
(GSourceFunc)set_preview, image, NULL); (GSourceFunc)set_preview, image, NULL);
} }
static void void
draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height, draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height,
cairo_surface_t *surface) 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); cairo_restore(cr);
} }
struct capture_completed_args {
cairo_surface_t *thumb;
char *fname;
};
static bool static bool
capture_completed(const char *fname) capture_completed(struct capture_completed_args *args)
{ {
strncpy(last_path, fname, 259); strncpy(last_path, args->fname, 259);
// Create a thumbnail from the current surface gtk_image_set_from_surface(GTK_IMAGE(thumb_last), args->thumb);
cairo_surface_t *thumb =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 24, 24);
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_spinner_stop(GTK_SPINNER(process_spinner)); gtk_spinner_stop(GTK_SPINNER(process_spinner));
gtk_stack_set_visible_child(GTK_STACK(open_last_stack), thumb_last); 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; return false;
} }
void 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, 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 static void

7
main.h
View File

@@ -3,6 +3,8 @@
#include "camera_config.h" #include "camera_config.h"
#include "gtk/gtk.h" #include "gtk/gtk.h"
#define MP_MAIN_THUMB_SIZE 24
struct mp_main_state { struct mp_main_state {
const struct mp_camera_config *camera; const struct mp_camera_config *camera;
MPCameraMode mode; MPCameraMode mode;
@@ -21,6 +23,9 @@ struct mp_main_state {
void mp_main_update_state(const struct mp_main_state *state); void mp_main_update_state(const struct mp_main_state *state);
void mp_main_set_preview(cairo_surface_t *image); 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); 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);

View File

@@ -128,7 +128,7 @@ mp_process_pipeline_stop()
mp_pipeline_free(pipeline); mp_pipeline_free(pipeline);
} }
static void static cairo_surface_t *
process_image_for_preview(const MPImage *image) process_image_for_preview(const MPImage *image)
{ {
uint32_t surface_width, surface_height, skip; 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->previewmatrix[0] == 0 ? NULL : camera->previewmatrix,
camera->blacklevel, skip); 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); mp_main_set_preview(surface);
return thumb;
} }
static void static void
@@ -302,7 +318,7 @@ process_image_for_capture(const MPImage *image, int count)
} }
static void 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; char *stdout;
g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL); 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; --path;
} while (path > stdout); } while (path > stdout);
mp_main_capture_completed(path); mp_main_capture_completed(thumb, path);
} }
static void static void
process_capture_burst() process_capture_burst(cairo_surface_t *thumb)
{ {
time_t rawtime; time_t rawtime;
time(&rawtime); time(&rawtime);
@@ -357,7 +373,7 @@ process_capture_burst()
NULL, NULL,
NULL, NULL,
(GAsyncReadyCallback)post_process_finished, (GAsyncReadyCallback)post_process_finished,
NULL); thumb);
} }
static void static void
@@ -365,7 +381,7 @@ process_image(MPPipeline *pipeline, const MPImage *image)
{ {
assert(image->width == mode.width && image->height == mode.height); 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) { if (captures_remaining > 0) {
int count = burst_length - captures_remaining; int count = burst_length - captures_remaining;
@@ -374,8 +390,13 @@ process_image(MPPipeline *pipeline, const MPImage *image)
process_image_for_capture(image, count); process_image_for_capture(image, count);
if (captures_remaining == 0) { if (captures_remaining == 0) {
process_capture_burst(); assert(thumb);
process_capture_burst(thumb);
} else {
assert(!thumb);
} }
} else {
assert(!thumb);
} }
free(image->data); free(image->data);