From 84f8c9436ffb84ca5d443b906f1ffb7be42a50e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Wed, 8 Jun 2022 02:45:45 +0200 Subject: Downscale embedded thumbnails within minions Otherwise the UI would become unresponsive during loading. --- fiv-thumbnail.c | 133 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 63 deletions(-) (limited to 'fiv-thumbnail.c') diff --git a/fiv-thumbnail.c b/fiv-thumbnail.c index aee3d49..1a9213a 100644 --- a/fiv-thumbnail.c +++ b/fiv-thumbnail.c @@ -130,69 +130,6 @@ render(GFile *target, GBytes *data, gboolean *color_managed, GError **error) return surface; } -cairo_surface_t * -fiv_thumbnail_extract(GFile *target, GError **error) -{ - const char *path = g_file_peek_path(target); - if (!path) { - set_error(error, "thumbnails will only be extracted from local files"); - return NULL; - } - - GMappedFile *mf = g_mapped_file_new(path, FALSE, error); - if (!mf) - return NULL; - - cairo_surface_t *surface = NULL; -#ifndef HAVE_LIBRAW - // TODO(p): Implement our own thumbnail extractors. - set_error(error, "unsupported file"); -#else // HAVE_LIBRAW - libraw_data_t *iprc = libraw_init( - LIBRAW_OPIONS_NO_MEMERR_CALLBACK | LIBRAW_OPIONS_NO_DATAERR_CALLBACK); - if (!iprc) { - set_error(error, "failed to obtain a LibRaw handle"); - goto fail; - } - - int err = 0; - if ((err = libraw_open_buffer(iprc, (void *) g_mapped_file_get_contents(mf), - g_mapped_file_get_length(mf))) || - (err = libraw_unpack_thumb(iprc))) { - set_error(error, libraw_strerror(err)); - goto fail_libraw; - } - - libraw_processed_image_t *image = libraw_dcraw_make_mem_thumb(iprc, &err); - if (!image) { - set_error(error, libraw_strerror(err)); - goto fail_libraw; - } - - gboolean dummy = FALSE; - switch (image->type) { - case LIBRAW_IMAGE_JPEG: - surface = render( - target, g_bytes_new(image->data, image->data_size), &dummy, error); - break; - case LIBRAW_IMAGE_BITMAP: - // TODO(p): Implement this one as well. - default: - set_error(error, "unsupported embedded thumbnail"); - } - - libraw_dcraw_clear_mem(image); -fail_libraw: - libraw_close(iprc); -#endif // HAVE_LIBRAW - -fail: - g_mapped_file_unref(mf); - return surface; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In principle similar to rescale_thumbnail() from fiv-browser.c. static cairo_surface_t * adjust_thumbnail(cairo_surface_t *thumbnail, double row_height) @@ -264,6 +201,76 @@ adjust_thumbnail(cairo_surface_t *thumbnail, double row_height) return scaled; } +cairo_surface_t * +fiv_thumbnail_extract(GFile *target, FivThumbnailSize max_size, GError **error) +{ + const char *path = g_file_peek_path(target); + if (!path) { + set_error(error, "thumbnails will only be extracted from local files"); + return NULL; + } + + GMappedFile *mf = g_mapped_file_new(path, FALSE, error); + if (!mf) + return NULL; + + cairo_surface_t *surface = NULL; +#ifndef HAVE_LIBRAW + // TODO(p): Implement our own thumbnail extractors. + set_error(error, "unsupported file"); +#else // HAVE_LIBRAW + libraw_data_t *iprc = libraw_init( + LIBRAW_OPIONS_NO_MEMERR_CALLBACK | LIBRAW_OPIONS_NO_DATAERR_CALLBACK); + if (!iprc) { + set_error(error, "failed to obtain a LibRaw handle"); + goto fail; + } + + int err = 0; + if ((err = libraw_open_buffer(iprc, (void *) g_mapped_file_get_contents(mf), + g_mapped_file_get_length(mf))) || + (err = libraw_unpack_thumb(iprc))) { + set_error(error, libraw_strerror(err)); + goto fail_libraw; + } + + libraw_processed_image_t *image = libraw_dcraw_make_mem_thumb(iprc, &err); + if (!image) { + set_error(error, libraw_strerror(err)); + goto fail_libraw; + } + + gboolean dummy = FALSE; + switch (image->type) { + case LIBRAW_IMAGE_JPEG: + surface = render( + target, g_bytes_new(image->data, image->data_size), &dummy, error); + break; + case LIBRAW_IMAGE_BITMAP: + // TODO(p): Implement this one as well. + default: + set_error(error, "unsupported embedded thumbnail"); + } + + libraw_dcraw_clear_mem(image); +fail_libraw: + libraw_close(iprc); +#endif // HAVE_LIBRAW + +fail: + g_mapped_file_unref(mf); + if (!surface || max_size < FIV_THUMBNAIL_SIZE_MIN || + max_size > FIV_THUMBNAIL_SIZE_MAX) + return surface; + + cairo_surface_t *result = + adjust_thumbnail(surface, fiv_thumbnail_sizes[max_size].size); + cairo_surface_destroy(surface); + return result; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static WebPData encode_thumbnail(cairo_surface_t *surface) { -- cgit v1.2.3