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;
|
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.
|
// In principle similar to rescale_thumbnail() from fiv-browser.c.
|
||||||
static cairo_surface_t *
|
static cairo_surface_t *
|
||||||
adjust_thumbnail(cairo_surface_t *thumbnail, double row_height)
|
adjust_thumbnail(cairo_surface_t *thumbnail, double row_height)
|
||||||
@ -264,6 +201,76 @@ adjust_thumbnail(cairo_surface_t *thumbnail, double row_height)
|
|||||||
return scaled;
|
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
|
static WebPData
|
||||||
encode_thumbnail(cairo_surface_t *surface)
|
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);
|
gchar *fiv_thumbnail_get_root(void);
|
||||||
|
|
||||||
/// Attempts to extract any low-quality thumbnail from fast targets.
|
/// 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.
|
/// Generates wide thumbnails of up to the specified size, saves them in cache.
|
||||||
/// Returns the surface used for the maximum size, or an error.
|
/// 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)
|
if (!path_arg)
|
||||||
exit_fatal("no path given");
|
exit_fatal("no path given");
|
||||||
|
|
||||||
FivThumbnailSize size = 0;
|
FivThumbnailSize size = FIV_THUMBNAIL_SIZE_COUNT;
|
||||||
if (size_arg) {
|
if (size_arg) {
|
||||||
for (; size < FIV_THUMBNAIL_SIZE_COUNT; size++) {
|
for (size = 0; size < FIV_THUMBNAIL_SIZE_COUNT; size++) {
|
||||||
if (!strcmp(
|
if (!strcmp(
|
||||||
fiv_thumbnail_sizes[size].thumbnail_spec_name, size_arg))
|
fiv_thumbnail_sizes[size].thumbnail_spec_name, size_arg))
|
||||||
break;
|
break;
|
||||||
@ -1787,7 +1787,7 @@ output_thumbnail(const char *path_arg, gboolean extract, const char *size_arg)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GFile *file = g_file_new_for_commandline_arg(path_arg);
|
GFile *file = g_file_new_for_commandline_arg(path_arg);
|
||||||
cairo_surface_t *surface = NULL;
|
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);
|
fiv_io_serialize_to_stdout(surface, FIV_IO_SERIALIZE_LOW_QUALITY);
|
||||||
else if (size_arg &&
|
else if (size_arg &&
|
||||||
(g_clear_error(&error),
|
(g_clear_error(&error),
|
||||||
|
Loading…
Reference in New Issue
Block a user