Fix #37221: Multilayer EXR inputs generate pink frame/last displayed frame when using...
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 28 Oct 2013 12:16:17 +0000 (12:16 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 28 Oct 2013 12:16:17 +0000 (12:16 +0000)
generally speaking, if multilayer image fails to load for current
frame doesn't mean anything bad. It might be used to make it so
image sequence is being alpha-overed somewhere in the middle of
scene time.

Made it so if the whole file fails to load, image node will
deliver black transparent color, the same what happens for
regular (non-multilayer images).

Also needed to tweak code in load_multilayer_sequwnce to make
sure no cached frames are pointing to a freed memory.

source/blender/blenkernel/intern/image.c
source/blender/compositor/nodes/COM_ImageNode.cpp

index 01b41eb22cd307a5187ddd2ff89a0a5fe9fd3026..52f3c90754a7ad7756d5d3f27d021270303bc567 100644 (file)
@@ -191,17 +191,21 @@ void BKE_image_de_interlace(Image *ima, int odd)
 
 /* ***************** ALLOC & FREE, DATA MANAGING *************** */
 
-static void image_free_buffers(Image *ima)
+static void image_free_cahced_frames(Image *image)
 {
        ImBuf *ibuf;
-
-       while ((ibuf = BLI_pophead(&ima->ibufs))) {
+       while ((ibuf = BLI_pophead(&image->ibufs))) {
                if (ibuf->userdata) {
                        MEM_freeN(ibuf->userdata);
                        ibuf->userdata = NULL;
                }
                IMB_freeImBuf(ibuf);
        }
+}
+
+static void image_free_buffers(Image *ima)
+{
+       image_free_cahced_frames(ima);
 
        if (ima->anim) IMB_free_anim(ima->anim);
        ima->anim = NULL;
@@ -2505,26 +2509,22 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
 
        /* check for new RenderResult */
        if (ima->rr == NULL || frame != ima->rr->framenr) {
-               /* copy to survive not found multilayer image */
-               RenderResult *oldrr = ima->rr;
+               if (ima->rr) {
+                       /* Cached image buffers shares pointers with render result,
+                        * need to ensure there's no image buffers are hanging around
+                        * with dead links after freeing the render result.
+                        */
+                       image_free_cahced_frames(ima);
+                       RE_FreeRenderResult(ima->rr);
+                       ima->rr = NULL;
+               }
 
-               ima->rr = NULL;
                ibuf = image_load_sequence_file(ima, iuser, frame);
 
                if (ibuf) { /* actually an error */
                        ima->type = IMA_TYPE_IMAGE;
                        printf("error, multi is normal image\n");
                }
-               // printf("loaded new result %p\n", ima->rr);
-               /* free result if new one found */
-               if (ima->rr) {
-                       // if (oldrr) printf("freed previous result %p\n", oldrr);
-                       if (oldrr) RE_FreeRenderResult(oldrr);
-               }
-               else {
-                       ima->rr = oldrr;
-               }
-
        }
        if (ima->rr) {
                RenderPass *rpass = BKE_image_multilayer_index(ima->rr, iuser);
index 6e4bff460d1188cd07445955d37da4cb71a32bab..d595afe6a78ca059777803237f475596c48f3fc6 100644 (file)
@@ -142,7 +142,17 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
 
                /* without this, multilayer that fail to load will crash blender [#32490] */
                if (is_multilayer_ok == false) {
-                       convertToOperations_invalid(graph, context);
+                       int index;
+                       vector<OutputSocket *> &outputsockets = this->getOutputSockets();
+                       for (index = 0; index < outputsockets.size(); index++) {
+                               const float warning_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+                               SetColorOperation *operation = new SetColorOperation();
+                               operation->setChannels(warning_color);
+
+                               /* link the operation */
+                               this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket());
+                               graph->addOperation(operation);
+                       }
                }
        }
        else {