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_cvAnd(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CvArr* dst; CvArr* src1; CvArr* src2; CvArr* mask=NULL; CompBuf* dst_buf; if(out[0]->hasoutput==0) return; if((in[0]->data)){ //Inputs src1 = BOCV_IplImage_attach(in[0]->data); mask = BOCV_Mask_attach(in[2]->data); //Output dst_buf=dupalloc_compbuf(in[0]->data); dst=BOCV_IplImage_attach(dst_buf); //Check Image - Mask sizes if(mask){ if (!BOCV_checkMask(src1, mask)){ node->error= 1; return; } } if(in[1]->data){ src2 = BOCV_IplImage_attach(in[1]->data); //Checks //Check Image Sizes if(!BOCV_checkAreSameType(src1, src2)){ node->error= 1; return; } //Check Image number Channels if(!BOCV_checkSameNChannels(src1, src2)){ node->error= 1; return; } cvAnd(src1, src2, dst, mask); BOCV_IplImage_detach(src2); }else{ CvScalar s; s.val[0]= (in[1]->vec[0]); s.val[1]= (in[1]->vec[1]); s.val[2]= (in[1]->vec[2]); s.val[3]= 0; cvAndS(src1, s, dst, mask); } out[0]->data= dst_buf; BOCV_IplImage_detach(src1); BOCV_IplImage_detach(mask); BOCV_IplImage_detach(dst); } }
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); }
/* 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 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); }
static void node_composit_exec_cvSub(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CvArr* dst; CvArr* src1; CvArr* src2; CvArr* mask = NULL; CompBuf *dst_buf; if (out[0]->hasoutput == 0) return; if ((in[0]->data)) { src1 = BOCV_IplImage_attach(in[0]->data); if (in[2]->data) { mask = BOCV_Mask_attach(in[2]->data); if (!BOCV_checkMask(src1, mask)) { node->error = 1; return; } } //Create output dst_buf = dupalloc_compbuf(in[0]->data); dst = BOCV_IplImage_attach(dst_buf); //If there are second input if (in[1]->data) { src2 = BOCV_IplImage_attach(in[1]->data); if (!BOCV_checkAreSameType(src1, src2)) { node->error = 1; return; } if (!BOCV_checkSameNChannels(src1, src2)) { node->error = 1; return; } cvSub(src1, src2, dst, mask); BOCV_IplImage_detach(src2); } else { CvScalar s; s.val[0] = (in[1]->vec[0]); s.val[1] = (in[1]->vec[1]); s.val[2] = (in[1]->vec[2]); s.val[3] = 0; cvSubS(src1, s, dst, mask); } out[0]->data = dst_buf; BOCV_IplImage_detach(src1); BOCV_IplImage_detach(dst); } }
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 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 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); }
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 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_cvDiv(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CvArr* dst; CvArr* src1; CvArr* src2; CompBuf *dst_buf; if (out[0]->hasoutput == 0) return; if ((in[0]->data) && in[1]->data) { //Get inuts src1 = BOCV_IplImage_attach(in[0]->data); src2 = BOCV_IplImage_attach(in[1]->data); //Create output dst_buf = dupalloc_compbuf(in[0]->data); dst = BOCV_IplImage_attach(dst_buf); //Check for inputs if (!BOCV_checkAreSameType(src1, src2)) { node->error = 1; return; } if (!BOCV_checkSameNChannels(src1, src2)) { node->error = 1; return; } cvDiv(src1, src2, dst, in[2]->vec[0]); //Output out[0]->data = dst_buf; //Release memory BOCV_IplImage_detach(src1); BOCV_IplImage_detach(src2); BOCV_IplImage_detach(dst); } }
static void node_composit_exec_cvErode(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { int iterations; IplImage *src, *dst; CompBuf *dst_buf; if(in[0]->hasinput==0) return; if(out[0]->hasoutput==0) return; src= BOCV_IplImage_attach(in[0]->data); dst_buf = dupalloc_compbuf(in[0]->data); iterations=(int)in[1]->vec[0]; dst = BOCV_IplImage_attach(dst_buf); cvErode(src,dst,0,iterations); out[0]->data = dst_buf; BOCV_IplImage_detach(src); BOCV_IplImage_detach(dst); }
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_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_sepycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* input no image? then only color operation */ if(in[0]->data==NULL) { float y, cb, cr; switch(node->custom1) { case 1: rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT709); break; case 2: rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255); break; case 0: default: rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT601); break; } /*divided by 255 to normalize for viewing in */ out[0]->vec[0] = y/255.0; out[1]->vec[0] = cb/255.0; out[2]->vec[0] = cr/255.0; 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 buffer doesn't get corrupted */ CompBuf *cbuf= dupalloc_compbuf(in[0]->data); CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA); /* convert the RGB stackbuf to an HSV representation */ switch(node->custom1) { case 1: composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_709, CB_RGBA); break; case 2: composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_jfif, CB_RGBA); break; case 0: default: composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_601, CB_RGBA); break; } /* 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 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); }
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_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; } }
static void lensDistort(CompBuf* dst, CompBuf* src, float kr, float kg, float kb, int jit, int proj, int fit) { int x, y, z; const float cx = 0.5f*(float)dst->x, cy = 0.5f*(float)dst->y; if (proj) { // shift CompBuf* tsrc = dupalloc_compbuf(src); for (z=0; z<tsrc->type; ++z) IIR_gauss(tsrc, (kr+0.5f)*(kr+0.5f), z, 1); kr *= 20.f; for (y=0; y<dst->y; y++) { fRGB* colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; const float v = (y + 0.5f)/(float)dst->y; for (x=0; x<dst->x; x++) { const float u = (x + 0.5f)/(float)dst->x; qd_getPixelLerpChan(tsrc, (u*dst->x + kr) - 0.5f, v*dst->y - 0.5f, 0, colp[x]); if (tsrc->type == CB_VAL) colp[x][1] = tsrc->rect[x + y*tsrc->x]; else colp[x][1] = tsrc->rect[(x + y*tsrc->x)*tsrc->type + 1]; qd_getPixelLerpChan(tsrc, (u*dst->x - kr) - 0.5f, v*dst->y - 0.5f, 2, colp[x]+2); } } free_compbuf(tsrc); } else { // Spherical // Scale factor to make bottom/top & right/left sides fit in window after deform // so in the case of pincushion (kn < 0), corners will be outside window. // Now also optionally scales image such that black areas are not visible when distort factor is positive // (makes distorted corners match window corners, but really only valid if mk<=0.5) const float mk = MAX3(kr, kg, kb); const float sc = (fit && (mk > 0.f)) ? (1.f/(1.f + 2.f*mk)) : (1.f/(1.f + mk)); const float drg = 4.f*(kg - kr), dgb = 4.f*(kb - kg); kr *= 4.f, kg *= 4.f, kb *= 4.f; for (y=0; y<dst->y; y++) { fRGB* colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; const float v = sc*((y + 0.5f) - cy)/cy; for (x=0; x<dst->x; x++) { int dr = 0, dg = 0, db = 0; float d, t, ln[6] = {0, 0, 0, 0, 0, 0}; fRGB c1, tc = {0, 0, 0, 0}; const float u = sc*((x + 0.5f) - cx)/cx; int sta = 0, mid = 0, end = 0; if ((t = 1.f - kr*(u*u + v*v)) >= 0.f) { d = 1.f/(1.f + sqrtf(t)); ln[0] = (u*d + 0.5f)*dst->x - 0.5f, ln[1] = (v*d + 0.5f)*dst->y - 0.5f; sta = 1; } if ((t = 1.f - kg*(u*u + v*v)) >= 0.f) { d = 1.f/(1.f + sqrtf(t)); ln[2] = (u*d + 0.5f)*dst->x - 0.5f, ln[3] = (v*d + 0.5f)*dst->y - 0.5f; mid = 1; } if ((t = 1.f - kb*(u*u + v*v)) >= 0.f) { d = 1.f/(1.f + sqrtf(t)); ln[4] = (u*d + 0.5f)*dst->x - 0.5f, ln[5] = (v*d + 0.5f)*dst->y - 0.5f; end = 1; } if (sta && mid && end) { // RG const int dx = ln[2] - ln[0], dy = ln[3] - ln[1]; const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); const float sd = 1.f/(float)ds; for (z=0; z<ds; ++z) { const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; t = 1.f - (kr + tz*drg)*(u*u + v*v); d = 1.f / (1.f + sqrtf(t)); qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; tc[0] += (1.f-tz)*c1[0], tc[1] += tz*c1[1]; dr++, dg++; } // GB { const int dx = ln[4] - ln[2], dy = ln[5] - ln[3]; const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); const float sd = 1.f/(float)ds; for (z=0; z<ds; ++z) { const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; t = 1.f - (kg + tz*dgb)*(u*u + v*v); d = 1.f / (1.f + sqrtf(t)); qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; tc[1] += (1.f-tz)*c1[1], tc[2] += tz*c1[2]; dg++, db++; } } } if (dr) colp[x][0] = 2.f*tc[0] / (float)dr; if (dg) colp[x][1] = 2.f*tc[1] / (float)dg; if (db) colp[x][2] = 2.f*tc[2] / (float)db; } } } }