static void node_composit_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order input: fac, image, black level, white level */ /* stack order output: image */ if (out[0]->hasoutput==0) return; curvemapping_initialize(node->storage); /* input no image? then only color operation */ if (in[1]->data==NULL) { curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[1]->vec); } else { /* make output size of input image */ CompBuf *cbuf= in[1]->data; CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ curvemapping_set_black_white(node->storage, in[2]->vec, in[3]->vec); if (in[0]->data==NULL && in[0]->vec[0] == 1.0f) composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA); else composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL); out[0]->data= stackbuf; } }
static void node_composit_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf *cbuf=in[0]->data; CompBuf *cbuf2=in[1]->data; CompBuf *stackbuf; /* check for inputs and outputs for early out*/ if(out[0]->hasoutput==0) return; /* no image-color operation */ if(in[0]->data==NULL && in[1]->data==NULL) { do_math(node, out[0]->vec, in[0]->vec, in[1]->vec); return; } /*create output based on first input */ if(cbuf) { stackbuf=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); } /* and if it doesn't exist use the second input since we know that one of them must exist at this point*/ else { stackbuf=alloc_compbuf(cbuf2->x, cbuf2->y, CB_VAL, 1); } /* operate in case there's valid size */ composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_math, CB_VAL, CB_VAL); out[0]->data= stackbuf; }
/* applies to render pipeline */ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { /* image assigned to output */ /* stack order input sockets: col, alpha, z */ if(node->flag & NODE_DO_OUTPUT) { /* only one works on out */ Scene *scene= (Scene *)node->id; RenderData *rd= data; if(scene && (rd->scemode & R_DOCOMP)) { Render *re= RE_GetRender(scene->id.name); RenderResult *rr= RE_AcquireResultWrite(re); if(rr) { CompBuf *outbuf, *zbuf=NULL; if(rr->rectf) MEM_freeN(rr->rectf); outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1); if(in[1]->data==NULL) composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA); else composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); if(in[2]->data) { if(rr->rectz) MEM_freeN(rr->rectz); zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1); composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); rr->rectz= zbuf->rect; zbuf->malloc= 0; free_compbuf(zbuf); } generate_preview(data, node, outbuf); /* we give outbuf to rr... */ rr->rectf= outbuf->rect; outbuf->malloc= 0; free_compbuf(outbuf); RE_ReleaseResult(re); /* signal for imageviewer to refresh (it converts to byte rects...) */ BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); return; } else RE_ReleaseResult(re); } } if(in[0]->data) generate_preview(data, node, in[0]->data); }
static void node_composit_exec_gamma(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order in: Fac, Image */ /* stack order out: Image */ if(out[0]->hasoutput==0) return; /* input no image? then only color operation */ if(in[0]->data==NULL) { do_gamma(node, out[0]->vec, in[0]->vec, in[1]->vec); } else { /* make output size of input image */ CompBuf *cbuf= in[0]->data; CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs composit2_pixel_processor(node, stackbuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_gamma, CB_RGBA, CB_VAL); out[0]->data= stackbuf; } }
static void node_composit_exec_diff_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf *outbuf=0; CompBuf *imbuf1=0; CompBuf *imbuf2=0; NodeChroma *c; /*is anything connected?*/ if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return; /*must have an image imput*/ if(in[0]->data==NULL) return; imbuf1=typecheck_compbuf(in[0]->data, CB_RGBA); /* if there's an image, use that, if not use the color */ if(in[1]->data) { imbuf2=typecheck_compbuf(in[1]->data, CB_RGBA); } c=node->storage; outbuf=dupalloc_compbuf(imbuf1); /* note, processor gets a keyvals array passed on as buffer constant */ composit2_pixel_processor(node, outbuf, imbuf1, in[0]->vec, imbuf2, in[1]->vec, do_diff_matte, CB_RGBA, CB_RGBA); out[0]->data=outbuf; if(out[1]->hasoutput) out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); generate_preview(data, node, outbuf); if(imbuf1!=in[0]->data) free_compbuf(imbuf1); if(imbuf2!=in[1]->data) free_compbuf(imbuf2); }
static void node_composit_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order in: Fac, Image */ /* stack order out: Image */ if(out[0]->hasoutput==0) return; /* input no image? then only color operation */ if(in[1]->data==NULL) { do_hue_sat_fac(node, out[0]->vec, in[1]->vec, in[0]->vec); } else { /* make output size of input image */ CompBuf *cbuf= dupalloc_compbuf(in[1]->data); CompBuf *stackbuf=typecheck_compbuf(cbuf,CB_RGBA); composit2_pixel_processor(node, stackbuf, stackbuf, in[1]->vec, in[0]->data, in[0]->vec, do_hue_sat_fac, CB_RGBA, CB_VAL); out[0]->data= stackbuf; /* get rid of intermediary cbuf if it's extra */ if(stackbuf!=cbuf) free_compbuf(cbuf); } }
static void node_composit_exec_color_spill(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* Originally based on the information from the book "The Art and Science of Digital Composition" and * discussions from vfxtalk.com .*/ CompBuf *cbuf; /* CompBuf *mask; */ /* UNUSED */ CompBuf *rgbbuf; CompBuf *spillmap; NodeColorspill *ncs; ncs=node->storage; /* early out for missing connections */ if(out[0]->hasoutput==0 ) return; if(in[0]->hasinput==0) return; if(in[0]->data==NULL) return; cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); /* mask= */ /* UNUSED */ typecheck_compbuf(in[1]->data, CB_VAL); spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); rgbbuf=dupalloc_compbuf(cbuf); switch(node->custom1) { case 1: /*red spill*/ { switch(node->custom2) { case 0: /* simple limit */ { if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA); } else { composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA, CB_VAL); } break; } case 1: /* average limit */ { if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA); } else { composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_red_fac, CB_RGBA, CB_VAL); } break; } } if(ncs->unspill==0) { ncs->uspillr=1.0f; ncs->uspillg=0.0f; ncs->uspillb=0.0f; } composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_red, CB_RGBA, CB_VAL); break; } case 2: /*green spill*/ { switch(node->custom2) { case 0: /* simple limit */ { if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_green, CB_RGBA); } else { composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_green_fac, CB_RGBA, CB_VAL); } break; } case 1: /* average limit */ { if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_green, CB_RGBA); } else { composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA, CB_VAL); } break; } } if(ncs->unspill==0) { ncs->uspillr=0.0f; ncs->uspillg=1.0f; ncs->uspillb=0.0f; } composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL); break; } case 3: /*blue spill*/ { switch(node->custom2) { case 0: /* simple limit */ { if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA); } else { composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA, CB_VAL); } break; } case 1: /* average limit */ { if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA); } else { composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA, CB_VAL); } break; } } if(ncs->unspill==0) { ncs->uspillr=0.0f; ncs->uspillg=0.0f; ncs->uspillb=1.0f; } composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL); break; } default: break; } out[0]->data=rgbbuf; if(cbuf!=in[0]->data) free_compbuf(cbuf); free_compbuf(spillmap); }
static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) { /* image assigned to output */ /* stack order input sockets: col, alpha, z */ if (node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ RenderData *rd= data; Image *ima= (Image *)node->id; ImBuf *ibuf; CompBuf *cbuf, *tbuf; int rectx, recty; void *lock; BKE_image_user_frame_calc(node->storage, rd->cfra, 0); /* always returns for viewer image, but we check nevertheless */ ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf==NULL) { printf("node_composit_exec_viewer error\n"); BKE_image_release_ibuf(ima, lock); return; } /* free all in ibuf */ imb_freerectImBuf(ibuf); imb_freerectfloatImBuf(ibuf); IMB_freezbuffloatImBuf(ibuf); /* get size */ tbuf= in[0]->data?in[0]->data:(in[1]->data?in[1]->data:in[2]->data); if (tbuf==NULL) { rectx= 320; recty= 256; } else { rectx= tbuf->x; recty= tbuf->y; } /* make ibuf, and connect to ima */ ibuf->x= rectx; ibuf->y= recty; imb_addrectfloatImBuf(ibuf); ima->ok= IMA_OK_LOADED; /* now we combine the input with ibuf */ cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0); /* no alloc*/ cbuf->rect= ibuf->rect_float; /* when no alpha, we can simply copy */ if (in[1]->data==NULL) { composit1_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA); } else composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); /* zbuf option */ if (in[2]->data) { CompBuf *zbuf= alloc_compbuf(rectx, recty, CB_VAL, 1); ibuf->zbuf_float= zbuf->rect; ibuf->mall |= IB_zbuffloat; composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); /* free compbuf, but not the rect */ zbuf->malloc= 0; free_compbuf(zbuf); } BKE_image_release_ibuf(ima, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); } else if (in[0]->data) { generate_preview(data, node, in[0]->data); } }
static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { RenderData *rd= data; CompBuf *cbuf= in[0]->data; CompBuf *zbuf; /* stack order in: col z col z */ /* stack order out: col z */ if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; /* no input image; do nothing now */ if (in[0]->data==NULL) { return; } if (out[1]->hasoutput) { /* copy or make a buffer for for the first z value, here we write result in */ if (in[1]->data) zbuf= dupalloc_compbuf(in[1]->data); else { float *zval; int tot= cbuf->x*cbuf->y; zbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); for (zval= zbuf->rect; tot; tot--, zval++) *zval= in[1]->vec[0]; } /* lazy coder hack */ node->custom2= 1; out[1]->data= zbuf; } else { node->custom2= 0; zbuf= in[1]->data; } if (rd->scemode & R_FULL_SAMPLE) { /* make output size of first input image */ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, zbuf, in[1]->vec, in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, do_zcombine, CB_RGBA, CB_VAL, CB_RGBA, CB_VAL); out[0]->data= stackbuf; } else { /* make output size of first input image */ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ CompBuf *mbuf; float *fp; int x; char *aabuf; /* make a mask based on comparison, optionally write zvalue */ mbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); composit2_pixel_processor(node, mbuf, zbuf, in[1]->vec, in[3]->data, in[3]->vec, do_zcombine_mask, CB_VAL, CB_VAL); /* convert to char */ aabuf= MEM_mallocN(cbuf->x*cbuf->y, "aa buf"); fp= mbuf->rect; for (x= cbuf->x*cbuf->y-1; x>=0; x--) if (fp[x]==0.0f) aabuf[x]= 0; else aabuf[x]= 255; antialias_tagbuf(cbuf->x, cbuf->y, aabuf); /* convert to float */ fp= mbuf->rect; for (x= cbuf->x*cbuf->y-1; x>=0; x--) if (aabuf[x]>1) fp[x]= (1.0f/255.0f)*(float)aabuf[x]; composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[2]->data, in[2]->vec, mbuf, NULL, do_zcombine_add, CB_RGBA, CB_RGBA, CB_VAL); /* free */ free_compbuf(mbuf); MEM_freeN(aabuf); out[0]->data= stackbuf; } }