diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2021-11-03 12:05:43 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2021-11-03 14:03:28 +0100 |
commit | dbc500ae9f715b57deef27046c37bd2655f482e2 (patch) | |
tree | e325752de067ffdf26d2b3d4cb9c576639894fae /fastiv-browser.c | |
parent | d6ac386dbd90636e565443ca26e66406cac3c17d (diff) | |
download | fiv-dbc500ae9f715b57deef27046c37bd2655f482e2.tar.gz fiv-dbc500ae9f715b57deef27046c37bd2655f482e2.tar.xz fiv-dbc500ae9f715b57deef27046c37bd2655f482e2.zip |
Improve thumbnail scaling and alignment
Stretch thumbnails by up to half a pixel so that they align nicely.
Make use of pixman's sRGB mode.
Diffstat (limited to 'fastiv-browser.c')
-rw-r--r-- | fastiv-browser.c | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/fastiv-browser.c b/fastiv-browser.c index 41c89ed..ba6d8a3 100644 --- a/fastiv-browser.c +++ b/fastiv-browser.c @@ -16,6 +16,7 @@ // #include <math.h> +#include <pixman.h> #include "fastiv-browser.h" #include "fastiv-io.h" @@ -145,12 +146,49 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr) int width = cairo_image_surface_get_width(entry->thumbnail); int height = cairo_image_surface_get_height(entry->thumbnail); - double scale = row_height / height; - if (width * scale > 2 * row_height) - scale = 2 * row_height / width; + double scale_x = 1; + double scale_y = 1; + if (width > 2 * height) { + scale_x = 2 * row_height / width; + scale_y = round(scale_x * height) / height; + } else { + scale_y = row_height / height; + scale_x = round(scale_y * width) / width; + } - int projected_width = round(scale * width); - int projected_height = round(scale * height); + int projected_width = round(scale_x * width); + int projected_height = round(scale_y * height); + cairo_surface_t *scaled = cairo_image_surface_create( + CAIRO_FORMAT_ARGB32, projected_width, projected_height); + + // pixman can take gamma into account when scaling, unlike Cairo. + struct pixman_f_transform xform_floating; + struct pixman_transform xform; + + pixman_image_t *src = pixman_image_create_bits( + PIXMAN_a8r8g8b8_sRGB, width, height, + (uint32_t *) cairo_image_surface_get_data(entry->thumbnail), + cairo_image_surface_get_stride(entry->thumbnail)); + pixman_image_t *dest = pixman_image_create_bits( + PIXMAN_a8r8g8b8_sRGB, + cairo_image_surface_get_width(scaled), + cairo_image_surface_get_height(scaled), + (uint32_t *) cairo_image_surface_get_data(scaled), + cairo_image_surface_get_stride(scaled)); + + pixman_f_transform_init_scale(&xform_floating, scale_x, scale_y); + pixman_f_transform_invert(&xform_floating, &xform_floating); + pixman_transform_from_pixman_f_transform(&xform, &xform_floating); + pixman_image_set_transform(src, &xform); + pixman_image_set_filter(src, PIXMAN_FILTER_BILINEAR, NULL, 0); + pixman_image_set_repeat(src, PIXMAN_REPEAT_PAD); + + pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dest, 0, 0, 0, 0, 0, 0, + projected_width, projected_height); + pixman_image_unref(src); + pixman_image_unref(dest); + + cairo_surface_mark_dirty(scaled); if (occupied_width != 0 && occupied_width + projected_width > allocation.width) { @@ -160,8 +198,8 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr) cairo_save(cr); cairo_translate(cr, occupied_width, y + row_height - projected_height); - cairo_scale(cr, scale, scale); - cairo_set_source_surface(cr, entry->thumbnail, 0, 0); + cairo_set_source_surface(cr, scaled, 0, 0); + cairo_surface_destroy(scaled); cairo_paint(cr); cairo_restore(cr); |