Compare commits

..

3 Commits

Author SHA1 Message Date
cdb8d852a6
Pre-scale loaded thumbnails, and only when needed 2021-11-03 14:15:34 +01:00
dbc500ae9f
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.
2021-11-03 14:03:28 +01:00
d6ac386dbd
Bump wuffs
No great differences.
2021-11-02 04:53:33 +01:00
4 changed files with 71 additions and 19 deletions

View File

@ -18,8 +18,8 @@ a package with the latest development version from Archlinux's AUR.
Building and Running
--------------------
Build dependencies: Meson, pkg-config +
Runtime dependencies: gtk+-3.0, shared-mime-info, libpng>=1.5.4, libturbojpeg,
LibRaw (optional)
Runtime dependencies: gtk+-3.0, pixman-1, shared-mime-info, libpng>=1.5.4,
libturbojpeg, LibRaw (optional)
$ git clone --recursive https://git.janouch.name/p/fastiv.git
$ meson builddir

View File

@ -16,6 +16,7 @@
//
#include <math.h>
#include <pixman.h>
#include "fastiv-browser.h"
#include "fastiv-io.h"
@ -36,6 +37,8 @@ entry_free(Entry *self)
cairo_surface_destroy(self->thumbnail);
}
static const double g_row_height = 256;
// --- Boilerplate -------------------------------------------------------------
struct _FastivBrowser {
@ -134,8 +137,6 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr)
gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0,
allocation.width, allocation.height);
const double row_height = 256;
gint occupied_width = 0, y = 0;
for (guint i = 0; i < self->entries->len; i++) {
const Entry *entry = &g_array_index(self->entries, Entry, i);
@ -144,28 +145,19 @@ 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;
int projected_width = round(scale * width);
int projected_height = round(scale * height);
if (occupied_width != 0 &&
occupied_width + projected_width > allocation.width) {
occupied_width + width > allocation.width) {
occupied_width = 0;
y += row_height;
y += g_row_height;
}
cairo_save(cr);
cairo_translate(cr, occupied_width, y + row_height - projected_height);
cairo_scale(cr, scale, scale);
cairo_translate(cr, occupied_width, y + g_row_height - height);
cairo_set_source_surface(cr, entry->thumbnail, 0, 0);
cairo_paint(cr);
cairo_restore(cr);
occupied_width += projected_width;
occupied_width += width;
}
return TRUE;
}
@ -203,6 +195,64 @@ fastiv_browser_init(FastivBrowser *self)
self->selected = -1;
}
static cairo_surface_t *
rescale_thumbnail(cairo_surface_t *thumbnail)
{
if (!thumbnail)
return thumbnail;
int width = cairo_image_surface_get_width(thumbnail);
int height = cairo_image_surface_get_height(thumbnail);
double scale_x = 1;
double scale_y = 1;
if (width > 2 * height) {
scale_x = 2 * g_row_height / width;
scale_y = round(scale_x * height) / height;
} else {
scale_y = g_row_height / height;
scale_x = round(scale_y * width) / width;
}
if (scale_x == 1 && scale_y == 1)
return thumbnail;
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(thumbnail),
cairo_image_surface_get_stride(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_destroy(thumbnail);
cairo_surface_mark_dirty(scaled);
return scaled;
}
void
fastiv_browser_load(FastivBrowser *self, const char *path)
{
@ -221,7 +271,8 @@ fastiv_browser_load(FastivBrowser *self, const char *path)
gchar *subpath = g_build_filename(path, filename, NULL);
g_array_append_val(self->entries,
((Entry){
.thumbnail = fastiv_io_lookup_thumbnail(subpath),
.thumbnail =
rescale_thumbnail(fastiv_io_lookup_thumbnail(subpath)),
.filename = subpath,
}));
}

View File

@ -6,6 +6,7 @@ dependencies = [
dependency('gtk+-3.0'),
dependency('libturbojpeg'),
dependency('libpng', version : '>=1.5.4'),
dependency('pixman-1'),
libraw,
meson.get_compiler('c').find_library('m', required : false),
]

@ -1 +1 @@
Subproject commit c9d2ed7983381ab659a56e0b8bc0d077e421f697
Subproject commit 7804ffe150db6f0dd2c745587b9327fa4f150ee5