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:
34
main.c
34
main.c
@@ -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
7
main.h
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user