Fix T46223: multiview image sequences crashing.

Differential Revision: https://developer.blender.org/D1549
This commit is contained in:
Brecht Van Lommel 2015-10-11 01:14:02 +02:00
parent 4965c43df7
commit 8191066c0b
Notes: blender-bot 2023-02-14 08:38:06 +01:00
Referenced by issue #46223, Open EXR multiview image sequences crash Blender 2.75a and 2.76rc
11 changed files with 73 additions and 112 deletions

View File

@ -212,6 +212,8 @@ void BKE_image_multiview_index(struct Image *ima, struct ImageUser *iuser);
/* for multilayer images as well as for render-viewer */
bool BKE_image_is_multilayer(struct Image *ima);
bool BKE_image_is_multiview(struct Image *ima);
bool BKE_image_is_stereo(struct Image *ima);
struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima);
void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima);

View File

@ -280,14 +280,9 @@ void BKE_image_free_packedfiles(Image *ima)
image_free_packedfiles(ima);
}
static void image_free_views(Image *ima)
{
BLI_freelistN(&ima->views);
}
void BKE_image_free_views(Image *image)
{
image_free_views(image);
BLI_freelistN(&image->views);
}
static void image_free_anims(Image *ima)
@ -350,7 +345,7 @@ void BKE_image_free(Image *ima)
}
}
image_free_views(ima);
BKE_image_free_views(ima);
MEM_freeN(ima->stereo3d_format);
}
@ -866,8 +861,6 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei
}
ima->ok = IMA_OK_LOADED;
if (stereo3d)
ima->flag |= IMA_IS_STEREO | IMA_IS_MULTIVIEW;
}
return ima;
@ -957,7 +950,7 @@ void BKE_image_memorypack(Image *ima)
{
ImBuf *ibuf;
if ((ima->flag & IMA_IS_MULTIVIEW)) {
if (BKE_image_is_multiview(ima)) {
image_memorypack_multiview(ima);
return;
}
@ -2483,15 +2476,8 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *
BLI_lock_thread(LOCK_DRAW_IMAGE);
if (BKE_scene_multiview_is_stereo3d(rd)) {
ima->flag |= IMA_IS_STEREO;
ima->flag |= IMA_IS_MULTIVIEW;
}
else {
ima->flag &= ~IMA_IS_STEREO;
ima->flag &= ~IMA_IS_MULTIVIEW;
if (!BKE_scene_multiview_is_stereo3d(rd))
iuser->flag &= ~IMA_SHOW_STEREO;
}
/* see if all scene render views are in the image view list */
do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views));
@ -2832,7 +2818,7 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
{
if (iuser) {
bool is_stereo = (ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO);
bool is_stereo = BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO);
if (is_stereo) {
iuser->multi_index = iuser->multiview_eye;
}
@ -2865,27 +2851,27 @@ bool BKE_image_is_multilayer(Image *ima)
return false;
}
static void image_init_multilayer_multiview_flag(Image *ima, RenderResult *rr)
bool BKE_image_is_multiview(Image *ima)
{
return (BLI_listbase_count_ex(&ima->views, 2) > 1);
}
bool BKE_image_is_stereo(Image *ima)
{
return BKE_image_is_multiview(ima) &&
(BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
}
static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
{
BKE_image_free_views(ima);
if (rr) {
if (RE_RenderResult_is_stereo(rr)) {
ima->flag |= IMA_IS_STEREO;
ima->flag |= IMA_IS_MULTIVIEW;
}
else {
ima->flag &= ~IMA_IS_STEREO;
if (BLI_listbase_count_ex(&rr->views, 2) > 1)
ima->flag |= IMA_IS_MULTIVIEW;
else
ima->flag &= ~IMA_IS_MULTIVIEW;
}
}
else {
ima->flag &= ~IMA_IS_STEREO;
ima->flag &= ~IMA_IS_MULTIVIEW;
BLI_duplicatelist(&ima->views, &rr->views);
}
}
RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
{
RenderResult *rr = NULL;
@ -2898,8 +2884,8 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
else
rr = ima->renders[ima->render_slot];
/* set proper multiview flag */
image_init_multilayer_multiview_flag(ima, rr);
/* set proper views */
image_init_multilayer_multiview(ima, rr);
}
return rr;
@ -3057,39 +3043,15 @@ static void image_add_buffer_cb(void *base, const char *str, ImBuf *ibuf, const
}
#endif /* WITH_OPENEXR */
#ifdef WITH_OPENEXR
static void image_update_multiview_flags(Image *ima)
{
if (BLI_listbase_count_ex(&ima->views, 2) > 1) {
ima->flag |= IMA_IS_MULTIVIEW;
if (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)))
{
ima->flag |= IMA_IS_STEREO;
}
else {
ima->flag &= ~IMA_IS_STEREO;
}
}
else {
ima->flag &= ~IMA_IS_STEREO;
ima->flag &= ~IMA_IS_MULTIVIEW;
}
}
#endif /* WITH_OPENEXR */
/* after imbuf load, openexr type can return with a exrhandle open */
/* in that case we have to build a render-result */
#ifdef WITH_OPENEXR
static void image_create_multiview(Image *ima, ImBuf *ibuf, const int frame)
{
image_free_views(ima);
BKE_image_free_views(ima);
IMB_exr_multiview_convert(ibuf->userdata, ima, image_add_view_cb, image_add_buffer_cb, frame);
image_update_multiview_flags(ima);
IMB_exr_close(ibuf->userdata);
}
#endif /* WITH_OPENEXR */
@ -3110,8 +3072,8 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
if (ima->rr)
ima->rr->framenr = framenr;
/* set proper multiview flag */
image_init_multilayer_multiview_flag(ima, ima->rr);
/* set proper views */
image_init_multilayer_multiview(ima, ima->rr);
}
#endif /* WITH_OPENEXR */
@ -3149,7 +3111,7 @@ static int imbuf_alpha_flags_for_image(Image *ima)
/* the number of files will vary according to the stereo format */
static size_t image_num_files(Image *ima)
{
const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
const bool is_multiview = BKE_image_is_multiview(ima);
if (!is_multiview) {
return 1;
@ -3231,7 +3193,7 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf = NULL;
const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
const bool is_multiview = BKE_image_is_multiview(ima);
const size_t totfiles = image_num_files(ima);
bool assign = false;
@ -3251,7 +3213,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
for (i = 0; i < totfiles; i++)
ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &assign);
if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
/* return the original requested ImBuf */
@ -3388,7 +3350,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const s
static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf = NULL;
const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
const bool is_multiview = BKE_image_is_multiview(ima);
const size_t totfiles = image_num_files(ima);
size_t i;
@ -3416,7 +3378,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
}
if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
for (i = 0; i < totviews; i++) {
@ -3544,7 +3506,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
{
struct ImBuf *ibuf = NULL;
bool assign = false;
const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
const bool is_multiview = BKE_image_is_multiview(ima);
const size_t totfiles = image_num_files(ima);
bool has_packed = BKE_image_has_packedfile(ima);
@ -3577,7 +3539,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &assign);
/* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */
if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D &&
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D &&
ibuf_arr[0] && totfiles == 1 && totviews >= 2)
{
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
@ -3677,7 +3639,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
pass = iuser->pass;
actview = iuser->view;
if ((ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO))
if (BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO))
actview = iuser->multiview_eye;
if (from_render) {
@ -3851,12 +3813,12 @@ static size_t image_get_multiview_index(Image *ima, ImageUser *iuser)
return iuser ? iuser->multi_index : index;
}
else if (is_backdrop) {
if ((ima->flag & IMA_IS_STEREO)) {
if (BKE_image_is_stereo(ima)) {
/* backdrop hackaround (since there is no iuser */
return ima->eye;
}
}
else if ((ima->flag & IMA_IS_MULTIVIEW)) {
else if (BKE_image_is_multiview(ima)) {
return iuser ? iuser->multi_index : index;
}
@ -4345,9 +4307,12 @@ void BKE_image_update_frame(const Main *bmain, int cfra)
void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
{
if ((ima->flag & IMA_IS_MULTIVIEW) && (ima->rr == NULL)) {
if (BKE_image_is_multiview(ima) && (ima->rr == NULL)) {
ImageView *iv = BLI_findlink(&ima->views, iuser->view);
BLI_strncpy(filepath, iv->filepath, FILE_MAX);
if (iv->filepath[0])
BLI_strncpy(filepath, iv->filepath, FILE_MAX);
else
BLI_strncpy(filepath, ima->name, FILE_MAX);
}
else {
BLI_strncpy(filepath, ima->name, FILE_MAX);
@ -4642,15 +4607,12 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
BKE_image_free_views(ima);
if (!is_multiview) {
goto monoview;
/* nothing to do */
}
else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
size_t i;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
ima->flag |= IMA_IS_MULTIVIEW;
ima->flag |= IMA_IS_STEREO;
for (i = 0; i < 2; i++) {
image_add_view(ima, names[i], ima->name);
}
@ -4665,7 +4627,8 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
if (prefix[0] == '\0') {
goto monoview;
BKE_image_free_views(ima);
return;
}
/* create all the image views */
@ -4701,15 +4664,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
}
/* all good */
if (BLI_listbase_count_ex(&ima->views, 2) > 1) {
ima->flag |= IMA_IS_MULTIVIEW;
if (BKE_scene_multiview_is_stereo3d(&scene->r))
ima->flag |= IMA_IS_STEREO;
}
else {
monoview:
ima->flag &= ~IMA_IS_STEREO;
ima->flag &= ~IMA_IS_MULTIVIEW;
if (!BKE_image_is_multiview(ima)) {
BKE_image_free_views(ima);
}
}

View File

@ -229,13 +229,8 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
}
BLI_lock_thread(LOCK_DRAW_IMAGE);
if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) {
oglrender->ima->flag |= IMA_IS_STEREO;
}
else {
oglrender->ima->flag &= ~IMA_IS_STEREO;
if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd)))
oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
}
BLI_unlock_thread(LOCK_DRAW_IMAGE);
/* will only work for non multiview correctly */

