svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / blender / blenkernel / intern / image.c
index fdd36d72b06cf280a116adbd23ec464b92cc52a3..ef0984bf93dbb3242eff27ee5bfa6c7248e7657c 100644 (file)
@@ -21,9 +21,7 @@
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Blender Foundation, 2006
+ * Contributor(s): Blender Foundation, 2006, full recode
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -53,7 +51,9 @@
 #include "DNA_packedFile_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_sequence_types.h"
 #include "DNA_texture_types.h"
+#include "DNA_sequence_types.h"
 #include "DNA_userdef_types.h"
 
 #include "BLI_arithb.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 
-#include "BIF_editseq.h"
+//XXX #include "BIF_editseq.h"
 
 #include "PIL_time.h"
 
 #include "RE_pipeline.h"
 
-/* bad level; call to free_realtime_image */
-#include "BKE_bad_level_calls.h"       
-
-/* for stamp drawing to an image */
-#include "BMF_Api.h"
+#include "GPU_extensions.h"
+#include "GPU_draw.h"
 
-#include "blendef.h"
-#include "BSE_time.h"
+#include "BLO_sys_types.h" // for intptr_t support
 
 /* max int, to indicate we don't store sequences in ibuf */
 #define IMA_NO_INDEX   0x7FEFEFEF
@@ -92,6 +88,7 @@
 /* quick lookup: supports 1 million frames, thousand passes */
 #define IMA_MAKE_INDEX(frame, index)   ((frame)<<10)+index
 #define IMA_INDEX_FRAME(index)                 (index>>10)
+#define IMA_INDEX_PASS(index)                  (index & ~1023)
 
 /* ******** IMAGE PROCESSING ************* */
 
@@ -238,7 +235,7 @@ static void image_free_buffers(Image *ima)
                ima->rr= NULL;
        }       
        
-       free_realtime_image(ima);
+       GPU_free_image(ima);
        
        ima->ok= IMA_OK;
 }
@@ -246,7 +243,6 @@ static void image_free_buffers(Image *ima)
 /* called by library too, do not free ima itself */
 void free_image(Image *ima)
 {
-
        image_free_buffers(ima);
        if (ima->packedfile) {
                freePackedFile(ima->packedfile);
@@ -257,7 +253,6 @@ void free_image(Image *ima)
        if (ima->preview) {
                BKE_previewimg_free(&ima->preview);
        }
-       
 }
 
 /* only image block itself */
@@ -283,15 +278,19 @@ static Image *image_alloc(const char *name, short source, short type)
 /* get the ibuf from an image cache, local use here only */
 static ImBuf *image_get_ibuf(Image *ima, int index, int frame)
 {
+       /* this function is intended to be thread safe. with IMA_NO_INDEX this
+        * should be OK, but when iterating over the list this is more tricky
+        * */
        if(index==IMA_NO_INDEX)
                return ima->ibufs.first;
        else {
                ImBuf *ibuf;
-               
+
                index= IMA_MAKE_INDEX(frame, index);
                for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next)
                        if(ibuf->index==index)
                                return ibuf;
+
                return NULL;
        }
 }
@@ -319,25 +318,54 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
                for(link= ima->ibufs.first; link; link= link->next)
                        if(link->index>=index)
                                break;
+
+               ibuf->index= index;
+
+               /* this function accepts link==NULL */
+               BLI_insertlinkbefore(&ima->ibufs, link, ibuf);
+
                /* now we don't want copies? */
-               if(link && ibuf->index==link->index) {
-                       ImBuf *prev= ibuf->prev;
+               if(link && ibuf->index==link->index)
                        image_remove_ibuf(ima, link);
-                       link= prev;
+       }
+}
+
+/* empty image block, of similar type and filename */
+Image *BKE_image_copy(Image *ima)
+{
+       Image *new= image_alloc(ima->id.name+2, ima->source, ima->type);
+
+       BLI_strncpy(new->name, ima->name, sizeof(ima->name));
+       
+       new->gen_x= ima->gen_x;
+       new->gen_y= ima->gen_y;
+       new->gen_type= ima->gen_type;
+       
+       return new;
+}
+
+void BKE_image_merge(Image *dest, Image *source)
+{
+       ImBuf *ibuf;
+       
+       /* sanity check */
+       if(dest && source && dest!=source) {
+       
+               while((ibuf= source->ibufs.first)) {
+                       BLI_remlink(&source->ibufs, ibuf);
+                       image_assign_ibuf(dest, ibuf, IMA_INDEX_PASS(ibuf->index), IMA_INDEX_FRAME(ibuf->index));
                }
                
-               /* this function accepts link==NULL */
-               BLI_insertlinkbefore(&ima->ibufs, link, ibuf);
-               
-               ibuf->index= index;
+               free_libblock(&G.main->image, source);
        }
-       
 }
 
+
 /* checks if image was already loaded, then returns same image */
 /* otherwise creates new. */
 /* does not load ibuf itself */
-Image *BKE_add_image_file(const char *name)
+/* pass on optional frame for #name images */
+Image *BKE_add_image_file(const char *name, int frame)
 {
        Image *ima;
        int file, len;
@@ -352,7 +380,8 @@ Image *BKE_add_image_file(const char *name)
        }
        
        BLI_strncpy(str, name, sizeof(str));
-       BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
+       BLI_convertstringcode(str, G.sce);
+       BLI_convertstringframe(str, frame);
        
        /* exists? */
        file= open(str, O_BINARY|O_RDONLY);
