Downscale embedded thumbnails within minions

Otherwise the UI would become unresponsive during loading.
This commit is contained in:
2022-06-08 02:45:45 +02:00
parent a8f7532abd
commit 84f8c9436f
3 changed files with 76 additions and 67 deletions

View File

@@ -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)
{