Fix #112586: VSE can't use multi-layer EXR images

The rest of blender does handle multi-layer EXR images, using the
"combined" or RGBA/RGB layers when the visual result is needed. Make
VSE do the same.

While fixing this, I found several issues in other not well tested code
and had to fix them:

- IMB_buffer_float_from_float_threaded was wrongly using source channels
  as destination channels, producing garbage result.
- IMB_scale_into_new was not assigning channels to destination image.

Pull Request: https://projects.blender.org/blender/blender/pulls/132790
This commit is contained in:
Aras Pranckevicius
2025-01-08 10:45:24 +01:00
committed by Aras Pranckevicius
parent d7a480e863
commit 5ef08c2a96
5 changed files with 34 additions and 6 deletions

View File

@@ -518,7 +518,7 @@ static void imb_buffer_float_from_float_thread_do(void *data_v, int scanline)
const int num_scanlines = 1;
FloatToFloatThreadData *data = (FloatToFloatThreadData *)data_v;
size_t offset_from = size_t(scanline) * data->stride_from * data->channels_from;
size_t offset_to = size_t(scanline) * data->stride_to * data->channels_from;
size_t offset_to = size_t(scanline) * data->stride_to * 4;
IMB_buffer_float_from_float(data->rect_to + offset_to,
data->rect_from + offset_from,
data->channels_from,

View File

@@ -879,6 +879,7 @@ ImBuf *IMB_scale_into_new(
/* Create result image. */
ImBuf *dst = IMB_allocImBuf(newx, newy, ibuf->planes, IB_uninitialized_pixels);
dst->channels = ibuf->channels;
IMB_metadata_copy(dst, ibuf);
dst->colormanage_flag = ibuf->colormanage_flag;
if (dst_byte != nullptr) {

View File

@@ -843,6 +843,30 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
/** \name Individual strip rendering functions
* \{ */
static void convert_multilayer_ibuf(ImBuf *ibuf)
{
/* Load the combined/RGB layer, if this is a multi-layer image. */
BKE_movieclip_convert_multilayer_ibuf(ibuf);
/* Combined layer might be non-4 channels, however the rest
* of sequencer assumes RGBA everywhere. Convert to 4 channel if needed. */
if (ibuf->float_buffer.data != nullptr && ibuf->channels != 4) {
float *dst = static_cast<float *>(MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__));
IMB_buffer_float_from_float_threaded(dst,
ibuf->float_buffer.data,
ibuf->channels,
IB_PROFILE_LINEAR_RGB,
IB_PROFILE_LINEAR_RGB,
false,
ibuf->x,
ibuf->y,
ibuf->x,
ibuf->x);
IMB_assign_float_buffer(ibuf, dst, IB_TAKE_OWNERSHIP);
ibuf->channels = 4;
}
}
/**
* Render individual view for multi-view or single (default view) for mono-view.
*/
@@ -855,7 +879,7 @@ static ImBuf *seq_render_image_strip_view(const SeqRenderData *context,
{
ImBuf *ibuf = nullptr;
int flag = IB_rect | IB_metadata;
int flag = IB_rect | IB_metadata | IB_multilayer;
if (strip->alpha_mode == SEQ_ALPHA_PREMUL) {
flag |= IB_alphamode_premul;
}
@@ -873,6 +897,7 @@ static ImBuf *seq_render_image_strip_view(const SeqRenderData *context,
if (ibuf == nullptr) {
return nullptr;
}
convert_multilayer_ibuf(ibuf);
/* We don't need both (speed reasons)! */
if (ibuf->float_buffer.data != nullptr && ibuf->byte_buffer.data != nullptr) {

View File

@@ -211,8 +211,9 @@ void SEQ_add_image_init_alpha_mode(Strip *strip)
/* Initialize input color space. */
if (strip->type == STRIP_TYPE_IMAGE) {
ibuf = IMB_loadiffname(
filepath, IB_test | IB_alphamode_detect, strip->data->colorspace_settings.name);
ibuf = IMB_loadiffname(filepath,
IB_test | IB_multilayer | IB_alphamode_detect,
strip->data->colorspace_settings.name);
/* Byte images are default to straight alpha, however sequencer
* works in premul space, so mark strip to be premultiplied first.
@@ -255,7 +256,8 @@ Strip *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoad
char file_path[FILE_MAX];
STRNCPY(file_path, load_data->path);
BLI_path_abs(file_path, BKE_main_blendfile_path(bmain));
ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, strip->data->colorspace_settings.name);
ImBuf *ibuf = IMB_loadiffname(
file_path, IB_rect | IB_multilayer, strip->data->colorspace_settings.name);
if (ibuf != nullptr) {
/* Set image resolution. Assume that all images in sequence are same size. This fields are only
* informative. */