Further work on the premul option for ton. This option
authorJoseph Eagar <joeedh@gmail.com>
Mon, 18 Feb 2008 23:50:12 +0000 (23:50 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Mon, 18 Feb 2008 23:50:12 +0000 (23:50 +0000)
(which basically tells the renderer and compositor to expect a
key image) is now done at the image user level.

This does have some caveats, as image users don't always work
the way I thought they would/should (for example, the same image user
structure is apparently used in the uv image editor for all images,
which is kindof odd).

The UV image editor also now smartly detects if the premul option is
set and draws the image using key alpha, instead of premul

The subversion level was upped to convert the old premul flag, which was at
the image level, to the new one, which is at the image user level.

source/blender/blenkernel/BKE_blender.h
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_image_types.h
source/blender/nodes/intern/CMP_nodes/CMP_image.c
source/blender/render/intern/source/texture.c
source/blender/src/buttons_shading.c
source/blender/src/drawimage.c
source/blender/src/drawnode.c

index 6c3ff3f3467fd33350b03525692fb9e9f68d8835..d81eb4d510378de058b56ee0b2df7874540b0238 100644 (file)
@@ -44,7 +44,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        245
-#define BLENDER_SUBVERSION             14
+#define BLENDER_SUBVERSION             15
 
 #define BLENDER_MINVERSION             240
 #define BLENDER_MINSUBVERSION  0
index 3207bed2139c35daed617bef2e2878ef9fbfc511..3019d1756896994f97f3d238fa19112765f1c8fe 100644 (file)
@@ -2419,6 +2419,7 @@ static void lib_link_texture(FileData *fd, Main *main)
                if(tex->id.flag & LIB_NEEDLINK) {
 
                        tex->ima= newlibadr_us(fd, tex->id.lib, tex->ima);
+
                        tex->ipo= newlibadr_us(fd, tex->id.lib, tex->ipo);
                        if(tex->env) tex->env->object= newlibadr(fd, tex->id.lib, tex->env->object);
 
@@ -7450,7 +7451,56 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       
+       /*version patch to migrate premul flag from images to image users*/
+       if (main->versionfile < 245 || (main->versionfile == 245 && main->subversionfile < 15)) {
+               Tex *tex;
+               Image *image;
+               ImageUser *iuser;
+               Scene *scene;
+               bNode *node;
+               bNodeTree *ntree;
+               
+               /*handle image textures*/
+               for (tex=main->tex.first; tex; tex=tex->id.next) {
+                       if (tex->ima) {
+                               image = newlibadr(fd, lib, tex->ima);
+                               if (image->flag & IMA_OLDFLAG) tex->iuser.flag |= IMA_DO_PREMUL;
+                       }
+               }
+
+               /*handle composite node trees*/
+               for (scene=main->scene.first; scene; scene=scene->id.next) {
+                       if (scene->nodetree) {
+                               for (node=scene->nodetree->nodes.first; node; node=node->next) {
+                                       ID *nodeid = newlibadr(fd, lib, node->id);
+                                       if (node->storage && nodeid && *(short*)nodeid->name == ID_IM) {
+                                               image = (Image*) nodeid;
+                                               iuser = node->storage;
+                                               if (image->flag & IMA_OLDFLAG) iuser->flag |= IMA_DO_PREMUL;
+                                       }
+                               }
+                       }
+               }
+
+               /*handle node groups*/
+               for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               for (node=ntree->nodes.first; node; node=node->next) {
+                                       ID *nodeid = newlibadr(fd, lib, node->id);
+                                       if (node->storage && nodeid && *(short*)nodeid->name == ID_IM) {
+                                               image = (Image*) nodeid;
+                                               iuser = node->storage;
+                                               if (image->flag & IMA_OLDFLAG) iuser->flag |= IMA_DO_PREMUL;
+                                       }
+                               }
+                       }
+               }
+
+               /*finally, remove the flag from all images*/
+               for (image=main->image.first; image; image=image->id.next) {
+                       if (image->flag & IMA_OLDFLAG) image->flag &= ~IMA_OLDFLAG;
+               }
+       }
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
index d5e4b7a11420bc844670300ab9e9f0ac0f560a52..bc94f807baa2c6d0f079c92753ec3eb018e11dae 100644 (file)
@@ -58,6 +58,7 @@ typedef struct ImageUser {
 /* iuser->flag */
 #define        IMA_ANIM_ALWAYS         1
 #define IMA_ANIM_REFRESHED     2
+#define IMA_DO_PREMUL          4
 
 typedef struct Image {
        ID id;
@@ -108,7 +109,12 @@ typedef struct Image {
 #define        IMA_REFLECT             16
 #define IMA_NOCOLLECT   32
 #define IMA_ANTIALI            64
-#define IMA_DO_PREMUL  128
+
+/*used to be IMA_DO_PREMUL.  Note that
+  in theory, in should be possible
+  to use this flag position if necassary,
+  since this is only used in do_versions.*/
+#define IMA_OLDFLAG            128 
 
 /* tpageflag */
 #define IMA_TILES                      1
index 06c3b90e8289f9f3486bb7f03375c8559736f767..5df649d6808ff4ccc8fd8ae22c8fe83ed37bdce9 100644 (file)
@@ -58,7 +58,7 @@ static bNodeSocketType cmp_node_rlayers_out[]= {
 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
 {
        ImBuf *ibuf;
-       CompBuf *stackbuf;
+       CompBuf *stackbuf, *old;
        int type;
        
        ibuf= BKE_image_get_ibuf(ima, iuser);
@@ -79,10 +79,11 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
                stackbuf->rect= ibuf->rect_float;
        }
        
-       /*code to respect the premul flag of images; I'm
-         not sure if this is a good idea for multilayer images,
-         since it never worked before for them.
-       if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
+       old = stackbuf;
+       stackbuf = dupalloc_compbuf(stackbuf);
+       free_compbuf(old);      
+
+       if (type==CB_RGBA && iuser && (iuser->flag & IMA_DO_PREMUL)) {
                //premul the image
                int i;
                float *pixel = stackbuf->rect;
@@ -93,7 +94,7 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
                        pixel[2] *= pixel[3];
                }
        }
-       */
+       
        return stackbuf;
 };
 
@@ -202,27 +203,6 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, b
                else {
                        stackbuf= node_composit_get_image(rd, ima, iuser);
                        
-                       /*respect image premul option*/
-                       if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
-                               int i;
-                               float *pixel;
-                       
-                               /*first duplicate stackbuf->rect, since it's just a pointer
-                                 to the source imbuf, and we don't want to change that.*/
-                               stackbuf->rect = MEM_dupallocN(stackbuf->rect);
-                               
-                               /*flag that we can free the buffer.*/
-                               stackbuf->malloc = 1;
-                               
-                               /*premul the image*/                            
-                               pixel = stackbuf->rect;
-                               for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
-                                       pixel[0] *= pixel[3];
-                                       pixel[1] *= pixel[3];
-                                       pixel[2] *= pixel[3];
-                               }
-                       }
-                       
                        /* put image on stack */        
                        out[0]->data= stackbuf;
                        
index 5de1757b56da6b6e82550250c4320767df9adfcd..4fc79a942a62d19d070d73efc26143f5c73d99c6 100644 (file)
@@ -1140,7 +1140,7 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex,
                tag_image_time(tex->ima); /* tag image as having being used */
                
                /*do premul if necassary*/
-               if (tex->ima && tex->ima->flag & IMA_DO_PREMUL) {
+               if (tex->iuser.flag & IMA_DO_PREMUL) {
                        texres->tr *= texres->ta;
                        texres->tg *= texres->ta;
                        texres->tb *= texres->ta;
index 31f22e5cd80a1bd47fba5e97d12c5b346e6f58f0..d8f50395bba19ade6590655732e7fb49816e6908 100644 (file)
@@ -1181,7 +1181,7 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser,
                 
                 uiBlockSetFunc(block, image_reload_cb, ima, iuser);
                 uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti",                   10, 50, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors");
-                uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul",                55, 50, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha");
+                uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul",                55, 50, 65, 20, &iuser->flag, 0, 0, 0, 0, "Toggles whether to premultiply the image at render/composite time.");
                 uiBlockEndAlign(block);
                 
                 if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
@@ -2559,7 +2559,7 @@ static void lamp_panel_spot(Object *ob, Lamp *la)
                                tip= "Irregular buffer produces sharp shadow always, but it doesn't show up for raytracing";
                        else if(la->buftype==LA_SHADBUF_HALFWAY)
                                tip= "Regular buffer, averaging the closest and 2nd closest Z value for reducing biasing";
-                       
+                               
                        uiDefButC(block, MENU, B_REDR, "Classical %x0|Classic-Halfway %x2|Irregular %x1", 10,140,80,19,&la->buftype, 0, 0, 0, 0, tip);
                }
        }