@@ -363,7 +392,8 @@ Image *BKE_add_image_file(const char *name)
        for(ima= G.main->image.first; ima; ima= ima->id.next) {
                if(ima->source!=IMA_SRC_VIEWER && ima->source!=IMA_SRC_GENERATED) {
                        BLI_strncpy(strtest, ima->name, sizeof(ima->name));
-                       BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra);
+                       BLI_convertstringcode(strtest, G.sce);
+                       BLI_convertstringframe(strtest, frame);
                        
                        if( strcmp(strtest, str)==0 ) {
                                if(ima->anim==NULL || ima->id.us==0) {
@@ -403,7 +433,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, sho
        unsigned char *rect= NULL;
        float *rect_float= NULL;
        int x, y;
-       int checkerwidth=21, dark=1;
+       int checkerwidth=32, dark=1;
        
        if (floatbuf) {
                ibuf= IMB_allocImBuf(width, height, 24, IB_rectfloat, 0);
@@ -414,7 +444,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, sho
                rect= (unsigned char*)ibuf->rect;
        }
        
-       strcpy(ibuf->name, "Untitled");
+       strcpy(ibuf->name, "//Untitled");
        ibuf->userflags |= IB_BITMAPDIRTY;
        
        if (uvtestgrid) {
@@ -581,7 +611,8 @@ void tag_image_time(Image *ima)
                ima->lastused = (int)PIL_check_seconds_timer();
 }
 
-void tag_all_images_time() 
+#if 0
+static void tag_all_images_time() 
 {
        Image *ima;
        int ctime = (int)PIL_check_seconds_timer();
@@ -593,6 +624,7 @@ void tag_all_images_time()
                }
        }
 }
+#endif
 
 void free_old_images()
 {
@@ -617,7 +649,7 @@ void free_old_images()
                           This gives textures a "second chance" to be used before dying.
                        */
                        if(ima->bindcode || ima->repbind) {
-                               free_realtime_image(ima);
+                               GPU_free_image(ima);
                                ima->lastused = ctime;
                        }
                        /* Otherwise, just kill the buffers */
@@ -629,13 +661,18 @@ void free_old_images()
        }
 }
 
-static unsigned long image_mem_size(Image *ima)
+static uintptr_t image_mem_size(Image *ima)
 {
        ImBuf *ibuf, *ibufm;
        int level;
-       unsigned long size = 0;
+       uintptr_t size = 0;
 
        size= 0;
+       
+       /* viewers have memory depending on other rules, has no valid rect pointer */
+       if(ima->source==IMA_SRC_VIEWER)
+               return 0;
+       
        for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) {
                if(ibuf->rect) size += MEM_allocN_len(ibuf->rect);
                else if(ibuf->rect_float) size += MEM_allocN_len(ibuf->rect_float);
@@ -655,7 +692,7 @@ static unsigned long image_mem_size(Image *ima)
 void BKE_image_print_memlist(void)
 {
        Image *ima;
-       unsigned long size, totsize= 0;
+       uintptr_t size, totsize= 0;
 
        for(ima= G.main->image.first; ima; ima= ima->id.next)
                totsize += image_mem_size(ima);
@@ -763,6 +800,10 @@ int BKE_imtype_to_ftype(int imtype)
                return RAWTGA;
        else if(imtype==R_HAMX)
                return AN_hamx;
+#ifdef WITH_OPENJPEG
+       else if(imtype==R_JP2)
+               return JP2;
+#endif
        else
                return JPG|90;
 }
@@ -797,6 +838,10 @@ int BKE_ftype_to_imtype(int ftype)
                return R_RAWTGA;
        else if(ftype == AN_hamx)
                return R_HAMX;
+#ifdef WITH_OPENJPEG
+       else if(ftype & JP2)
+               return R_JP2;
+#endif
        else
                return R_JPEG90;
 }
@@ -817,11 +862,11 @@ int BKE_imtype_is_movie(int imtype)
        return 0;
 }
 
