aboutsummaryrefslogtreecommitdiff
path: root/fiv-io.c
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-02-20 19:43:21 +0100
committerPřemysl Eric Janouch <p@janouch.name>2022-02-20 21:14:33 +0100
commit04ec292caf2ec2aa1e6a694996fefa6ec3b5ff6b (patch)
tree98ae92f877537656d49e72d6ecdf0c1efcfd969a /fiv-io.c
parenta28fbf25bcec03ae8cb8e6b22537883f78541d66 (diff)
downloadfiv-04ec292caf2ec2aa1e6a694996fefa6ec3b5ff6b.tar.gz
fiv-04ec292caf2ec2aa1e6a694996fefa6ec3b5ff6b.tar.xz
fiv-04ec292caf2ec2aa1e6a694996fefa6ec3b5ff6b.zip
Make thumbnailers pass back raw images
Diffstat (limited to 'fiv-io.c')
-rw-r--r--fiv-io.c66
1 files changed, 65 insertions, 1 deletions
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 <fnmatch.h>
-typedef struct _ModelEntry {
+typedef struct {
gchar *uri; ///< GIO URI
gchar *collate_key; ///< Collate key for the filename
gint64 mtime_msec; ///< Modification time in milliseconds