@@ -2655,7 +2655,6 @@ static void lamp_panel_spot(Object *ob, Lamp *la)
                        }
                }
                
-               
        }
        else uiDefBut(block, LABEL,0," ",       100,180,200,19,NULL, 0, 0, 0, 0, "");
 
index 824c9f5232c04258096ea14d677195c2bb2089df..0b3b98bde2d3886e3f5aef1ceebae69c2df0814a 100644 (file)
@@ -2060,7 +2060,11 @@ void drawimagespace(ScrArea *sa, void *spacedata)
                                                        if(sima->flag & SI_USE_ALPHA) {
                                                                sima_draw_alpha_backdrop(sima, x1_rep, y1_rep, (float)ibuf->x, (float)ibuf->y);
                                                                glEnable(GL_BLEND);
-                                                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                                                               /*use key alpha if the IMA_DO_PREMUL option is set.*/
+                                                               if (sima->iuser.flag & IMA_DO_PREMUL)
+                                                                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                                                               else
+                                                                       glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
                                                        }
                                                        
                                                        /* detect if we need to redo the curve map. 
index 54475eb362e23c31eb8cf8b9a095a8759f5237c9..5b4975401b3d8fa988f43997ae2ee6053e8abb50 100644 (file)
@@ -938,7 +938,7 @@ static void image_layer_cb(void *ima_v, void *iuser_v)
 {
        
        ntreeCompositForceHidden(G.scene->nodetree);
-       BKE_image_multilayer_index(ima_v, iuser_v);
+       BKE_image_multilayer_index(BKE_image_get_renderresult(ima_v), iuser_v);
        allqueue(REDRAWNODE, 0);
 }
 
@@ -995,6 +995,11 @@ static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *nod
                        uiButSetFunc(bt, node_image_type_cb, node, ima);
                        MEM_freeN(strp);
                        
+                       if (iuser) {
+                               dy -= 19;
+                               uiDefButBitS(block, TOG, IMA_DO_PREMUL, B_NODE_EXEC+node->nr, "Premul", xmin, dy, xmax-xmin, 20, &iuser->flag, 0, 0, 0, 0, "Toggles whether to premultiply the image at render/composite time.");
+                       }
+
                        if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
                                width= (xmax-xmin)/2;
                                
@@ -1034,7 +1039,7 @@ static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *nod
        }       
        if(node->id) {
                Image *ima= (Image *)node->id;
-               int retval= 19;
+               int retval= 19*2;
                
                /* for each draw we test for anim refresh event */
                if(iuser->flag & IMA_ANIM_REFRESHED) {