Don't use a side buffer to load thumbnails
Undoing part of a recent commit.
This commit is contained in:
parent
6f86911df6
commit
e835c889a1
51
fastiv-io.c
51
fastiv-io.c
|
@ -645,12 +645,12 @@ read_spng_thumbnail(
|
||||||
const gchar *path, const gchar *uri, time_t mtime, GError **error)
|
const gchar *path, const gchar *uri, time_t mtime, GError **error)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
cairo_surface_t *result = NULL;
|
||||||
if (!(fp = fopen(path, "rb"))) {
|
if (!(fp = fopen(path, "rb"))) {
|
||||||
set_error(error, g_strerror(errno));
|
set_error(error, g_strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t *result = NULL;
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
spng_ctx *ctx = spng_ctx_new(0);
|
spng_ctx *ctx = spng_ctx_new(0);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
|
@ -671,7 +671,22 @@ read_spng_thumbnail(
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *data = g_malloc0(size);
|
struct spng_ihdr ihdr = {};
|
||||||
|
spng_get_ihdr(ctx, &ihdr);
|
||||||
|
cairo_surface_t *surface = cairo_image_surface_create(
|
||||||
|
CAIRO_FORMAT_ARGB32, ihdr.width, ihdr.height);
|
||||||
|
|
||||||
|
cairo_status_t surface_status = cairo_surface_status(surface);
|
||||||
|
if (surface_status != CAIRO_STATUS_SUCCESS) {
|
||||||
|
set_error(error, cairo_status_to_string(surface_status));
|
||||||
|
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);
|
||||||
|
|
||||||
|
cairo_surface_flush(surface);
|
||||||
if ((err = spng_decode_image(ctx, data, size, SPNG_FMT_RGBA8,
|
if ((err = spng_decode_image(ctx, data, size, SPNG_FMT_RGBA8,
|
||||||
SPNG_DECODE_TRNS | SPNG_DECODE_GAMMA))) {
|
SPNG_DECODE_TRNS | SPNG_DECODE_GAMMA))) {
|
||||||
set_error(error, spng_strerror(err));
|
set_error(error, spng_strerror(err));
|
||||||
|
@ -686,47 +701,31 @@ read_spng_thumbnail(
|
||||||
goto fail_data;
|
goto fail_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct spng_ihdr ihdr = {};
|
|
||||||
spng_get_ihdr(ctx, &ihdr);
|
|
||||||
cairo_surface_t *surface = cairo_image_surface_create(
|
|
||||||
CAIRO_FORMAT_ARGB32, ihdr.width, ihdr.height);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
// 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);
|
|
||||||
|
|
||||||
struct spng_trns trns = {};
|
struct spng_trns trns = {};
|
||||||
if (ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA ||
|
if (ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA ||
|
||||||
ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR_ALPHA ||
|
ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR_ALPHA ||
|
||||||
!spng_get_trns(ctx, &trns)) {
|
!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],
|
const uint8_t *unit = (const uint8_t *) &data[i],
|
||||||
a = unit[3],
|
a = unit[3],
|
||||||
b = unit[2] * a / 255,
|
b = unit[2] * a / 255,
|
||||||
g = unit[1] * a / 255,
|
g = unit[1] * a / 255,
|
||||||
r = unit[0] * 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 {
|
} else {
|
||||||
for (size_t i = size / sizeof *output; i--; ) {
|
for (size_t i = size / sizeof *data; i--; ) {
|
||||||
uint32_t x = g_ntohl(data[i]);
|
uint32_t rgba = g_ntohl(data[i]);
|
||||||
output[i] = x << 24 | x >> 8;
|
data[i] = rgba << 24 | rgba >> 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_mark_dirty((result = surface));
|
cairo_surface_mark_dirty((result = surface));
|
||||||
|
|
||||||
fail_data:
|
fail_data:
|
||||||
free(data);
|
if (!result)
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
fail:
|
fail:
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
fail_init:
|
fail_init:
|
||||||
|
|
Loading…
Reference in New Issue