From 04ec292caf2ec2aa1e6a694996fefa6ec3b5ff6b Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch Date: Sun, 20 Feb 2022 19:43:21 +0100 Subject: Make thumbnailers pass back raw images --- fiv-io.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) (limited to 'fiv-io.c') diff --git a/fiv-io.c b/fiv-io.c index 1778120..870624f 100644 --- a/fiv-io.c +++ b/fiv-io.c @@ -2703,13 +2703,77 @@ fiv_io_open_from_data( return surface; } +// --- Thumbnail passing utilities --------------------------------------------- + +typedef struct { + int width, height, stride, format; +} CairoHeader; + +void +fiv_io_serialize_to_stdout(cairo_surface_t *surface) +{ + if (!surface || cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE) + return; + +#ifdef G_OS_UNIX + // Common courtesy, this is never what the user wants. + if (isatty(fileno(stdout))) + return; +#endif + + CairoHeader h = { + .width = cairo_image_surface_get_width(surface), + .height = cairo_image_surface_get_height(surface), + .stride = cairo_image_surface_get_stride(surface), + .format = cairo_image_surface_get_format(surface), + }; + + // Cairo lets pixman initialize image surfaces. + // pixman allocates stride * height, not omitting those trailing bytes. + const unsigned char *data = cairo_image_surface_get_data(surface); + if (fwrite(&h, sizeof h, 1, stdout) == 1) + fwrite(data, 1, h.stride * h.height, stdout); +} + +cairo_surface_t * +fiv_io_deserialize(GBytes *bytes) +{ + CairoHeader h = {}; + GByteArray *array = g_bytes_unref_to_array(bytes); + if (array->len < sizeof h) { + g_byte_array_unref(array); + return NULL; + } + + h = *(CairoHeader *) array->data; + if (h.width < 1 || h.height < 1 || h.stride < h.width || + G_MAXSIZE / (gsize) h.stride < (gsize) h.height || + array->len - sizeof h < (gsize) h.stride * (gsize) h.height) { + g_byte_array_unref(array); + return NULL; + } + + cairo_surface_t *surface = cairo_image_surface_create_for_data( + array->data + sizeof h, h.format, h.width, h.height, h.stride); + if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { + cairo_surface_destroy(surface); + g_byte_array_unref(array); + return NULL; + } + + static cairo_user_data_key_t key; + cairo_surface_set_user_data( + surface, &key, array, (cairo_destroy_func_t) g_byte_array_unref); + return surface; +} + // --- Filesystem -------------------------------------------------------------- #include "xdg.h" #include -typedef struct _ModelEntry { +typedef struct { gchar *uri; ///< GIO URI gchar *collate_key; ///< Collate key for the filename gint64 mtime_msec; ///< Modification time in milliseconds -- cgit v1.2.3-54-g00ecf