-void BKE_add_image_extension(char *string, int imtype)
+void BKE_add_image_extension(Scene *scene, char *string, int imtype)
 {
        char *extension="";
        
-       if(G.scene->r.imtype== R_IRIS) {
+       if(scene->r.imtype== R_IRIS) {
                if(!BLI_testextensie(string, ".rgb"))
                        extension= ".rgb";
        }
@@ -847,17 +892,13 @@ void BKE_add_image_extension(char *string, int imtype)
                if(!BLI_testextensie(string, ".tga"))
                        extension= ".tga";
        }
-       else if(ELEM5(imtype, R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90)) {
-               if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg")))
-                       extension= ".jpg";
-       }
        else if(imtype==R_BMP) {
                if(!BLI_testextensie(string, ".bmp"))
                        extension= ".bmp";
        }
        else if(G.have_libtiff && (imtype==R_TIFF)) {
-               if(!BLI_testextensie(string, ".tif"))
-                       extension= ".tif";
+               if(!BLI_testextensie(string, ".tif") && 
+                       !BLI_testextensie(string, ".tiff")) extension= ".tif";
        }
 #ifdef WITH_OPENEXR
        else if( ELEM(imtype, R_OPENEXR, R_MULTILAYER)) {
@@ -873,10 +914,20 @@ void BKE_add_image_extension(char *string, int imtype)
                if (!BLI_testextensie(string, ".dpx"))
                        extension= ".dpx";
        }
-       else {  /* targa default */
+       else if(imtype==R_TARGA) {
                if(!BLI_testextensie(string, ".tga"))
                        extension= ".tga";
        }
+#ifdef WITH_OPENJPEG
+       else if(imtype==R_JP2) {
+               if(!BLI_testextensie(string, ".jp2"))
+                       extension= ".jp2";
+       }
+#endif
+       else { //   R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90, R_QUICKTIME etc
+               if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg")))
+                       extension= ".jpg";
+       }
 
        strcat(string, extension);
 }
@@ -894,7 +945,7 @@ typedef struct StampData {
        char    strip[64];
 } StampData;
 
-static void stampdata(StampData *stamp_data, int do_prefix)
+static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix)
 {
        char text[256];
        
@@ -905,22 +956,27 @@ static void stampdata(StampData *stamp_data, int do_prefix)
        char sdate[9];
 #endif /* WIN32 */
        
-       if (G.scene->r.stamp & R_STAMP_FILENAME) {
-               if (do_prefix)          sprintf(stamp_data->file, "File %s", G.sce);
-               else                            sprintf(stamp_data->file, "%s", G.sce);
+       if (scene->r.stamp & R_STAMP_FILENAME) {
+               if (G.relbase_valid) {
+                       if (do_prefix)          sprintf(stamp_data->file, "File %s", G.sce);
+                       else                            sprintf(stamp_data->file, "%s", G.sce);
+               } else {
+                       if (do_prefix)          strcpy(stamp_data->file, "File <untitled>");
+                       else                            strcpy(stamp_data->file, "<untitled>");
+               }
                stamp_data->note[0] = '\0';
        } else {
                stamp_data->file[0] = '\0';
        }
        
-       if (G.scene->r.stamp & R_STAMP_NOTE) {
+       if (scene->r.stamp & R_STAMP_NOTE) {
                /* Never do prefix for Note */
-               sprintf(stamp_data->note, "%s", G.scene->r.stamp_udata);
+               sprintf(stamp_data->note, "%s", scene->r.stamp_udata);
        } else {
                stamp_data->note[0] = '\0';
        }
        
-       if (G.scene->r.stamp & R_STAMP_DATE) {
+       if (scene->r.stamp & R_STAMP_DATE) {
 #ifdef WIN32
                _strdate (sdate);
                sprintf (text, "%s", sdate);
@@ -935,8 +991,8 @@ static void stampdata(StampData *stamp_data, int do_prefix)
                stamp_data->date[0] = '\0';
        }
        
-       if (G.scene->r.stamp & R_STAMP_MARKER) {
-               TimeMarker *marker = get_frame_marker(CFRA);
+       if (scene->r.stamp & R_STAMP_MARKER) {
+               TimeMarker *marker = NULL; // XXX get_frame_marker(scene->r.cfra);
        
                if (marker) strcpy(text, marker->name);
                else            strcpy(text, "<none>");
@@ -947,11 +1003,11 @@ static void stampdata(StampData *stamp_data, int do_prefix)
                stamp_data->marker[0] = '\0';
        }
        
-       if (G.scene->r.stamp & R_STAMP_TIME) {
+       if (scene->r.stamp & R_STAMP_TIME) {
                int h, m, s, f;
                h= m= s= f= 0;
-               f = (int)(G.scene->r.cfra % G.scene->r.frs_sec);
-               s = (int)(G.scene->r.cfra / G.scene->r.frs_sec);
+               f = (int)(scene->r.cfra % scene->r.frs_sec);
+               s = (int)(scene->r.cfra / scene->r.frs_sec);
 
                if (s) {
                        m = (int)(s / 60);
@@ -963,7 +1019,7 @@ static void stampdata(StampData *stamp_data, int do_prefix)
                        }
                }
 
-               if (G.scene->r.frs_sec < 100)
+               if (scene->r.frs_sec < 100)
                        sprintf (text, "%02d:%02d:%02d.%02d", h, m, s, f);
                else
                        sprintf (text, "%02d:%02d:%02d.%03d", h, m, s, f);
@@ -974,31 +1030,34 @@ static void stampdata(StampData *stamp_data, int do_prefix)
                stamp_data->time[0] = '\0';
        }
        
-       if (G.scene->r.stamp & R_STAMP_FRAME) {
+       if (scene->r.stamp & R_STAMP_FRAME) {
                char format[32];
-               if (do_prefix)          sprintf(format, "Frame %%0%di\n", 1 + (int) log10(G.scene->r.efra));
-               else                            sprintf(format, "%%0%di\n", 1 + (int) log10(G.scene->r.efra));
-               sprintf (stamp_data->frame, format, G.scene->r.cfra);
+               if (do_prefix)          sprintf(format, "Frame %%0%di\n", 1 + (int) log10(scene->r.efra));
+               else                            sprintf(format, "%%0%di\n", 1 + (int) log10(scene->r.efra));
+               sprintf (stamp_data->frame, format, scene->r.cfra);
        } else {
                stamp_data->frame[0] = '\0';
        }
 
-       if (G.scene->r.stamp & R_STAMP_CAMERA) {
-               if (do_prefix)          sprintf(stamp_data->camera, "Camera %s", ((Camera *) G.scene->camera)->id.name+2);
-               else                            sprintf(stamp_data->camera, "%s", ((Camera *) G.scene->camera)->id.name+2);
+       if (scene->r.stamp & R_STAMP_CAMERA) {
+               if (scene->camera) strcpy(text, ((Camera *) scene->camera)->id.name+2);
+               else            strcpy(text, "<none>");
+               
+               if (do_prefix)          sprintf(stamp_data->camera, "Camera %s", text);
+               else                            sprintf(stamp_data->camera, "%s", text);
        } else {
                stamp_data->camera[0] = '\0';
        }
 
-       if (G.scene->r.stamp & R_STAMP_SCENE) {
-               if (do_prefix)          sprintf(stamp_data->scene, "Scene %s", G.scene->id.name+2);
-               else                            sprintf(stamp_data->scene, "%s", G.scene->id.name+2);
+       if (scene->r.stamp & R_STAMP_SCENE) {
+               if (do_prefix)          sprintf(stamp_data->scene, "Scene %s", scene->id.name+2);
+               else                            sprintf(stamp_data->scene, "%s", scene->id.name+2);
        } else {
                stamp_data->scene[0] = '\0';
        }
        
-       if (G.scene->r.stamp & R_STAMP_SEQSTRIP) {
-               Sequence *seq = get_forground_frame_seq(CFRA);
+       if (scene->r.stamp & R_STAMP_SEQSTRIP) {
+               Sequence *seq= NULL; //XXX = get_foreground_frame_seq(scene->r.cfra);
        
                if (seq) strcpy(text, seq->name+2);
                else            strcpy(text, "<none>");
@@ -1010,8 +1069,11 @@ static void stampdata(StampData *stamp_data, int do_prefix)
        }
 }
 
-void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int channels)
+void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels)
 {
+#if 0
+// XXX
+// This go back when BLF_draw_buffer is implemented - Diego
        struct StampData stamp_data;
        
        int x=1,y=1;
@@ -1023,9 +1085,9 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
        if (!rect && !rectf)
                return;
        
-       stampdata(&stamp_data, 1);
+       stampdata(scene, &stamp_data, 1);
        
-       switch (G.scene->r.stamp_font_id) {
+       switch (scene->r.stamp_font_id) {
        case 1: /* tiny */
                font = BMF_GetFont(BMF_kHelveticaBold8);
                break;
@@ -1057,24 +1119,24 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
        if (stamp_data.file[0]) {
                /* Top left corner */
                text_width = BMF_GetStringWidth(font, stamp_data.file);
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
                y -= font_height+2; /* Top and bottom 1 pix padding each */
        }
 
        /* Top left corner, below File */
        if (stamp_data.note[0]) {
                text_width = BMF_GetStringWidth(font, stamp_data.note);
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
                y -= font_height+2; /* Top and bottom 1 pix padding each */
        }
        
        /* Top left corner, below File (or Note) */
        if (stamp_data.date[0]) {
                text_width = BMF_GetStringWidth(font, stamp_data.date);
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
        }
 
        /* Bottom left corner, leaving space for timing */
@@ -1082,8 +1144,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
                x = 1;
                y = font_height+2+1; /* 2 for padding in TIME|FRAME fields below and 1 for padding in this one */
                text_width = BMF_GetStringWidth(font, stamp_data.marker);
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
        }
        
        /* Left bottom corner */
@@ -1091,8 +1153,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
                x = 1;
                y = 1;
                text_width = BMF_GetStringWidth(font, stamp_data.time);
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
                x += text_width+text_pad+2; /* Both sides have 1 pix additional padding each */
        }
        
@@ -1101,8 +1163,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
                /* Left bottom corner (after SMPTE if exists) */
                if (!stamp_data.time[0])        x = 1;
                y = 1;
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
        }
 
        if (stamp_data.camera[0]) {
@@ -1110,8 +1172,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
                /* Center of bottom edge */
                x = (width/2) - (BMF_GetStringWidth(font, stamp_data.camera)/2);
                y = 1;
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
        }
        
        if (stamp_data.scene[0]) {
@@ -1119,8 +1181,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
                /* Bottom right corner */
                x = width - (text_width+1+text_pad);
                y = 1;
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
        }
        
        if (stamp_data.strip[0]) {
@@ -1128,20 +1190,20 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int
                /* Top right corner */
                x = width - (text_width+1+text_pad);
                y = height - font_height - 1;
-               buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
-               BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels);
+               buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1);
+               BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels);
        }
-       
+#endif // 0 XXX        
 }
 
-void BKE_stamp_info(struct ImBuf *ibuf)
+void BKE_stamp_info(Scene *scene, struct ImBuf *ibuf)
 {
        struct StampData stamp_data;
 
        if (!ibuf)      return;
        
        /* fill all the data values, no prefix */
-       stampdata(&stamp_data, 0);
+       stampdata(scene, &stamp_data, 0);
        
        if (stamp_data.file[0])         IMB_imginfo_change_field (ibuf, "File",         stamp_data.file);
        if (stamp_data.note[0])         IMB_imginfo_change_field (ibuf, "Note",         stamp_data.note);
@@ -1154,7 +1216,7 @@ void BKE_stamp_info(struct ImBuf *ibuf)
        if (stamp_data.strip[0])        IMB_imginfo_change_field (ibuf, "Strip",        stamp_data.strip);
 }
 
-int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quality)
+int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimtype, int quality)
 {
        int ok;
        
@@ -1177,6 +1239,9 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali
        }
        else if ((G.have_libtiff) && (imtype==R_TIFF)) {
                ibuf->ftype= TIF;
+
+               if(subimtype & R_TIFF_16BIT)
+                       ibuf->ftype |= TIF_16BIT;
        }
 #ifdef WITH_OPENEXR
        else if (imtype==R_OPENEXR || imtype==R_MULTILAYER) {
@@ -1205,6 +1270,28 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali
        else if(imtype==R_HAMX) {
                ibuf->ftype= AN_hamx;
        }
+#ifdef WITH_OPENJPEG
+       else if(imtype==R_JP2) {
+               if(quality < 10) quality= 90;
+               ibuf->ftype= JP2|quality;
+               
+               if (subimtype & R_JPEG2K_16BIT) {
+                       ibuf->ftype |= JP2_16BIT;
+               } else if (subimtype & R_JPEG2K_12BIT) {
+                       ibuf->ftype |= JP2_12BIT;
+               }
+               
+               if (subimtype & R_JPEG2K_YCC) {
+                       ibuf->ftype |= JP2_YCC;
+               }
+               
+               if (subimtype & R_JPEG2K_CINE_PRESET) {
+                       ibuf->ftype |= JP2_CINE;
+                       if (subimtype & R_JPEG2K_CINE_48FPS)
+                               ibuf->ftype |= JP2_CINE_48FPS;
+               }
+       }
+#endif
        else {
                /* R_JPEG90, R_MOVIE, etc. default we save jpegs */
                if(quality < 10) quality= 90;
@@ -1214,8 +1301,8 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali
        
        BLI_make_existing_file(name);
 
-       if(G.scene->r.scemode & R_STAMP_INFO)
-               BKE_stamp_info(ibuf);
+       if(scene->r.scemode & R_STAMP_INFO)
+               BKE_stamp_info(scene, ibuf);
        
        ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
        if (ok == 0) {
@@ -1226,28 +1313,21 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali
 }
 
 
-void BKE_makepicstring(char *string, char *base, int frame, int imtype)
+void BKE_makepicstring(struct Scene *scene, char *string, char *base, int frame, int imtype)
 {
-       short i, len, digits= 4;        /* digits in G.scene? */
-       char num[10];
-
        if (string==NULL) return;
 
        BLI_strncpy(string, base, FILE_MAX - 10);       /* weak assumption */
-       BLI_convertstringcode(string, G.sce, frame);
-
-       len= strlen(string);
-                       
-       i= digits - sprintf(num, "%d", frame);
-       for(; i>0; i--){
-               string[len]= '0';
-               len++;
-       }
-       string[len]= 0;
-       strcat(string, num);
+       
+       /* if we dont have any #'s to insert numbers into, use 4 numbers by default */
+       if (strchr(string, '#')==NULL)
+               strcat(string, "####"); /* 4 numbers */
+       
+       BLI_convertstringcode(string, G.sce);
+       BLI_convertstringframe(string, frame);
 
-       if(G.scene->r.scemode & R_EXTENSION) 
-               BKE_add_image_extension(string, imtype);
+       if(scene->r.scemode & R_EXTENSION) 
+               BKE_add_image_extension(scene, string, imtype);
                
 }
 
@@ -1351,7 +1431,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
                /* try to repack file */
                if(ima->packedfile) {
                        PackedFile *pf;
-                       pf = newPackedFile(ima->name);
+                       pf = newPackedFile(NULL, ima->name);
                        if (pf) {
                                freePackedFile(ima->packedfile);
                                ima->packedfile = pf;
@@ -1418,12 +1498,12 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
        return rpass;
 }
 
-RenderResult *BKE_image_get_renderresult(Image *ima)
+RenderResult *BKE_image_get_renderresult(struct Scene *scene, Image *ima)
 {
        if(ima->rr)
                return ima->rr;
        if(ima->type==IMA_TYPE_R_RESULT)
-               return RE_GetResult(RE_GetRender(G.scene->id.name));
+               return RE_GetResult(RE_GetRender(scene->id.name));
        return NULL;
 }
 
@@ -1480,9 +1560,11 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
        BLI_strncpy(name, ima->name, sizeof(name));
        
        if(ima->id.lib)
-               BLI_convertstringcode(name, ima->id.lib->filename, frame);
+               BLI_convertstringcode(name, ima->id.lib->filename);
        else
-               BLI_convertstringcode(name, G.sce, frame);
+               BLI_convertstringcode(name, G.sce);
+       
+       BLI_convertstringframe(name, frame); /* TODO - should this be here? */
        
        /* read ibuf */
        ibuf = IMB_loadiffname(name, IB_rect|IB_multilayer);
@@ -1498,13 +1580,17 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
                        ibuf= NULL;
                }
                else {
-                       image_assign_ibuf(ima, ibuf, 0, frame);
                        image_initialize_after_load(ima, ibuf);
+                       image_assign_ibuf(ima, ibuf, 0, frame);
                }
 #else
-               image_assign_ibuf(ima, ibuf, 0, frame);
                image_initialize_after_load(ima, ibuf);
+               image_assign_ibuf(ima, ibuf, 0, frame);
 #endif
+               
+               if(ima->flag & IMA_DO_PREMUL)
+                       converttopremul(ibuf);
+               
        }
        else
                ima->ok= 0;
@@ -1539,8 +1625,9 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
                        // if(oldrr) printf("freed previous result %p\n", oldrr);
                        if(oldrr) RE_FreeRenderResult(oldrr);
                }
