static void node_composit_exec_displace(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) { if(out[0]->hasoutput==0) return; if(in[0]->data && in[1]->data) { CompBuf *cbuf= in[0]->data; CompBuf *vecbuf= in[1]->data; CompBuf *xbuf= in[2]->data; CompBuf *ybuf= in[3]->data; CompBuf *stackbuf; cbuf= typecheck_compbuf(cbuf, CB_RGBA); vecbuf= typecheck_compbuf(vecbuf, CB_VEC3); xbuf= typecheck_compbuf(xbuf, CB_VAL); ybuf= typecheck_compbuf(ybuf, CB_VAL); stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ do_displace(stackbuf, cbuf, vecbuf, in[1]->vec, xbuf, ybuf, in[2]->vec, in[3]->vec); out[0]->data= stackbuf; if(cbuf!=in[0]->data) free_compbuf(cbuf); if(vecbuf!=in[1]->data) free_compbuf(vecbuf); } }
static void streaks(NodeGlare* ndg, CompBuf* dst, CompBuf* src) { CompBuf *bsrc, *tsrc, *tdst, *sbuf; int x, y, n; unsigned int nump=0; fRGB c1, c2, c3, c4; float a, ang = 360.f/(float)ndg->angle; bsrc = BTP(src, ndg->threshold, 1 << ndg->quality); tsrc = dupalloc_compbuf(bsrc); // sample from buffer tdst = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // sample to buffer sbuf = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // streak sum buffer for (a=0.f; a<360.f; a+=ang) { const float an = (a + (float)ndg->angle_ofs)*(float)M_PI/180.f; const float vx = cos((double)an), vy = sin((double)an); for (n=0; n<ndg->iter; ++n) { const float p4 = pow(4.0, (double)n); const float vxp = vx*p4, vyp = vy*p4; const float wt = pow((double)ndg->fade, (double)p4); const float cmo = 1.f - pow((double)ndg->colmod, (double)n+1); // colormodulation amount relative to current pass float* tdstcol = tdst->rect; for (y=0; y<tsrc->y; ++y) { for (x=0; x<tsrc->x; ++x, tdstcol+=4) { // first pass no offset, always same for every pass, exact copy, // otherwise results in uneven brightness, only need once if (n==0) qd_getPixel(tsrc, x, y, c1); else c1[0]=c1[1]=c1[2]=0; qd_getPixelLerp(tsrc, x + vxp, y + vyp, c2); qd_getPixelLerp(tsrc, x + vxp*2.f, y + vyp*2.f, c3); qd_getPixelLerp(tsrc, x + vxp*3.f, y + vyp*3.f, c4); // modulate color to look vaguely similar to a color spectrum fRGB_rgbmult(c2, 1.f, cmo, cmo); fRGB_rgbmult(c3, cmo, cmo, 1.f); fRGB_rgbmult(c4, cmo, 1.f, cmo); tdstcol[0] = 0.5f*(tdstcol[0] + c1[0] + wt*(c2[0] + wt*(c3[0] + wt*c4[0]))); tdstcol[1] = 0.5f*(tdstcol[1] + c1[1] + wt*(c2[1] + wt*(c3[1] + wt*c4[1]))); tdstcol[2] = 0.5f*(tdstcol[2] + c1[2] + wt*(c2[2] + wt*(c3[2] + wt*c4[2]))); } } memcpy(tsrc->rect, tdst->rect, sizeof(float)*tdst->x*tdst->y*tdst->type); } addImage(sbuf, tsrc, 1.f/(float)(6 - ndg->iter)); memset(tdst->rect, 0, tdst->x*tdst->y*tdst->type*sizeof(float)); memcpy(tsrc->rect, bsrc->rect, bsrc->x*bsrc->y*bsrc->type*sizeof(float)); nump++; } mixImages(dst, sbuf, 0.5f + 0.5f*ndg->mix); free_compbuf(tsrc); free_compbuf(tdst); free_compbuf(sbuf); free_compbuf(bsrc); }
/* 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_dilateerode(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order in: mask */ /* stack order out: mask */ if (out[0]->hasoutput == 0) return; /* input no image? then only color operation */ if (in[0]->data == NULL) { zero_v4(out[0]->vec); } else { /* make output size of input image */ CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_VAL); CompBuf *stackbuf = dupalloc_compbuf(cbuf); short i; if (node->custom2 > 0) { // positive, dilate for (i = 0; i < node->custom2; i++) morpho_dilate(stackbuf); } else if (node->custom2 < 0) { // negative, erode for (i = 0; i > node->custom2; i--) morpho_erode(stackbuf); } if (cbuf != in[0]->data) free_compbuf(cbuf); out[0]->data = stackbuf; } }
static void node_composit_exec_seprgba(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) { /* stack order out: bw channels */ /* stack order in: col */ /* input no image? then only color operation */ if (in[0]->data==NULL) { out[0]->vec[0] = in[0]->vec[0]; out[1]->vec[0] = in[0]->vec[1]; out[2]->vec[0] = in[0]->vec[2]; out[3]->vec[0] = in[0]->vec[3]; } else { /* make sure we get right rgba buffer */ CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); /* don't do any pixel processing, just copy the stack directly (faster, I presume) */ if (out[0]->hasoutput) out[0]->data= valbuf_from_rgbabuf(cbuf, CHAN_R); if (out[1]->hasoutput) out[1]->data= valbuf_from_rgbabuf(cbuf, CHAN_G); if (out[2]->hasoutput) out[2]->data= valbuf_from_rgbabuf(cbuf, CHAN_B); if (out[3]->hasoutput) out[3]->data= valbuf_from_rgbabuf(cbuf, CHAN_A); if (cbuf!=in[0]->data) free_compbuf(cbuf); } }
static void node_composit_exec_channel_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf *cbuf; CompBuf *outbuf; if(in[0]->hasinput==0) return; if(in[0]->data==NULL) return; if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return; cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); outbuf=dupalloc_compbuf(cbuf); /*convert to colorspace*/ switch(node->custom1) { case 1: /*RGB */ break; case 2: /*HSV*/ composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA); break; case 3: /*YUV*/ composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA); break; case 4: /*YCC*/ composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_normalized_rgba_to_ycca2, CB_RGBA); break; default: break; } /*use the selected channel information to do the key */ composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_channel_matte, CB_RGBA); /*convert back to RGB colorspace in place*/ switch(node->custom1) { case 1: /*RGB*/ break; case 2: /*HSV*/ composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA); break; case 3: /*YUV*/ composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA); break; case 4: /*YCC*/ composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_normalized_ycca_to_rgba2, CB_RGBA); break; default: break; } generate_preview(data, node, outbuf); out[0]->data=outbuf; if(out[1]->hasoutput) out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); if(cbuf!=in[0]->data) free_compbuf(cbuf); }
static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf* cbuf; CompBuf* histogram; RenderData *rd=data; float mean, std_dev; int bins[256]; int x; if(in[0]->hasinput==0) return; if(in[0]->data==NULL) return; histogram=alloc_compbuf(256, 256, CB_RGBA, 1); cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); /*initalize bins*/ for(x=0; x<256; x++) { bins[x]=0; } /*fill bins */ fill_bins(node, in[0]->data, bins, rd->color_mgt_flag & R_COLOR_MANAGEMENT); /* draw the histogram chart */ draw_histogram(node, histogram, bins); /* calculate the average brightness and contrast */ mean=brightness_mean(node, in[0]->data); std_dev=brightness_standard_deviation(node, in[0]->data, mean); /* Printf debuging ;) printf("Mean: %f\n", mean); printf("Std Dev: %f\n", std_dev); */ if(out[0]->hasoutput) out[0]->vec[0]= mean; if(out[1]->hasoutput) out[1]->vec[0]= std_dev; generate_preview(data, node, histogram); if(cbuf!=in[0]->data) free_compbuf(cbuf); free_compbuf(histogram); }
/* node->custom1 stores if input values are absolute or relative scale */ static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { if(out[0]->hasoutput==0) return; if(in[0]->data) { RenderData *rd= data; CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); ImBuf *ibuf; int newx, newy; if(node->custom1==CMP_SCALE_RELATIVE) { newx= MAX2((int)(in[1]->vec[0]*cbuf->x), 1); newy= MAX2((int)(in[2]->vec[0]*cbuf->y), 1); } else if(node->custom1==CMP_SCALE_SCENEPERCENT) { newx = cbuf->x * (rd->size / 100.0f); newy = cbuf->y * (rd->size / 100.0f); } else { /* CMP_SCALE_ABSOLUTE */ newx= MAX2((int)in[1]->vec[0], 1); newy= MAX2((int)in[2]->vec[0], 1); } newx= MIN2(newx, CMP_SCALE_MAX); newy= MIN2(newy, CMP_SCALE_MAX); ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0); if(ibuf) { ibuf->rect_float= cbuf->rect; IMB_scaleImBuf(ibuf, newx, newy); if(ibuf->rect_float == cbuf->rect) { /* no scaling happened. */ stackbuf= pass_on_compbuf(in[0]->data); } else { stackbuf= alloc_compbuf(newx, newy, CB_RGBA, 0); stackbuf->rect= ibuf->rect_float; stackbuf->malloc= 1; } ibuf->rect_float= NULL; ibuf->mall &= ~IB_rectfloat; IMB_freeImBuf(ibuf); /* also do the translation vector */ stackbuf->xof = (int)(((float)newx/(float)cbuf->x) * (float)cbuf->xof); stackbuf->yof = (int)(((float)newy/(float)cbuf->y) * (float)cbuf->yof); } else { stackbuf= dupalloc_compbuf(cbuf); printf("Scaling to %dx%d failed\n", newx, newy); } out[0]->data= stackbuf; if(cbuf!=in[0]->data) free_compbuf(cbuf); } };
static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { if (in[0]->data) { if (node->id) { MovieClip *clip = (MovieClip *)node->id; CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); CompBuf *stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 0); ImBuf *ibuf; ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); if (ibuf) { RenderData *rd = data; ImBuf *obuf; MovieTracking *tracking = &clip->tracking; int width, height; float overscan = 0.0f; MovieClipUser user = {0}; BKE_movieclip_user_set_frame(&user, rd->cfra); ibuf->rect_float = cbuf->rect; BKE_movieclip_get_size(clip, &user, &width, &height); if (!node->storage) node->storage = BKE_tracking_distortion_create(); if (node->custom1 == 0) obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 1); else obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 0); stackbuf->rect = obuf->rect_float; stackbuf->malloc = TRUE; obuf->mall &= ~IB_rectfloat; obuf->rect_float = NULL; IMB_freeImBuf(ibuf); IMB_freeImBuf(obuf); } /* pass on output and free */ out[0]->data = stackbuf; if (cbuf != in[0]->data) free_compbuf(cbuf); } else { CompBuf *cbuf = in[0]->data; CompBuf *stackbuf = pass_on_compbuf(cbuf); out[0]->data = stackbuf; } } }
static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sock; for (sock= node->outputs.first; sock; sock= sock->next) { if (sock->cache) { free_compbuf(sock->cache); sock->cache= NULL; } } }
static void node_composit_exec_sepyuva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order out: bw channels */ /* stack order in: col */ /* input no image? then only color operation */ if(in[0]->data==NULL) { float y, u, v; rgb_to_yuv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &u, &v); out[0]->vec[0] = y; out[1]->vec[0] = u; out[2]->vec[0] = v; out[3]->vec[0] = in[0]->vec[3]; } else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) { /* make copy of buffer so input image doesn't get corrupted */ CompBuf *cbuf= dupalloc_compbuf(in[0]->data); CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA); /* convert the RGB stackbuf to an YUV representation */ composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepyuva, CB_RGBA); /* separate each of those channels */ if(out[0]->hasoutput) out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R); if(out[1]->hasoutput) out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G); if(out[2]->hasoutput) out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B); if(out[3]->hasoutput) out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A); /*not used anymore */ if(cbuf2!=cbuf) free_compbuf(cbuf2); free_compbuf(cbuf); } }
static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sock; for (sock= node->outputs.first; sock; sock= sock->next) { if (sock->cache) { #ifdef WITH_COMPOSITOR_LEGACY free_compbuf(sock->cache); #endif sock->cache= NULL; } } }
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); }
/* Free internal buffers */ static void group_free_internal(bNodeTreeExec *gexec) { bNodeStack *ns; int i; for (i=0, ns=gexec->stack; i < gexec->stacksize; ++i, ++ns) { if (!ns->external && !ns->is_copy) { if (ns->data) { free_compbuf(ns->data); ns->data = NULL; } } } }
static void node_composit_exec_brightcontrast(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { if (out[0]->hasoutput==0) return; if (in[0]->data) { CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); stackbuf= dupalloc_compbuf(cbuf); composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, do_brightnesscontrast, CB_RGBA, CB_VAL, CB_VAL); out[0]->data = stackbuf; if (cbuf != in[0]->data) free_compbuf(cbuf); } }
static void fglow(NodeGlare* ndg, CompBuf* dst, CompBuf* src) { int x, y; float scale, u, v, r, w, d; fRGB fcol; CompBuf *tsrc, *ckrn; unsigned int sz = 1 << ndg->size; const float cs_r = 1.f, cs_g = 1.f, cs_b = 1.f; // temp. src image tsrc = BTP(src, ndg->threshold, 1 << ndg->quality); // make the convolution kernel ckrn = alloc_compbuf(sz, sz, CB_RGBA, 1); scale = 0.25f*sqrtf(sz*sz); for (y=0; y<sz; ++y) { v = 2.f*(y / (float)sz) - 1.f; for (x=0; x<sz; ++x) { u = 2.f*(x / (float)sz) - 1.f; r = (u*u + v*v)*scale; d = -sqrtf(sqrtf(sqrtf(r)))*9.f; fcol[0] = expf(d*cs_r), fcol[1] = expf(d*cs_g), fcol[2] = expf(d*cs_b); // linear window good enough here, visual result counts, not scientific analysis //w = (1.f-fabs(u))*(1.f-fabs(v)); // actually, Hanning window is ok, cos^2 for some reason is slower w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI)); fRGB_mult(fcol, w); qd_setPixel(ckrn, x, y, fcol); } } convolve(tsrc, tsrc, ckrn); free_compbuf(ckrn); mixImages(dst, tsrc, 0.5f + 0.5f*ndg->mix); free_compbuf(tsrc); }
static void node_composit_exec_transform(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { if (in[0]->data) { CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); CompBuf *stackbuf; stackbuf= node_composit_transform(cbuf, in[1]->vec[0], in[2]->vec[0], in[3]->vec[0], in[4]->vec[0], node->custom1); /* pass on output and free */ out[0]->data= stackbuf; if (cbuf!=in[0]->data) free_compbuf(cbuf); } }
static void node_composit_exec_mapuv(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { if(out[0]->hasoutput==0) return; if(in[0]->data && in[1]->data) { CompBuf *cbuf= in[0]->data; CompBuf *uvbuf= in[1]->data; CompBuf *stackbuf; cbuf= typecheck_compbuf(cbuf, CB_RGBA); uvbuf= typecheck_compbuf(uvbuf, CB_VEC3); stackbuf= alloc_compbuf(uvbuf->x, uvbuf->y, CB_RGBA, 1); /* allocs */; do_mapuv(stackbuf, cbuf, uvbuf, 0.05f*(float)node->custom1); out[0]->data= stackbuf; if(cbuf!=in[0]->data) free_compbuf(cbuf); if(uvbuf!=in[1]->data) free_compbuf(uvbuf); } }
static void node_composit_exec_premulkey(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { if(out[0]->hasoutput==0) return; if(in[0]->data) { CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); stackbuf= dupalloc_compbuf(cbuf); premul_compbuf(stackbuf, node->custom1 == 1); out[0]->data = stackbuf; if(cbuf != in[0]->data) free_compbuf(cbuf); } }
static void update_node(bNodeTree *ntree, bNode *node) { bNodeSocket *sock; for(sock= node->outputs.first; sock; sock= sock->next) { if(sock->cache) { if(sock->type < 7)//Only for Blender Sockets free_compbuf(sock->cache); sock->cache= NULL; } } node->need_exec= 1; /* individual node update call */ if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); }
static void node_composit_exec_distance_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { /* * Loosely based on the Sequencer chroma key plug-in, but enhanced to work in other color spaces and * uses a different difference function (suggested in forums of vfxtalk.com). */ CompBuf *workbuf; CompBuf *inbuf; 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; inbuf=typecheck_compbuf(in[0]->data, CB_RGBA); c=node->storage; workbuf=dupalloc_compbuf(inbuf); /*use the input color*/ c->key[0] = in[1]->vec[0]; c->key[1] = in[1]->vec[1]; c->key[2] = in[1]->vec[2]; /* work in RGB color space */ if (c->channel == 1) { /* note, processor gets a keyvals array passed on as buffer constant */ composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_distance_matte, CB_RGBA); } /* work in YCbCr color space */ else { composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_chroma_distance_matte, CB_RGBA); } out[0]->data=workbuf; if (out[1]->hasoutput) out[1]->data=valbuf_from_rgbabuf(workbuf, CHAN_A); generate_preview(data, node, workbuf); if (inbuf!=in[0]->data) free_compbuf(inbuf); }
/* while executing tree, free buffers from nodes that are not needed anymore */ static void freeExecutableNode(bNodeTreeExec *exec) { /* node outputs can be freed when: * - not a render result or image node * - when node outputs go to nodes all being set NODE_FINISHED */ bNodeTree *ntree = exec->nodetree; bNodeExec *nodeexec; bNode *node; bNodeSocket *sock; int n; /* set exec flag for finished nodes that might need freed */ for (node= ntree->nodes.first; node; node= node->next) { if (node->type!=CMP_NODE_R_LAYERS) if (node->exec & NODE_FINISHED) node->exec |= NODE_FREEBUFS; } /* clear this flag for input links that are not done yet. * Using the exec data for valid dependency sort. */ for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { node = nodeexec->node; if ((node->exec & NODE_FINISHED)==0) { for (sock= node->inputs.first; sock; sock= sock->next) if (sock->link) sock->link->fromnode->exec &= ~NODE_FREEBUFS; } } /* now we can free buffers */ for (node= ntree->nodes.first; node; node= node->next) { if (node->exec & NODE_FREEBUFS) { for (sock= node->outputs.first; sock; sock= sock->next) { bNodeStack *ns= node_get_socket_stack(exec->stack, sock); if (ns && ns->data) { free_compbuf(ns->data); ns->data= NULL; // printf("freed buf node %s\n", node->name); } } } } }
static void node_composit_exec_stabilize2d(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { if (in[0]->data && node->id) { RenderData *rd= data; MovieClip *clip= (MovieClip *)node->id; CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); CompBuf *stackbuf; float loc[2], scale, angle; BKE_tracking_stabilization_data(&clip->tracking, rd->cfra, cbuf->x, cbuf->y, loc, &scale, &angle); stackbuf= node_composit_transform(cbuf, loc[0], loc[1], angle, scale, node->custom1); /* pass on output and free */ out[0]->data= stackbuf; if (cbuf!=in[0]->data) free_compbuf(cbuf); } }
static void node_composit_exec_chroma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf *cbuf; CompBuf *chromabuf; NodeChroma *c; if(in[0]->hasinput==0) return; if(in[0]->data==NULL) return; if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return; cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); chromabuf= dupalloc_compbuf(cbuf); c=node->storage; /*convert rgbbuf to normalized chroma space*/ composit1_pixel_processor(node, chromabuf, cbuf, in[0]->vec, do_rgba_to_ycca_normalized, CB_RGBA); /*convert key to normalized chroma color space */ do_rgba_to_ycca_normalized(node, c->key, in[1]->vec); /*per pixel chroma key*/ composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_chroma_key, CB_RGBA); /*convert back*/ composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_ycca_to_rgba_normalized, CB_RGBA); out[0]->data= chromabuf; if(out[1]->hasoutput) out[1]->data= valbuf_from_rgbabuf(chromabuf, CHAN_A); generate_preview(data, node, chromabuf); if(cbuf!=in[0]->data) free_compbuf(cbuf); };
static void node_composit_exec_luma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf *cbuf; CompBuf *outbuf; if(in[0]->hasinput==0) return; if(in[0]->data==NULL) return; if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return; cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); outbuf=dupalloc_compbuf(cbuf); composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA); composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_luma_matte, CB_RGBA); composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA); generate_preview(data, node, outbuf); out[0]->data=outbuf; if (out[1]->hasoutput) out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); if(cbuf!=in[0]->data) free_compbuf(cbuf); }
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); } }
/* return total of executable nodes, for timecursor */ static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd) { bNodeTree *ntree = exec->nodetree; bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ bNodeExec *nodeexec; bNode *node; bNodeSocket *sock; int n, totnode= 0, group_edit= 0; /* if we are in group edit, viewer nodes get skipped when group has viewer */ for (node= ntree->nodes.first; node; node= node->next) if (node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) if (ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER)) group_edit= 1; /* NB: using the exec data list here to have valid dependency sort */ for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { int a; node = nodeexec->node; node_get_stack(node, exec->stack, nsin, nsout); /* test the outputs */ /* skip value-only nodes (should be in type!) */ if (!node_only_value(node)) { for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { if (nsout[a]->data==NULL && nsout[a]->hasoutput) { node->need_exec= 1; break; } } } /* test the inputs */ for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { /* skip viewer nodes in bg render or group edit */ if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit)) node->need_exec= 0; /* is sock in use? */ else if (sock->link) { bNodeLink *link= sock->link; /* this is the test for a cyclic case */ if (link->fromnode==NULL || link->tonode==NULL); else if (link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { if (link->fromnode->need_exec) { node->need_exec= 1; break; } } else { node->need_exec= 0; printf("Node %s skipped, cyclic dependency\n", node->name); } } } if (node->need_exec) { /* free output buffers */ for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { if (nsout[a]->data) { free_compbuf(nsout[a]->data); nsout[a]->data= NULL; } } totnode++; /* printf("node needs exec %s\n", node->name); */ /* tag for getExecutableNode() */ node->exec= 0; } else { /* tag for getExecutableNode() */ node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED; } } /* last step: set the stack values for only-value nodes */ /* just does all now, compared to a full buffer exec this is nothing */ if (totnode) { for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { node = nodeexec->node; if (node->need_exec==0 && node_only_value(node)) { if (node->typeinfo->execfunc) { node_get_stack(node, exec->stack, nsin, nsout); node->typeinfo->execfunc(thd->rd, node, nsin, nsout); } } } } return totnode; }
static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) { /* image assigned to output */ /* stack order input sockets: image image */ if(in[0]->data==NULL || in[1]->data==NULL) return; if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ Image *ima= (Image *)node->id; RenderData *rd= data; ImBuf *ibuf; CompBuf *cbuf, *buf1, *buf2, *mask; int x, y; float offset; void *lock; buf1= typecheck_compbuf(in[0]->data, CB_RGBA); buf2= typecheck_compbuf(in[1]->data, CB_RGBA); BKE_image_user_calc_frame(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); /* make ibuf, and connect to ima */ ibuf->x= buf1->x; ibuf->y= buf1->y; imb_addrectfloatImBuf(ibuf); ima->ok= IMA_OK_LOADED; /* output buf */ cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0); /* no alloc*/ cbuf->rect= ibuf->rect_float; /* mask buf */ mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1); /* Check which offset mode is selected and limit offset if needed */ if(node->custom2 == 0) { offset = buf1->x / 100.0f * node->custom1; CLAMP(offset, 0, buf1->x); } else { offset = buf1->y / 100.0f * node->custom1; CLAMP(offset, 0, buf1->y); } if(node->custom2 == 0) { for(y=0; y<buf1->y; y++) { float *fac= mask->rect + y*buf1->x; for(x=offset; x>0; x--, fac++) *fac= 1.0f; } } else { for(y=0; y<offset; y++) { float *fac= mask->rect + y*buf1->x; for(x=buf1->x; x>0; x--, fac++) *fac= 1.0f; } } composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL); BKE_image_release_ibuf(ima, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); free_compbuf(mask); if(in[0]->data != buf1) free_compbuf(buf1); if(in[1]->data != buf2) free_compbuf(buf2); } }
static void ghosts(NodeGlare* ndg, CompBuf* dst, CompBuf* src) { // colormodulation and scale factors (cm & scalef) for 16 passes max: 64 int x, y, n, p, np; fRGB c, tc, cm[64]; float sc, isc, u, v, sm, s, t, ofs, scalef[64]; CompBuf *tbuf1, *tbuf2, *gbuf; const float cmo = 1.f - ndg->colmod; const int qt = 1 << ndg->quality; const float s1 = 4.f/(float)qt, s2 = 2.f*s1; gbuf = BTP(src, ndg->threshold, qt); tbuf1 = dupalloc_compbuf(gbuf); IIR_gauss(tbuf1, s1, 0, 3); IIR_gauss(tbuf1, s1, 1, 3); IIR_gauss(tbuf1, s1, 2, 3); tbuf2 = dupalloc_compbuf(tbuf1); IIR_gauss(tbuf2, s2, 0, 3); IIR_gauss(tbuf2, s2, 1, 3); IIR_gauss(tbuf2, s2, 2, 3); if (ndg->iter & 1) ofs = 0.5f; else ofs = 0.f; for (x=0; x<(ndg->iter*4); x++) { y = x & 3; cm[x][0] = cm[x][1] = cm[x][2] = 1; if (y==1) fRGB_rgbmult(cm[x], 1.f, cmo, cmo); if (y==2) fRGB_rgbmult(cm[x], cmo, cmo, 1.f); if (y==3) fRGB_rgbmult(cm[x], cmo, 1.f, cmo); scalef[x] = 2.1f*(1.f-(x+ofs)/(float)(ndg->iter*4)); if (x & 1) scalef[x] = -0.99f/scalef[x]; } sc = 2.13; isc = -0.97; for (y=0; y<gbuf->y; y++) { v = (float)(y+0.5f) / (float)gbuf->y; for (x=0; x<gbuf->x; x++) { u = (float)(x+0.5f) / (float)gbuf->x; s = (u-0.5f)*sc + 0.5f, t = (v-0.5f)*sc + 0.5f; qd_getPixelLerp(tbuf1, s*gbuf->x, t*gbuf->y, c); sm = smoothMask(s, t); fRGB_mult(c, sm); s = (u-0.5f)*isc + 0.5f, t = (v-0.5f)*isc + 0.5f; qd_getPixelLerp(tbuf2, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, tc); sm = smoothMask(s, t); fRGB_madd(c, tc, sm); qd_setPixel(gbuf, x, y, c); } } memset(tbuf1->rect, 0, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float)); for (n=1; n<ndg->iter; n++) { for (y=0; y<gbuf->y; y++) { v = (float)(y+0.5f) / (float)gbuf->y; for (x=0; x<gbuf->x; x++) { u = (float)(x+0.5f) / (float)gbuf->x; tc[0] = tc[1] = tc[2] = 0.f; for (p=0;p<4;p++) { np = (n<<2) + p; s = (u-0.5f)*scalef[np] + 0.5f; t = (v-0.5f)*scalef[np] + 0.5f; qd_getPixelLerp(gbuf, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, c); fRGB_colormult(c, cm[np]); sm = smoothMask(s, t)*0.25f; fRGB_madd(tc, c, sm); } p = (x + y*tbuf1->x)*tbuf1->type; tbuf1->rect[p] += tc[0]; tbuf1->rect[p+1] += tc[1]; tbuf1->rect[p+2] += tc[2]; } } memcpy(gbuf->rect, tbuf1->rect, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float)); } free_compbuf(tbuf1); free_compbuf(tbuf2); mixImages(dst, gbuf, 0.5f + 0.5f*ndg->mix); free_compbuf(gbuf); }
static void star4(NodeGlare* ndg, CompBuf* dst, CompBuf* src) { int x, y, i, xm, xp, ym, yp; float c[4] = {0,0,0,0}, tc[4] = {0,0,0,0}; CompBuf *tbuf1, *tbuf2, *tsrc; const float f1 = 1.f - ndg->fade, f2 = (1.f - f1)*0.5f; //const float t3 = ndg->threshold*3.f; const float sc = (float)(1 << ndg->quality); const float isc = 1.f/sc; tsrc = BTP(src, ndg->threshold, (int)sc); tbuf1 = dupalloc_compbuf(tsrc); tbuf2 = dupalloc_compbuf(tsrc); for (i=0; i<ndg->iter; i++) { // (x || x-1, y-1) to (x || x+1, y+1) // F for (y=0; y<tbuf1->y; y++) { ym = y - i; yp = y + i; for (x=0; x<tbuf1->x; x++) { xm = x - i; xp = x + i; qd_getPixel(tbuf1, x, y, c); fRGB_mult(c, f1); qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc); fRGB_madd(c, tc, f2); qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc); fRGB_madd(c, tc, f2); qd_setPixel(tbuf1, x, y, c); } } // B for (y=tbuf1->y-1; y>=0; y--) { ym = y - i; yp = y + i; for (x=tbuf1->x-1; x>=0; x--) { xm = x - i; xp = x + i; qd_getPixel(tbuf1, x, y, c); fRGB_mult(c, f1); qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc); fRGB_madd(c, tc, f2); qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc); fRGB_madd(c, tc, f2); qd_setPixel(tbuf1, x, y, c); } } // (x-1, y || y+1) to (x+1, y || y-1) // F for (y=0; y<tbuf2->y; y++) { ym = y - i; yp = y + i; for (x=0; x<tbuf2->x; x++) { xm = x - i; xp = x + i; qd_getPixel(tbuf2, x, y, c); fRGB_mult(c, f1); qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc); fRGB_madd(c, tc, f2); qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc); fRGB_madd(c, tc, f2); qd_setPixel(tbuf2, x, y, c); } } // B for (y=tbuf2->y-1; y>=0; y--) { ym = y - i; yp = y + i; for (x=tbuf2->x-1; x>=0; x--) { xm = x - i; xp = x + i; qd_getPixel(tbuf2, x, y, c); fRGB_mult(c, f1); qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc); fRGB_madd(c, tc, f2); qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc); fRGB_madd(c, tc, f2); qd_setPixel(tbuf2, x, y, c); } } } for (y=0; y<tbuf1->y; ++y) for (x=0; x<tbuf1->x; ++x) { unsigned int p = (x + y*tbuf1->x)*tbuf1->type; tbuf1->rect[p] += tbuf2->rect[p]; tbuf1->rect[p+1] += tbuf2->rect[p+1]; tbuf1->rect[p+2] += tbuf2->rect[p+2]; } for (y=0; y<dst->y; ++y) { const float m = 0.5f + 0.5f*ndg->mix; for (x=0; x<dst->x; ++x) { unsigned int p = (x + y*dst->x)*dst->type; qd_getPixelLerp(tbuf1, x*isc, y*isc, tc); dst->rect[p] = src->rect[p] + m*(tc[0] - src->rect[p]); dst->rect[p+1] = src->rect[p+1] + m*(tc[1] - src->rect[p+1]); dst->rect[p+2] = src->rect[p+2] + m*(tc[2] - src->rect[p+2]); } } free_compbuf(tbuf1); free_compbuf(tbuf2); free_compbuf(tsrc); }