Extract all raw subimages as pages

And add missing colour management.
This commit is contained in:
Přemysl Eric Janouch 2023-05-21 23:30:29 +02:00
parent 0359ddf99f
commit 0f1c61ae33
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 49 additions and 35 deletions

View File

@ -1705,38 +1705,11 @@ fail:
#ifdef HAVE_LIBRAW // --------------------------------------------------------- #ifdef HAVE_LIBRAW // ---------------------------------------------------------
static cairo_surface_t * static cairo_surface_t *
open_libraw(const char *data, gsize len, GError **error) load_libraw(libraw_data_t *iprc, GError **error)
{ {
// https://github.com/LibRaw/LibRaw/issues/418
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");
return NULL;
}
#if 0
// TODO(p): Consider setting this--the image is still likely to be
// rendered suboptimally, so why not make it faster.
iprc->params.half_size = 1;
#endif
// TODO(p): Check if we need to set anything for autorotation (sizes.flip).
iprc->params.use_camera_wb = 1;
iprc->params.output_color = 1; // sRGB, TODO(p): Is this used?
iprc->params.output_bps = 8; // This should be the default value.
int err = 0; int err = 0;
if ((err = libraw_open_buffer(iprc, (void *) data, len))) {
set_error(error, libraw_strerror(err));
libraw_close(iprc);
return NULL;
}
// TODO(p): Do we need to check iprc->idata.raw_count? Maybe for TIFFs?
if ((err = libraw_unpack(iprc))) { if ((err = libraw_unpack(iprc))) {
set_error(error, libraw_strerror(err)); set_error(error, libraw_strerror(err));
libraw_close(iprc);
return NULL; return NULL;
} }
@ -1744,7 +1717,6 @@ open_libraw(const char *data, gsize len, GError **error)
// TODO(p): I'm not sure when this is necessary or useful yet. // TODO(p): I'm not sure when this is necessary or useful yet.
if ((err = libraw_adjust_sizes_info_only(iprc))) { if ((err = libraw_adjust_sizes_info_only(iprc))) {
set_error(error, libraw_strerror(err)); set_error(error, libraw_strerror(err));
libraw_close(iprc);
return NULL; return NULL;
} }
#endif #endif
@ -1752,7 +1724,6 @@ open_libraw(const char *data, gsize len, GError **error)
// TODO(p): Documentation says I should look at the code and do it myself. // TODO(p): Documentation says I should look at the code and do it myself.
if ((err = libraw_dcraw_process(iprc))) { if ((err = libraw_dcraw_process(iprc))) {
set_error(error, libraw_strerror(err)); set_error(error, libraw_strerror(err));
libraw_close(iprc);
return NULL; return NULL;
} }
@ -1761,7 +1732,6 @@ open_libraw(const char *data, gsize len, GError **error)
libraw_processed_image_t *image = libraw_dcraw_make_mem_image(iprc, &err); libraw_processed_image_t *image = libraw_dcraw_make_mem_image(iprc, &err);
if (!image) { if (!image) {
set_error(error, libraw_strerror(err)); set_error(error, libraw_strerror(err));
libraw_close(iprc);
return NULL; return NULL;
} }
@ -1769,7 +1739,6 @@ open_libraw(const char *data, gsize len, GError **error)
if (image->colors != 3 || image->bits != 8) { if (image->colors != 3 || image->bits != 8) {
set_error(error, "unexpected number of colours, or bit depth"); set_error(error, "unexpected number of colours, or bit depth");
libraw_dcraw_clear_mem(image); libraw_dcraw_clear_mem(image);
libraw_close(iprc);
return NULL; return NULL;
} }
@ -1781,7 +1750,6 @@ open_libraw(const char *data, gsize len, GError **error)
set_error(error, cairo_status_to_string(surface_status)); set_error(error, cairo_status_to_string(surface_status));
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
libraw_dcraw_clear_mem(image); libraw_dcraw_clear_mem(image);
libraw_close(iprc);
return NULL; return NULL;
} }
@ -1802,10 +1770,56 @@ open_libraw(const char *data, gsize len, GError **error)
cairo_surface_mark_dirty(surface); cairo_surface_mark_dirty(surface);
libraw_dcraw_clear_mem(image); libraw_dcraw_clear_mem(image);
libraw_close(iprc);
return surface; return surface;
} }
static cairo_surface_t *
open_libraw(
const char *data, gsize len, const FivIoOpenContext *ctx, GError **error)
{
// https://github.com/LibRaw/LibRaw/issues/418
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");
return NULL;
}
// TODO(p): Check if we need to set anything for autorotation (sizes.flip).
iprc->params.use_camera_wb = 1;
iprc->params.output_color = 1; // sRGB, TODO(p): Is this used?
iprc->params.output_bps = 8; // This should be the default value.
int err = 0;
cairo_surface_t *result = NULL, *result_tail = NULL;
if ((err = libraw_open_buffer(iprc, (const void *) data, len))) {
set_error(error, libraw_strerror(err));
goto out;
}
if (!try_append_page(load_libraw(iprc, error), &result, &result_tail) ||
ctx->first_frame_only)
goto out;
for (unsigned i = 1; i < iprc->idata.raw_count; i++) {
iprc->rawparams.shot_select = i;
// This library is terrible, we need to start again.
if ((err = libraw_open_buffer(iprc, (const void *) data, len))) {
set_error(error, libraw_strerror(err));
g_clear_pointer(&result, cairo_surface_destroy);
goto out;
}
if (!try_append_page(load_libraw(iprc, error), &result, &result_tail)) {
g_clear_pointer(&result, cairo_surface_destroy);
goto out;
}
}
out:
libraw_close(iprc);
return fiv_io_profile_finalize(result, ctx->screen_profile);
}
#endif // HAVE_LIBRAW --------------------------------------------------------- #endif // HAVE_LIBRAW ---------------------------------------------------------
#ifdef HAVE_RESVG // ---------------------------------------------------------- #ifdef HAVE_RESVG // ----------------------------------------------------------
@ -2811,7 +2825,7 @@ fiv_io_open_from_data(
break; break;
default: default:
#ifdef HAVE_LIBRAW // --------------------------------------------------------- #ifdef HAVE_LIBRAW // ---------------------------------------------------------
if ((surface = open_libraw(data, len, error))) if ((surface = open_libraw(data, len, ctx, error)))
break; break;
// TODO(p): We should try to pass actual processing errors through, // TODO(p): We should try to pass actual processing errors through,