-               else
+               else {
                        ima->rr= oldrr;
+               }
 
        }
        if(ima->rr) {
@@ -1555,8 +1642,8 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
                        ibuf->mall= IB_rectfloat;
                        ibuf->channels= rpass->channels;
                        
-                       image_assign_ibuf(ima, ibuf, iuser->multi_index, frame);
                        image_initialize_after_load(ima, ibuf);
+                       image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:0, frame);
                        
                }
                // else printf("pass not found\n");
@@ -1582,9 +1669,9 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
                
                BLI_strncpy(str, ima->name, FILE_MAX);
                if(ima->id.lib)
-                       BLI_convertstringcode(str, ima->id.lib->filename, 0);
+                       BLI_convertstringcode(str, ima->id.lib->filename);
                else
-                       BLI_convertstringcode(str, G.sce, 0);
+                       BLI_convertstringcode(str, G.sce);
                
                ima->anim = openanim(str, IB_cmap | IB_rect);
                
@@ -1602,8 +1689,8 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
                ibuf = IMB_anim_absolute(ima->anim, fra);
                
                if(ibuf) {
-                       image_assign_ibuf(ima, ibuf, 0, frame);
                        image_initialize_after_load(ima, ibuf);
+                       image_assign_ibuf(ima, ibuf, 0, frame);
                }
                else
                        ima->ok= 0;
