Bugfix #21385
authorTon Roosendaal <ton@blender.org>
Sat, 27 Nov 2010 19:33:40 +0000 (19:33 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 27 Nov 2010 19:33:40 +0000 (19:33 +0000)
Blender MultiLayer openEXR files now save with correct scanline order.
Code also provides backward compatibility. Also thanks to Troy Sobotka!

source/blender/blenkernel/BKE_blender.h
source/blender/imbuf/intern/openexr/openexr_api.cpp

index 01a26329f293c7c3f922f2c3e720c871734e3a7b..a97c5fd8d9e7c4553423e835807c45f37973a84b 100644 (file)
@@ -45,7 +45,7 @@ struct Scene;
 struct Main;
 
 #define BLENDER_VERSION                        255
-#define BLENDER_SUBVERSION             0
+#define BLENDER_SUBVERSION             1
 
 #define BLENDER_MINVERSION             250
 #define BLENDER_MINSUBVERSION  0
index 964e57f6cfee36a8aaa234f1958fd8cc57fb085d..81ec43c4c10f067eacafb79f15fe22df96b20e88 100644 (file)
@@ -342,6 +342,7 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag
                int ystride = - xstride*width;
                float *rect[4] = {NULL, NULL, NULL, NULL};
 
+               /* last scanline, stride negative */
                rect[0]= ibuf->rect_float + channels*(height-1)*width;
                rect[1]= rect[0]+1;
                rect[2]= rect[0]+2;
@@ -498,7 +499,7 @@ void IMB_exr_begin_write(void *handle, const char *filename, int width, int heig
        // openexr_header_metadata(&header, ibuf); // no imbuf. cant write
        /* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */
        
-       header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43 and newer"));
+       header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.55.1 and newer"));
        
        data->ofile = new OutputFile(filename, header);
 }
@@ -615,9 +616,13 @@ void IMB_exr_write_channels(void *handle)
        ExrChannel *echan;
        
        if(data->channels.first) {
-               for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next)
-                       frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)echan->rect, 
-                                                                                                       echan->xstride*sizeof(float), echan->ystride*sizeof(float)));
+               for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) {
+                       /* last scanline, stride negative */
+                       float *rect = echan->rect + echan->xstride*(data->height-1)*data->width;
+                       
+                       frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)rect, 
+                                                                                                       echan->xstride*sizeof(float), -echan->ystride*sizeof(float)));
+               }
                
                data->ofile->setFrameBuffer (frameBuffer);
                try {
@@ -638,11 +643,20 @@ void IMB_exr_read_channels(void *handle)
        FrameBuffer frameBuffer;
        ExrChannel *echan;
        
+       /* check if exr was saved with previous versions of blender which flipped images */
+       const StringAttribute *ta = data->ifile->header().findTypedAttribute <StringAttribute> ("BlenderMultiChannel");
+       short flip = (ta && strncmp(ta->value().c_str(), "Blender V2.43", 13)==0); /* 'previous multilayer attribute, flipped */
+       
        for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) {
-               /* no datawindow correction needed */
-               if(echan->rect)
-                       frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)echan->rect, 
-                                                                                               echan->xstride*sizeof(float), echan->ystride*sizeof(float)));
+               
+               if(echan->rect) {
+                       if(flip)
+                               frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)echan->rect, 
+                                                                                       echan->xstride*sizeof(float), echan->ystride*sizeof(float)));
+                       else
+                               frameBuffer.insert (echan->name, Slice (FLOAT,  (char *)(echan->rect + echan->xstride*(data->height-1)*data->width), 
+                                                                                       echan->xstride*sizeof(float), -echan->ystride*sizeof(float)));
+               }
                else 
                        printf("warning, channel with no rect set %s\n", echan->name);
        }