Downscale embedded thumbnails within minions
Otherwise the UI would become unresponsive during loading.
This commit is contained in:
parent
a8f7532abd
commit
84f8c9436f
133
fiv-thumbnail.c
133
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)
|
||||
{
|
||||
|
@ -56,7 +56,9 @@ extern cairo_user_data_key_t fiv_thumbnail_key_lq;
|
||||
gchar *fiv_thumbnail_get_root(void);
|
||||
|
||||
/// Attempts to extract any low-quality thumbnail from fast targets.
|
||||
cairo_surface_t *fiv_thumbnail_extract(GFile *target, GError **error);
|
||||
/// If `max_size` is a valid value, the image will be downscaled as appropriate.
|
||||
cairo_surface_t *fiv_thumbnail_extract(
|
||||
GFile *target, FivThumbnailSize max_size, GError **error);
|
||||
|
||||
/// Generates wide thumbnails of up to the specified size, saves them in cache.
|
||||
/// Returns the surface used for the maximum size, or an error.
|
||||
|
6
fiv.c
6
fiv.c
@ -1773,9 +1773,9 @@ output_thumbnail(const char *path_arg, gboolean extract, const char *size_arg)
|
||||
if (!path_arg)
|
||||
exit_fatal("no path given");
|
||||
|
||||
FivThumbnailSize size = 0;
|
||||
FivThumbnailSize size = FIV_THUMBNAIL_SIZE_COUNT;
|
||||
if (size_arg) {
|
||||
for (; size < FIV_THUMBNAIL_SIZE_COUNT; size++) {
|
||||
for (size = 0; size < FIV_THUMBNAIL_SIZE_COUNT; size++) {
|
||||
if (!strcmp(
|
||||
fiv_thumbnail_sizes[size].thumbnail_spec_name, size_arg))
|
||||
break;
|
||||
@ -1787,7 +1787,7 @@ output_thumbnail(const char *path_arg, gboolean extract, const char *size_arg)
|
||||
GError *error = NULL;
|
||||
GFile *file = g_file_new_for_commandline_arg(path_arg);
|
||||
cairo_surface_t *surface = NULL;
|
||||
if (extract && (surface = fiv_thumbnail_extract(file, &error)))
|
||||
if (extract && (surface = fiv_thumbnail_extract(file, size, &error)))
|
||||
fiv_io_serialize_to_stdout(surface, FIV_IO_SERIALIZE_LOW_QUALITY);
|
||||
else if (size_arg &&
|
||||
(g_clear_error(&error),
|
||||
|
Loading…
Reference in New Issue
Block a user