@@ -1622,6 +1709,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
 {
        struct ImBuf *ibuf;
        char str[FILE_MAX];
+       int assign = 0;
        
        /* always ensure clean ima */
        image_free_buffers(ima);
@@ -1635,9 +1723,11 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
                /* get the right string */
                BLI_strncpy(str, ima->name, sizeof(str));
                if(ima->id.lib)
-                       BLI_convertstringcode(str, ima->id.lib->filename, cfra);
+                       BLI_convertstringcode(str, ima->id.lib->filename);
                else
-                       BLI_convertstringcode(str, G.sce, cfra);
+                       BLI_convertstringcode(str, G.sce);
+               
+               BLI_convertstringframe(str, cfra);
                
                /* read ibuf */
                ibuf = IMB_loadiffname(str, IB_rect|IB_multilayer|IB_imginfo);
@@ -1652,26 +1742,26 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
                        ibuf= NULL;
                }
                else {
-                       image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
                        image_initialize_after_load(ima, ibuf);
+                       assign= 1;
 
                        /* check if the image is a font image... */
                        detectBitmapFont(ibuf);
                        
                        /* make packed file for autopack */
                        if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK))
-                               ima->packedfile = newPackedFile(str);
+                               ima->packedfile = newPackedFile(NULL, str);
                }
                
-               /*ok, this is *not* what a user expects when he clicks the premul
-                 button, that his image is actually changed.  This should be a
-                 render-time option, not a modification to the image! - joeedh*/
-               /*if(ima->flag & IMA_DO_PREMUL)
-                       converttopremul(ibuf);*/
+               if(ima->flag & IMA_DO_PREMUL)
+                       converttopremul(ibuf);
        }
        else
                ima->ok= 0;
        
+       if(assign)
+               image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+
        if(iuser)
                iuser->ok= ima->ok;
        
@@ -1695,12 +1785,13 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
                if(rpass) {
                        ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0);
                        
-                       image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:IMA_NO_INDEX, 0);
                        image_initialize_after_load(ima, ibuf);
                        
                        ibuf->rect_float= rpass->rect;
                        ibuf->flags |= IB_rectfloat;
                        ibuf->channels= rpass->channels;
+
+                       image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:IMA_NO_INDEX, 0);
                }
        }
        
@@ -1715,35 +1806,61 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
 
 /* showing RGBA result itself (from compo/sequence) or
    like exr, using layers etc */
+/* always returns a single ibuf, also during render progress */
 static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser)
 {
-       RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name));
+       Render *re= NULL;
+       RenderResult *rr= NULL;
        
-       if(rr && iuser) {
+       if(iuser && iuser->scene) {
+               re= RE_GetRender(iuser->scene->id.name);
+               rr= RE_GetResult(re);
+       }
+       if(rr==NULL) return NULL;
+       
+       if(RE_RenderInProgress(re)) {
+               ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0);
+               
+               /* make ibuf if needed, and initialize it */
+               /* this only gets called when mutex locked */
+               if(ibuf==NULL) {
+                       ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, IB_rect, 0);
+                       image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+               }
+               return ibuf;
+       }
+       else {
                RenderResult rres;
                float *rectf;
                unsigned int *rect;
-               int channels= 4, layer= iuser->layer;
+               float dither;
+               int channels, layer, pass;
+
+               channels= 4;
+               layer= (iuser)? iuser->layer: 0;
+               pass= (iuser)? iuser->pass: 0;
                
                /* this gives active layer, composite or seqence result */
-               RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
+               RE_GetResultImage(RE_GetRender(iuser->scene->id.name), &rres);
                rect= (unsigned int *)rres.rect32;
                rectf= rres.rectf;
-               
+               dither= iuser->scene->r.dither_intensity;
+
                /* get compo/seq result by default */
                if(rr->rectf && layer==0);
                else if(rr->layers.first) {
-                       RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer-(rr->rectf?1:0));
+                       RenderLayer *rl= BLI_findlink(&rr->layers, layer-(rr->rectf?1:0));
                        if(rl) {
                                /* there's no combined pass, is in renderlayer itself */
-                               if(iuser->pass==0) {
+                               if(pass==0) {
                                        rectf= rl->rectf;
                                }
                                else {
-                                       RenderPass *rpass= BLI_findlink(&rl->passes, iuser->pass-1);
+                                       RenderPass *rpass= BLI_findlink(&rl->passes, pass-1);
                                        if(rpass) {
                                                channels= rpass->channels;
                                                rectf= rpass->rect;
+                                               dither= 0.0f; /* don't dither passes */
                                        }
                                }
                        }
@@ -1768,6 +1885,9 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser)
                        ibuf->rect_float= rectf;
                        ibuf->flags |= IB_rectfloat;
                        ibuf->channels= channels;
+                       ibuf->zbuf_float= rres.rectz;
+                       ibuf->flags |= IB_zbuffloat;
+                       ibuf->dither= dither;
                        
                        ima->ok= IMA_OK_LOADED;
                        return ibuf;
@@ -1777,12 +1897,71 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser)
        return NULL;
 }
 
+static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
+{
+       ImBuf *ibuf = NULL;
+       int frame = 0, index = 0;
+
+       /* see if we already have an appropriate ibuf, with image source and type */
+       if(ima->source==IMA_SRC_MOVIE) {
+               frame= iuser?iuser->framenr:ima->lastframe;
+               ibuf= image_get_ibuf(ima, 0, frame);
+       }
+       else if(ima->source==IMA_SRC_SEQUENCE) {
+               if(ima->type==IMA_TYPE_IMAGE) {
+                       frame= iuser?iuser->framenr:ima->lastframe;
+                       ibuf= image_get_ibuf(ima, 0, frame);
+               }
+               else if(ima->type==IMA_TYPE_MULTILAYER) {
+                       frame= iuser?iuser->framenr:ima->lastframe;
+                       index= iuser?iuser->multi_index:IMA_NO_INDEX;
+                       ibuf= image_get_ibuf(ima, index, frame);
+               }
+       }
+       else if(ima->source==IMA_SRC_FILE) {
+               if(ima->type==IMA_TYPE_IMAGE)
+                       ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0);
+               else if(ima->type==IMA_TYPE_MULTILAYER)
+                       ibuf= image_get_ibuf(ima, iuser?iuser->multi_index:IMA_NO_INDEX, 0);
+       }
+       else if(ima->source == IMA_SRC_GENERATED) {
+               ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0);
+       }
+       else if(ima->source == IMA_SRC_VIEWER) {
+               if(ima->type==IMA_TYPE_R_RESULT) {
+                       /* always verify entirely, not that this shouldn't happen
+                        * during render anyway */
+               }
+               else if(ima->type==IMA_TYPE_COMPOSITE) {
+                       frame= iuser?iuser->framenr:0;
+                       ibuf= image_get_ibuf(ima, 0, frame);
+               }
+       }
+
+       *frame_r = frame;
+       *index_r = index;
+
+       return ibuf;
+}
+
 /* Checks optional ImageUser and verifies/creates ImBuf. */
 /* returns ibuf */
 ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
 {
        ImBuf *ibuf= NULL;
        float color[] = {0, 0, 0, 1};
+       int frame= 0, index= 0;
+
+       /* This function is intended to be thread-safe. It postpones the mutex lock
+        * until it needs to load the image, if the image is already there it
+        * should just get the pointer and return. The reason is that a lot of mutex
+        * locks appears to be very slow on certain multicore macs, causing a render
+        * with image textures to actually slow down as more threads are used.
+        *
+        * Note that all the image loading functions should also make sure they do
+        * things in a threadsafe way for image_get_ibuf_threadsafe to work correct.
+        * That means, the last two steps must be, 1) add the ibuf to the list and
+        * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */
 
        /* quick reject tests */
        if(ima==NULL) 
@@ -1794,69 +1973,61 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
        else if(ima->ok==0)
                return NULL;
        
-       BLI_lock_thread(LOCK_IMAGE);
-       
-       /* handle image source and types */
-       if(ima->source==IMA_SRC_MOVIE) {
-               /* source is from single file, use flipbook to store ibuf */
-               int frame= iuser?iuser->framenr:ima->lastframe;
-               
-               ibuf= image_get_ibuf(ima, 0, frame);
-               if(ibuf==NULL)
-                       ibuf= image_load_movie_file(ima, iuser, frame);
-       }
-       else if(ima->source==IMA_SRC_SEQUENCE) {
-               
-               if(ima->type==IMA_TYPE_IMAGE) {
-                       /* regular files, ibufs in flipbook, allows saving */
-                       int frame= iuser?iuser->framenr:ima->lastframe;
-                       
-                       ibuf= image_get_ibuf(ima, 0, frame);
-                       if(ibuf==NULL)
-                               ibuf= image_load_sequence_file(ima, iuser, frame);
-                       else
-                               BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name));
-               }
-               /* no else; on load the ima type can change */
-               if(ima->type==IMA_TYPE_MULTILAYER) {
-                       /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
-                       int frame= iuser?iuser->framenr:ima->lastframe;
-                       int index= iuser?iuser->multi_index:IMA_NO_INDEX;
-                       
-                       ibuf= image_get_ibuf(ima, index, frame);
-                       if(G.rt) printf("seq multi fra %d id %d ibuf %p %s\n", frame, index, ibuf, ima->id.name);
-                       if(ibuf==NULL)
-                               ibuf= image_load_sequence_multilayer(ima, iuser, frame);
-                       else
-                               BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name));
-               }
+       /* try to get the ibuf without locking */
+       ibuf= image_get_ibuf_threadsafe(ima, iuser, &frame, &index);
 
-       }
-       else if(ima->source==IMA_SRC_FILE) {
-               
-               if(ima->type==IMA_TYPE_IMAGE) {
-                       ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0);
-                       if(ibuf==NULL)
-                               ibuf= image_load_image_file(ima, iuser, G.scene->r.cfra);       /* cfra only for '#', this global is OK */
+       if(ibuf == NULL) {
+               /* couldn't get ibuf and image is not ok, so let's lock and try to
+                * load the image */
+               BLI_lock_thread(LOCK_IMAGE);
+
+               /* need to check ok flag and loading ibuf again, because the situation
+                * might have changed in the meantime */
+               if(iuser) {
+                       if(iuser->ok==0) {
+                               BLI_unlock_thread(LOCK_IMAGE);
+                               return NULL;
+                       }
                }
-               /* no else; on load the ima type can change */
-               if(ima->type==IMA_TYPE_MULTILAYER) {
-                       /* keeps render result, stores ibufs in listbase, allows saving */
-                       ibuf= image_get_ibuf(ima, iuser?iuser->multi_index:IMA_NO_INDEX, 0);
-                       if(ibuf==NULL)
-                               ibuf= image_get_ibuf_multilayer(ima, iuser);
+               else if(ima->ok==0) {
+                       BLI_unlock_thread(LOCK_IMAGE);
+                       return NULL;
                }
-                       
-       }
-       else if(ima->source == IMA_SRC_GENERATED) {
-               /* generated is: ibuf is allocated dynamically */
-               ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0);
-               
-               if(ibuf==NULL) {
-                       if(ima->type==IMA_TYPE_VERSE) {
-                               /* todo */
+
+               ibuf= image_get_ibuf_threadsafe(ima, iuser, &frame, &index);
+
+               if(ibuf == NULL) {
+                       /* we are sure we have to load the ibuf, using source and type */
+                       if(ima->source==IMA_SRC_MOVIE) {
+                               /* source is from single file, use flipbook to store ibuf */
+                               ibuf= image_load_movie_file(ima, iuser, frame);
+                       }
+                       else if(ima->source==IMA_SRC_SEQUENCE) {
+                               if(ima->type==IMA_TYPE_IMAGE) {
+                                       /* regular files, ibufs in flipbook, allows saving */
+                                       ibuf= image_load_sequence_file(ima, iuser, frame);
+                               }
+                               /* no else; on load the ima type can change */
+                               if(ima->type==IMA_TYPE_MULTILAYER) {
+                                       /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
+                                       ibuf= image_load_sequence_multilayer(ima, iuser, frame);
+                               }
+
+                               if(ibuf)
+                                       BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name));
                        }
-                       else { /* always fall back to IMA_TYPE_UV_TEST */
+                       else if(ima->source==IMA_SRC_FILE) {
+                               
+                               if(ima->type==IMA_TYPE_IMAGE)
+                                       ibuf= image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */
+                               /* no else; on load the ima type can change */
+                               if(ima->type==IMA_TYPE_MULTILAYER)
+                                       /* keeps render result, stores ibufs in listbase, allows saving */
+                                       ibuf= image_get_ibuf_multilayer(ima, iuser);
+                                       
+                       }
+                       else if(ima->source == IMA_SRC_GENERATED) {
+                               /* generated is: ibuf is allocated dynamically */
                                /* UV testgrid or black or solid etc */
                                if(ima->gen_x==0) ima->gen_x= 256;
                                if(ima->gen_y==0) ima->gen_y= 256;
@@ -1864,31 +2035,28 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
                                image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
                                ima->ok= IMA_OK_LOADED;
                        }
-               }
-       }
-       else if(ima->source == IMA_SRC_VIEWER) {
-               if(ima->type==IMA_TYPE_R_RESULT) {
-                       /* always verify entirely */
-                       ibuf= image_get_render_result(ima, iuser);
-               }
-               else if(ima->type==IMA_TYPE_COMPOSITE) {
-                       int frame= iuser?iuser->framenr:0;
-                       
-                       /* Composite Viewer, all handled in compositor */
-                       ibuf= image_get_ibuf(ima, 0, frame);
-                       if(ibuf==NULL) {
-                               /* fake ibuf, will be filled in compositor */
-                               ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0);
-                               image_assign_ibuf(ima, ibuf, 0, frame);
+                       else if(ima->source == IMA_SRC_VIEWER) {
+                               if(ima->type==IMA_TYPE_R_RESULT) {
+                                       /* always verify entirely */
+                                       ibuf= image_get_render_result(ima, iuser);
+                               }
+                               else if(ima->type==IMA_TYPE_COMPOSITE) {
+                                       /* Composite Viewer, all handled in compositor */
+                                       /* fake ibuf, will be filled in compositor */
+                                       ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0);
+                                       image_assign_ibuf(ima, ibuf, 0, frame);
+                               }
                        }
                }
+
+               BLI_unlock_thread(LOCK_IMAGE);
        }
 
+       /* we assuming that if it is not rendering, it's also not multithreaded
+        * (a somewhat weak assumption) */
        if(G.rendering==0)
                tag_image_time(ima);
 
-       BLI_unlock_thread(LOCK_IMAGE);
-
        return ibuf;
 }