diff options
| -rw-r--r-- | fiv-thumbnail.c | 133 | ||||
| -rw-r--r-- | fiv-thumbnail.h | 4 | ||||
| -rw-r--r-- | fiv.c | 6 | 
3 files changed, 76 insertions, 67 deletions
| 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)  { diff --git a/fiv-thumbnail.h b/fiv-thumbnail.h index 301a641..1a22c75 100644 --- a/fiv-thumbnail.h +++ b/fiv-thumbnail.h @@ -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. @@ -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), | 
