aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2021-11-15 10:16:10 +0100
committerPřemysl Eric Janouch <p@janouch.name>2021-11-15 10:30:02 +0100
commite835c889a178d2bdfcf52220e461ecfcd9067afb (patch)
tree5651a81c3c620a2420f114ed7ee245ffc3008584
parent6f86911df69bcfcd69d90feef43fef3450fc36e5 (diff)
downloadfiv-e835c889a178d2bdfcf52220e461ecfcd9067afb.tar.gz
fiv-e835c889a178d2bdfcf52220e461ecfcd9067afb.tar.xz
fiv-e835c889a178d2bdfcf52220e461ecfcd9067afb.zip
Don't use a side buffer to load thumbnails
Undoing part of a recent commit.
-rw-r--r--fastiv-io.c49
1 files changed, 24 insertions, 25 deletions
diff --git a/fastiv-io.c b/fastiv-io.c
index 64bbb3c..d63d336 100644
--- a/fastiv-io.c
+++ b/fastiv-io.c
@@ -645,12 +645,12 @@ read_spng_thumbnail(
const gchar *path, const gchar *uri, time_t mtime, GError **error)
{
FILE *fp;
+ cairo_surface_t *result = NULL;
if (!(fp = fopen(path, "rb"))) {
set_error(error, g_strerror(errno));
return NULL;
}
- cairo_surface_t *result = NULL;
errno = 0;
spng_ctx *ctx = spng_ctx_new(0);
if (!ctx) {
@@ -671,21 +671,6 @@ read_spng_thumbnail(
goto fail;
}
- uint32_t *data = g_malloc0(size);
- if ((err = spng_decode_image(ctx, data, size, SPNG_FMT_RGBA8,
- SPNG_DECODE_TRNS | SPNG_DECODE_GAMMA))) {
- set_error(error, spng_strerror(err));
- goto fail_data;
- }
-
- // The specification does not say where the required metadata should be,
- // it could very well be broken up into two parts.
- if (check_spng_thumbnail(ctx, uri, mtime, &err) != true) {
- set_error(
- error, err ? spng_strerror(err) : "mismatch or not a thumbnail");
- goto fail_data;
- }
-
struct spng_ihdr ihdr = {};
spng_get_ihdr(ctx, &ihdr);
cairo_surface_t *surface = cairo_image_surface_create(
@@ -694,39 +679,53 @@ read_spng_thumbnail(
cairo_status_t surface_status = cairo_surface_status(surface);
if (surface_status != CAIRO_STATUS_SUCCESS) {
set_error(error, cairo_status_to_string(surface_status));
- cairo_surface_destroy(surface);
goto fail_data;
}
+ uint32_t *data = (uint32_t *) cairo_image_surface_get_data(surface);
g_assert((size_t) cairo_image_surface_get_stride(surface) *
cairo_image_surface_get_height(surface) == size);
- // pixman can be mildly abused to do this operation, but it won't be faster.
- uint32_t *output = (uint32_t *) cairo_image_surface_get_data(surface);
cairo_surface_flush(surface);
+ if ((err = spng_decode_image(ctx, data, size, SPNG_FMT_RGBA8,
+ SPNG_DECODE_TRNS | SPNG_DECODE_GAMMA))) {
+ set_error(error, spng_strerror(err));
+ goto fail_data;
+ }
+ // The specification does not say where the required metadata should be,
+ // it could very well be broken up into two parts.
+ if (check_spng_thumbnail(ctx, uri, mtime, &err) != true) {
+ set_error(
+ error, err ? spng_strerror(err) : "mismatch or not a thumbnail");
+ goto fail_data;
+ }
+
+ // pixman can be mildly abused to do this operation, but it won't be faster.
struct spng_trns trns = {};
if (ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA ||
ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR_ALPHA ||
!spng_get_trns(ctx, &trns)) {
- for (size_t i = size / sizeof *output; i--; ) {
+ for (size_t i = size / sizeof *data; i--; ) {
const uint8_t *unit = (const uint8_t *) &data[i],
a = unit[3],
b = unit[2] * a / 255,
g = unit[1] * a / 255,
r = unit[0] * a / 255;
- output[i] = a << 24 | r << 16 | g << 8 | b;
+ data[i] = a << 24 | r << 16 | g << 8 | b;
}
} else {
- for (size_t i = size / sizeof *output; i--; ) {
- uint32_t x = g_ntohl(data[i]);
- output[i] = x << 24 | x >> 8;
+ for (size_t i = size / sizeof *data; i--; ) {
+ uint32_t rgba = g_ntohl(data[i]);
+ data[i] = rgba << 24 | rgba >> 8;
}
}
cairo_surface_mark_dirty((result = surface));
+
fail_data:
- free(data);
+ if (!result)
+ cairo_surface_destroy(surface);
fail:
spng_ctx_free(ctx);
fail_init: