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 fill_bins(bNode *node, CompBuf* in, int* bins) { float value[4]; int ivalue=0; int x, y; /*fill bins */ for (y=0; y<in->y; y++) { for (x=0; x<in->x; x++) { /* get the pixel */ qd_getPixel(in, x, y, value); if (value[3] > 0.0f) { /* don't count transparent pixels */ switch (node->custom1) { case 1: { /* all colors */ value[0] = rgb_to_bw(value); value[0]=value[0]*255; /* scale to 0-255 range */ ivalue=(int)value[0]; break; } case 2: { /* red channel */ value[0]=value[0]*255; /* scale to 0-255 range */ ivalue=(int)value[0]; break; } case 3: { /* green channel */ value[1]=value[1]*255; /* scale to 0-255 range */ ivalue=(int)value[1]; break; } case 4: /*blue channel */ { value[2]=value[2]*255; /* scale to 0-255 range */ ivalue=(int)value[2]; break; } case 5: /* luminence */ { rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]); value[0]=value[0]*255; /* scale to 0-255 range */ ivalue=(int)value[0]; break; } } /*end switch */ /*clip*/ if (ivalue<0) ivalue=0; if (ivalue>255) ivalue=255; /*put in the correct bin*/ bins[ivalue]+=1; } /*end if alpha */ } } }
static float brightness_standard_deviation(bNode* node, CompBuf* in, float mean) { float sum=0.0; int numPixels=0.0; int x,y; float value[4]; for(x=0; x< in->x; x++) { for(y=0; y < in->y; y++) { /* get the pixel */ qd_getPixel(in, x, y, value); if(value[3] > 0.0) { /* don't count transparent pixels */ numPixels++; switch(node->custom1) { case 1: { rgb_tobw(value[0],value[1],value[2], &value[0]); sum+=(value[0]-mean)*(value[0]-mean); break; } case 2: { sum+=value[0]; sum+=(value[0]-mean)*(value[0]-mean); break; } case 3: { sum+=value[1]; sum+=(value[1]-mean)*(value[1]-mean); break; } case 4: { sum+=value[2]; sum+=(value[2]-mean)*(value[2]-mean); break; } case 5: { rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]); sum+=(value[0]-mean)*(value[0]-mean); break; } } } } } return sqrt(sum/(float)(numPixels-1)); }
static float brightness_mean(bNode *node, CompBuf* in) { float sum=0.0; int numPixels=0.0; int x, y; float value[4]; for (x=0; x< in->x; x++) { for (y=0; y < in->y; y++) { /* get the pixel */ qd_getPixel(in, x, y, value); if (value[3] > 0.0f) { /* don't count transparent pixels */ numPixels++; switch (node->custom1) { case 1: { value[0] = rgb_to_bw(value); sum+=value[0]; break; } case 2: { sum+=value[0]; break; } case 3: { sum+=value[1]; break; } case 4: { sum+=value[2]; break; } case 5: { rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]); sum+=value[0]; break; } } } } } return sum/numPixels; }
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 do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf, CompBuf *ybuf, float *xscale, float *yscale) { ImBuf *ibuf; int x, y; float p_dx, p_dy; /* main displacement in pixel space */ float d_dx, d_dy; float dxt, dyt; float u, v; float xs, ys; float vec[3], vecdx[3], vecdy[3]; float col[3]; ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); ibuf->rect_float= cbuf->rect; for(y=0; y < stackbuf->y; y++) { for(x=0; x < stackbuf->x; x++) { /* calc pixel coordinates */ qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec); if (xbuf) qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs); else xs = xscale[0]; if (ybuf) qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys); else ys = yscale[0]; p_dx = vec[0] * xs; p_dy = vec[1] * ys; /* if no displacement, then just copy this pixel */ if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) { qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col); qd_setPixel(stackbuf, x, y, col); continue; } /* displaced pixel in uv coords, for image sampling */ u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x; v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y; /* calc derivatives */ qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx); qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy); d_dx = vecdx[0] * xs; d_dy = vecdy[0] * ys; /* clamp derivatives to minimum displacement distance in UV space */ dxt = p_dx - d_dx; dyt = p_dy - d_dy; dxt = signf(dxt)*maxf(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x; dyt = signf(dyt)*maxf(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y; ibuf_sample(ibuf, u, v, dxt, dyt, col); qd_setPixel(stackbuf, x, y, col); } } IMB_freeImBuf(ibuf); /* simple method for reference, linear interpolation */ /* int x, y; float dx, dy; float u, v; float vec[3]; float col[3]; for(y=0; y < stackbuf->y; y++) { for(x=0; x < stackbuf->x; x++) { qd_getPixel(vecbuf, x, y, vec); dx = vec[0] * (xscale[0]); dy = vec[1] * (yscale[0]); u = (x - dx + 0.5f) / (float)stackbuf->x; v = (y - dy + 0.5f) / (float)stackbuf->y; qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col); qd_setPixel(stackbuf, x, y, col); } } */ }