Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2021-09-23 20:22:15 +0300
committerBrecht Van Lommel <brecht@blender.org>2021-09-23 21:45:42 +0300
commit1bdaf0ebec5bafd6c0b945de49cc74515b93fe1c (patch)
treeefd40e84ee50d8a7a3634affdcabee2e3f166c63
parent7fb2b50e5dace1eeaa777965c445f85b708eaae0 (diff)
Fix T91638: image editor Open Cached Render not loading some passes
Previously this was only loading built-in render passes. Now instead of trying to load the scene render passes, load whatever passes exist in the cache file.
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc7
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp161
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_multi.h15
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_stub.cpp19
-rw-r--r--source/blender/render/intern/render_result.c31
5 files changed, 133 insertions, 100 deletions
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc
index 5b6f650d40e..d436b00a6e3 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc
@@ -86,8 +86,8 @@ void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filenam
/* prepare the file with all the channels */
- if (IMB_exr_begin_write(
- exrhandle, filename, width, height, this->m_format->exr_codec, nullptr) == 0) {
+ if (!IMB_exr_begin_write(
+ exrhandle, filename, width, height, this->m_format->exr_codec, nullptr)) {
printf("Error Writing Singlelayer Multiview Openexr\n");
IMB_exr_close(exrhandle);
}
@@ -200,8 +200,7 @@ void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename
/* prepare the file with all the channels for the header */
StampData *stamp_data = createStampData();
- if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data) ==
- 0) {
+ if (!IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data)) {
printf("Error Writing Multilayer Multiview Openexr\n");
IMB_exr_close(exrhandle);
BKE_stamp_data_free(stamp_data);
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index cd323e72003..ec0a085700a 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -681,6 +681,8 @@ struct ExrLayer {
ListBase passes;
};
+static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data);
+
/* ********************** */
void *IMB_exr_get_handle(void)
@@ -839,12 +841,12 @@ void IMB_exr_add_channel(void *handle,
}
/* used for output files (from RenderResult) (single and multilayer, single and multiview) */
-int IMB_exr_begin_write(void *handle,
- const char *filename,
- int width,
- int height,
- int compress,
- const StampData *stamp)
+bool IMB_exr_begin_write(void *handle,
+ const char *filename,
+ int width,
+ int height,
+ int compress,
+ const StampData *stamp)
{
ExrHandle *data = (ExrHandle *)handle;
Header header(width, height);
@@ -962,51 +964,64 @@ void IMB_exrtile_begin_write(
}
/* read from file */
-int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height)
+bool IMB_exr_begin_read(
+ void *handle, const char *filename, int *width, int *height, const bool parse_channels)
{
ExrHandle *data = (ExrHandle *)handle;
ExrChannel *echan;
/* 32 is arbitrary, but zero length files crashes exr. */
- if (BLI_exists(filename) && BLI_file_size(filename) > 32) {
- /* avoid crash/abort when we don't have permission to write here */
- try {
- data->ifile_stream = new IFileStream(filename);
- data->ifile = new MultiPartInputFile(*(data->ifile_stream));
- }
- catch (const std::exception &) {
- delete data->ifile;
- delete data->ifile_stream;
+ if (!(BLI_exists(filename) && BLI_file_size(filename) > 32)) {
+ return false;
+ }
- data->ifile = nullptr;
- data->ifile_stream = nullptr;
- }
+ /* avoid crash/abort when we don't have permission to write here */
+ try {
+ data->ifile_stream = new IFileStream(filename);
+ data->ifile = new MultiPartInputFile(*(data->ifile_stream));
+ }
+ catch (const std::exception &) {
+ delete data->ifile;
+ delete data->ifile_stream;
- if (data->ifile) {
- Box2i dw = data->ifile->header(0).dataWindow();
- data->width = *width = dw.max.x - dw.min.x + 1;
- data->height = *height = dw.max.y - dw.min.y + 1;
+ data->ifile = nullptr;
+ data->ifile_stream = nullptr;
+ }
- imb_exr_get_views(*data->ifile, *data->multiView);
+ if (!data->ifile) {
+ return false;
+ }
- std::vector<MultiViewChannelName> channels;
- GetChannelsInMultiPartFile(*data->ifile, channels);
+ Box2i dw = data->ifile->header(0).dataWindow();
+ data->width = *width = dw.max.x - dw.min.x + 1;
+ data->height = *height = dw.max.y - dw.min.y + 1;
- for (const MultiViewChannelName &channel : channels) {
- IMB_exr_add_channel(
- data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false);
+ if (parse_channels) {
+ /* Parse channels into view/layer/pass. */
+ if (!imb_exr_multilayer_parse_channels_from_file(data)) {
+ return false;
+ }
+ }
+ else {
+ /* Read view and channels without parsing. */
+ imb_exr_get_views(*data->ifile, *data->multiView);
- echan = (ExrChannel *)data->channels.last;
- echan->m->name = channel.name;
- echan->m->view = channel.view;
- echan->m->part_number = channel.part_number;
- echan->m->internal_name = channel.internal_name;
- }
+ std::vector<MultiViewChannelName> channels;
+ GetChannelsInMultiPartFile(*data->ifile, channels);
+
+ for (const MultiViewChannelName &channel : channels) {
+ IMB_exr_add_channel(
+ data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false);
- return 1;
+ echan = (ExrChannel *)data->channels.last;
+ echan->m->name = channel.name;
+ echan->m->view = channel.view;
+ echan->m->part_number = channel.part_number;
+ echan->m->internal_name = channel.internal_name;
}
}
- return 0;
+
+ return true;
}
/* still clumsy name handling, layers/channels can be ordered as list in list later */
@@ -1524,25 +1539,8 @@ static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname)
return pass;
}
-/* creates channels, makes a hierarchy and assigns memory to channels */
-static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
- MultiPartInputFile &file,
- int width,
- int height)
+static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data)
{
- ExrLayer *lay;
- ExrPass *pass;
- ExrChannel *echan;
- ExrHandle *data = (ExrHandle *)IMB_exr_get_handle();
- int a;
- char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME];
-
- data->ifile_stream = &file_stream;
- data->ifile = &file;
-
- data->width = width;
- data->height = height;
-
std::vector<MultiViewChannelName> channels;
GetChannelsInMultiPartFile(*data->ifile, channels);
@@ -1552,7 +1550,7 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
IMB_exr_add_channel(
data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false);
- echan = (ExrChannel *)data->channels.last;
+ ExrChannel *echan = (ExrChannel *)data->channels.last;
echan->m->name = channel.name;
echan->m->view = channel.view;
echan->m->part_number = channel.part_number;
@@ -1561,7 +1559,9 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
/* now try to sort out how to assign memory to the channels */
/* first build hierarchical layer list */
- for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
+ ExrChannel *echan = (ExrChannel *)data->channels.first;
+ for (; echan; echan = echan->next) {
+ char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME];
if (imb_exr_split_channel_name(echan, layname, passname)) {
const char *view = echan->m->view.c_str();
@@ -1591,21 +1591,20 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
}
if (echan) {
printf("error, too many channels in one pass: %s\n", echan->m->name.c_str());
- IMB_exr_close(data);
- return nullptr;
+ return false;
}
/* with some heuristics, try to merge the channels in buffers */
- for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) {
- for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) {
+ for (ExrLayer *lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) {
+ for (ExrPass *pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) {
if (pass->totchan) {
- pass->rect = (float *)MEM_callocN(width * height * pass->totchan * sizeof(float),
- "pass rect");
+ pass->rect = (float *)MEM_callocN(
+ data->width * data->height * pass->totchan * sizeof(float), "pass rect");
if (pass->totchan == 1) {
- echan = pass->chan[0];
+ ExrChannel *echan = pass->chan[0];
echan->rect = pass->rect;
echan->xstride = 1;
- echan->ystride = width;
+ echan->ystride = data->width;
pass->chan_id[0] = echan->chan_id;
}
else {
@@ -1634,20 +1633,20 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
lookup[(unsigned int)'V'] = 1;
lookup[(unsigned int)'A'] = 2;
}
- for (a = 0; a < pass->totchan; a++) {
+ for (int a = 0; a < pass->totchan; a++) {
echan = pass->chan[a];
echan->rect = pass->rect + lookup[(unsigned int)echan->chan_id];
echan->xstride = pass->totchan;
- echan->ystride = width * pass->totchan;
+ echan->ystride = data->width * pass->totchan;
pass->chan_id[(unsigned int)lookup[(unsigned int)echan->chan_id]] = echan->chan_id;
}
}
else { /* unknown */
- for (a = 0; a < pass->totchan; a++) {
- echan = pass->chan[a];
+ for (int a = 0; a < pass->totchan; a++) {
+ ExrChannel *echan = pass->chan[a];
echan->rect = pass->rect + a;
echan->xstride = pass->totchan;
- echan->ystride = width * pass->totchan;
+ echan->ystride = data->width * pass->totchan;
pass->chan_id[a] = echan->chan_id;
}
}
@@ -1656,6 +1655,28 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
}
}
+ return true;
+}
+
+/* creates channels, makes a hierarchy and assigns memory to channels */
+static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
+ MultiPartInputFile &file,
+ int width,
+ int height)
+{
+ ExrHandle *data = (ExrHandle *)IMB_exr_get_handle();
+
+ data->ifile_stream = &file_stream;
+ data->ifile = &file;
+
+ data->width = width;
+ data->height = height;
+
+ if (!imb_exr_multilayer_parse_channels_from_file(data)) {
+ IMB_exr_close(data);
+ return nullptr;
+ }
+
return data;
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h
index 556717ad618..82a5d161ded 100644
--- a/source/blender/imbuf/intern/openexr/openexr_multi.h
+++ b/source/blender/imbuf/intern/openexr/openexr_multi.h
@@ -50,13 +50,14 @@ void IMB_exr_add_channel(void *handle,
float *rect,
bool use_half_float);
-int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height);
-int IMB_exr_begin_write(void *handle,
- const char *filename,
- int width,
- int height,
- int compress,
- const struct StampData *stamp);
+bool IMB_exr_begin_read(
+ void *handle, const char *filename, int *width, int *height, const bool parse_channels);
+bool IMB_exr_begin_write(void *handle,
+ const char *filename,
+ int width,
+ int height,
+ int compress,
+ const struct StampData *stamp);
void IMB_exrtile_begin_write(
void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley);
diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp
index 51bc2094053..c8bc7c57e3a 100644
--- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp
@@ -43,21 +43,22 @@ void IMB_exr_add_channel(void * /*handle*/,
{
}
-int IMB_exr_begin_read(void * /*handle*/,
+bool IMB_exr_begin_read(void * /*handle*/,
const char * /*filename*/,
int * /*width*/,
- int * /*height*/)
+ int * /*height*/,
+ const bool /*add_channels*/))
{
return 0;
}
-int IMB_exr_begin_write(void * /*handle*/,
- const char * /*filename*/,
- int /*width*/,
- int /*height*/,
- int /*compress*/,
- const struct StampData * /*stamp*/)
+bool IMB_exr_begin_write(void * /*handle*/,
+ const char * /*filename*/,
+ int /*width*/,
+ int /*height*/,
+ int /*compress*/,
+ const struct StampData * /*stamp*/)
{
- return 0;
+ return false;
}
void IMB_exrtile_begin_write(void * /*handle*/,
const char * /*filename*/,
diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c
index 6bd6521d803..db14f7a2982 100644
--- a/source/blender/render/intern/render_result.c
+++ b/source/blender/render/intern/render_result.c
@@ -1083,7 +1083,7 @@ int render_result_exr_file_read_path(RenderResult *rr,
void *exrhandle = IMB_exr_get_handle();
int rectx, recty;
- if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) {
+ if (!IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty, false)) {
printf("failed being read %s\n", filepath);
IMB_exr_close(exrhandle);
return 0;
@@ -1175,21 +1175,32 @@ void render_result_exr_file_cache_write(Render *re)
/* For cache, makes exact copy of render result */
bool render_result_exr_file_cache_read(Render *re)
{
- char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
+ /* File path to cache. */
+ char filepath[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
char *root = U.render_cachedir;
+ render_result_exr_file_cache_path(re->scene, root, filepath);
- RE_FreeRenderResult(re->result);
- re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS);
- render_result_passes_allocated_ensure(re->result);
+ printf("read exr cache file: %s\n", filepath);
- /* First try cache. */
- render_result_exr_file_cache_path(re->scene, root, str);
+ /* Try opening the file. */
+ void *exrhandle = IMB_exr_get_handle();
+ int rectx, recty;
- printf("read exr cache file: %s\n", str);
- if (!render_result_exr_file_read_path(re->result, NULL, str)) {
- printf("cannot read: %s\n", str);
+ if (!IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty, true)) {
+ printf("cannot read: %s\n", filepath);
+ IMB_exr_close(exrhandle);
return false;
}
+
+ /* Read file contents into render result. */
+ const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+ RE_FreeRenderResult(re->result);
+
+ IMB_exr_read_channels(exrhandle);
+ re->result = render_result_new_from_exr(exrhandle, colorspace, false, rectx, recty);
+
+ IMB_exr_close(exrhandle);
+
return true;
}