View File

@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@ -2195,7 +2196,7 @@ bool ED_screen_stereo3d_required(bScreen *screen)
/* images should always show in stereo, even if
* the file doesn't have views enabled */
sima = sa->spacedata.first;
if (sima->image && (sima->image->flag & IMA_IS_STEREO) &&
if (sima->image && BKE_image_is_stereo(sima->image) &&
(sima->iuser.flag & IMA_SHOW_STEREO))
{
return true;

View File

@ -715,8 +715,8 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
}
/* stereo image */
else if (((image->flag & IMA_IS_STEREO) && (!show_stereo)) ||
((image->flag & IMA_IS_MULTIVIEW) && ((image->flag & IMA_IS_STEREO) == 0)))
else if ((BKE_image_is_stereo(image) && (!show_stereo)) ||
(BKE_image_is_multiview(image) && !BKE_image_is_stereo(image)))
{
ImageView *iv;
int nr = 0;

View File

@ -813,7 +813,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
show_stereo3d = (ima && (ima->flag & IMA_IS_STEREO) && (sima->iuser.flag & IMA_SHOW_STEREO));
show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO));
show_multilayer = ima && BKE_image_is_multilayer(ima);
if (show_viewer) {

View File

@ -1153,8 +1153,6 @@ static int image_open_exec(bContext *C, wmOperator *op)
}
else {
ima->flag &= ~IMA_USE_VIEWS;
ima->flag &= ~IMA_IS_STEREO;
ima->flag &= ~IMA_IS_MULTIVIEW;
BKE_image_free_views(ima);
}
@ -1703,7 +1701,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
/* we need renderresult for exr and rendered multiview */
scene = CTX_data_scene(C);
rr = BKE_image_acquire_renderresult(scene, ima);
is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : (ima->flag & IMA_IS_MULTIVIEW) == 0;
is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2;
/* error handling */
if (!rr) {
@ -1714,7 +1712,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
else {
if (imf->views_format == R_IMF_VIEWS_STEREO_3D) {
if ((ima->flag & IMA_IS_STEREO) == 0) {
if (!BKE_image_is_stereo(ima)) {
BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
goto cleanup;
@ -1959,9 +1957,9 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
/* show multiview save options only if image has multiviews */
prop = RNA_struct_find_property(op->ptr, "show_multiview");
RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
prop = RNA_struct_find_property(op->ptr, "use_multiview");
RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
image_filesel(C, op, simopts.filepath);

View File

@ -1618,7 +1618,7 @@ exit:
static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
{
if ((ima->flag & IMA_IS_STEREO)) {
if (BKE_image_is_stereo(ima)) {
iuser->flag |= IMA_SHOW_STEREO;
if ((scene->r.scemode & R_MULTIVIEW) == 0) {

View File

@ -172,8 +172,8 @@ enum {
IMA_IGNORE_ALPHA = (1 << 12),
IMA_DEINTERLACE = (1 << 13),
IMA_USE_VIEWS = (1 << 14),
IMA_IS_STEREO = (1 << 15),
IMA_IS_MULTIVIEW = (1 << 16), /* similar to stereo, but a more general case */
// IMA_IS_STEREO = (1 << 15), /* deprecated */
// IMA_IS_MULTIVIEW = (1 << 16), /* deprecated */
};
/* Image.tpageflag */

View File

@ -78,6 +78,16 @@ static void rna_Image_animated_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
}
}
static int rna_Image_is_stereo_3d_get(PointerRNA *ptr)
{
return BKE_image_is_stereo((Image *)ptr->data);
}
static int rna_Image_is_multiview_get(PointerRNA *ptr)
{
return BKE_image_is_multiview((Image *)ptr->data);
}
static int rna_Image_dirty_get(PointerRNA *ptr)
{
return BKE_image_is_dirty((Image *)ptr->data);
@ -716,12 +726,12 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update");
prop = RNA_def_property(srna, "is_stereo_3d", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_STEREO);
RNA_def_property_boolean_funcs(prop, "rna_Image_is_stereo_3d_get", NULL);
RNA_def_property_ui_text(prop, "Stereo 3D", "Image has left and right views");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_multiview", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_MULTIVIEW);
RNA_def_property_boolean_funcs(prop, "rna_Image_is_multiview_get", NULL);
RNA_def_property_ui_text(prop, "Multiple Views", "Image has more than one view");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);

View File

@ -1950,7 +1950,7 @@ static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
ImBuf *ibuf;
void *lock;
if ((ima->flag & IMA_IS_STEREO) == 0)
if (!BKE_image_is_stereo(ima))
return;
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);