void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out) { dt_iop_lowpass_data_t *data = (dt_iop_lowpass_data_t *)piece->data; float *in = (float *)ivoid; float *out = (float *)ovoid; const int width = roi_in->width; const int height = roi_in->height; const int ch = piece->colors; const int use_bilateral = data->radius < 0 ? 1 : 0; const float radius = fmax(0.1f, fabs(data->radius)); const float sigma = radius * roi_in->scale / piece ->iscale; const int order = data->order; const float Labmax[] = { 100.0f, 128.0f, 128.0f, 1.0f }; const float Labmin[] = { 0.0f, -128.0f, -128.0f, 0.0f }; if(!use_bilateral) { dt_gaussian_t *g = dt_gaussian_init(width, height, ch, Labmax, Labmin, sigma, order); if(!g) return; dt_gaussian_blur_4c(g, in, out); dt_gaussian_free(g); } else { const float sigma_r = 100.0f;// d->sigma_r; // does not depend on scale const float sigma_s = sigma; const float detail = -1.0f; // we want the bilateral base layer dt_bilateral_t *b = dt_bilateral_init(width, height, sigma_s, sigma_r); if(!b) return; dt_bilateral_splat(b, in); dt_bilateral_blur(b); dt_bilateral_slice(b, in, out, detail); dt_bilateral_free(b); } // some aliased pointers for compilers that don't yet understand operators on __m128 const float *const Labminf = (float *)&Labmin; const float *const Labmaxf = (float *)&Labmax; #ifdef _OPENMP #pragma omp parallel for default(none) shared(in,out,data,roi_out) schedule(static) #endif for(int k=0; k<roi_out->width*roi_out->height; k++) { out[k*ch+0] = (out[k*ch+0] < 100.0f) ? data->table[CLAMP((int)(out[k*ch+0]/100.0f*0x10000ul), 0, 0xffff)] : dt_iop_eval_exp(data->unbounded_coeffs, out[k*ch+0]/100.0f); out[k*ch+1] = CLAMPF(out[k*ch+1]*data->saturation, Labminf[1], Labmaxf[1]); out[k*ch+2] = CLAMPF(out[k*ch+2]*data->saturation, Labminf[2], Labmaxf[2]); out[k*ch+3] = in[k*ch+3]; } }
/****************************************************************************** * fogging */ static void tnl_fogging (void) { int i, n; GLfloat d; if (!ctx_fog.fogging) { return; } if (ctx_fog.source == GL_FOG_COORDINATE) { GLfloat4 *fogcoord = tnl_vb.attr[TNL_FOGCOORD].data; const GLuint fogcoord_stride = tnl_vb.attr[TNL_FOGCOORD].stride; n = fogcoord_stride ? tnl_vb.len : 1; switch (ctx_fog.mode) { case GL_LINEAR: if (ctx_fog.start == ctx_fog.end) { d = 1.0F; } else { d = 1.0F / (ctx_fog.end - ctx_fog.start); } for (i = 0; i < n; i++) { const GLfloat z = FABS(fogcoord[0][0]); GLfloat f = (ctx_fog.end - z) * d; tnl_vb.fogcoord[i][0] = CLAMPF(f); fogcoord += fogcoord_stride; } break; case GL_EXP: d = ctx_fog.density; for (i = 0; i < n; i++) { const GLfloat z = FABS(fogcoord[0][0]); tnl_vb.fogcoord[i][0] = CLAMPF(EXP(- d * z)); fogcoord += fogcoord_stride; } break; case GL_EXP2: d = ctx_fog.density * ctx_fog.density; for (i = 0; i < n; i++) { const GLfloat z = FABS(fogcoord[0][0]); tnl_vb.fogcoord[i][0] = CLAMPF(EXP(- d * z * z)); fogcoord += fogcoord_stride; } break; } tnl_vb.attr[TNL_FOGCOORD].data = tnl_vb.fogcoord; } else { /* XXX not implemented */ } }
void glLightModelfv (GLenum pname, const GLfloat *params) { switch (pname) { case GL_LIGHT_MODEL_AMBIENT: sendCommandi(CMD_AMBIENT_COLOR, COLOR3(params)); sendCommandi(CMD_AMBIENT_ALPHA, (int) (255.0 * CLAMPF(params[3]))); break; case GL_LIGHT_MODEL_COLOR_CONTROL: sendCommandi(CMD_LIGHTMODEL, (params[0] == GL_SEPARATE_SPECULAR_COLOR) ? 1 : 0); break; default: GLERROR(GL_INVALID_ENUM); return; } }
void dt_gaussian_blur( dt_gaussian_t *g, float *in, float *out) { const int width = g->width; const int height = g->height; const int ch = g->channels; float a0, a1, a2, a3, b1, b2, coefp, coefn; compute_gauss_params(g->sigma, g->order, &a0, &a1, &a2, &a3, &b1, &b2, &coefp, &coefn); float *temp = g->buf; float *Labmax = g->max; float *Labmin = g->min; // vertical blur column by column #ifdef _OPENMP #pragma omp parallel for default(none) shared(in,out,temp,Labmin,Labmax,a0,a1,a2,a3,b1,b2,coefp,coefn) schedule(static) #endif for(int i=0; i<width; i++) { float xp[ch]; float yb[ch]; float yp[ch]; float xc[ch]; float yc[ch]; float xn[ch]; float xa[ch]; float yn[ch]; float ya[ch]; // forward filter for(int k=0; k<ch; k++) { xp[k] = CLAMPF(in[i*ch+k], Labmin[k], Labmax[k]); yb[k] = xp[k] * coefp; yp[k] = yb[k]; xc[k] = yc[k] = xn[k] = xa[k] = yn[k] = ya[k] = 0.0f; } for(int j=0; j<height; j++) { int offset = (i + j * width)*ch; for(int k=0; k<ch; k++) { xc[k] = CLAMPF(in[offset+k], Labmin[k], Labmax[k]); yc[k] = (a0 * xc[k]) + (a1 * xp[k]) - (b1 * yp[k]) - (b2 * yb[k]); temp[offset+k] = yc[k]; xp[k] = xc[k]; yb[k] = yp[k]; yp[k] = yc[k]; } } // backward filter for(int k=0; k<ch; k++) { xn[k] = CLAMPF(in[((height - 1) * width + i)*ch+k], Labmin[k], Labmax[k]); xa[k] = xn[k]; yn[k] = xn[k] * coefn; ya[k] = yn[k]; } for(int j=height - 1; j > -1; j--) { int offset = (i + j * width)*ch; for(int k=0; k<ch; k++) { xc[k] = CLAMPF(in[offset+k], Labmin[k], Labmax[k]); yc[k] = (a2 * xn[k]) + (a3 * xa[k]) - (b1 * yn[k]) - (b2 * ya[k]); xa[k] = xn[k]; xn[k] = xc[k]; ya[k] = yn[k]; yn[k] = yc[k]; temp[offset+k] += yc[k]; } } } // horizontal blur line by line #ifdef _OPENMP #pragma omp parallel for default(none) shared(out,temp,Labmin,Labmax,a0,a1,a2,a3,b1,b2,coefp,coefn) schedule(static) #endif for(int j=0; j<height; j++) { float xp[ch]; float yb[ch]; float yp[ch]; float xc[ch]; float yc[ch]; float xn[ch]; float xa[ch]; float yn[ch]; float ya[ch]; // forward filter for(int k=0; k<ch; k++) { xp[k] = CLAMPF(temp[j*width*ch+k], Labmin[k], Labmax[k]); yb[k] = xp[k] * coefp; yp[k] = yb[k]; xc[k] = yc[k] = xn[k] = xa[k] = yn[k] = ya[k] = 0.0f; } for(int i=0; i<width; i++) { int offset = (i + j * width)*ch; for(int k=0; k<ch; k++) { xc[k] = CLAMPF(temp[offset+k], Labmin[k], Labmax[k]); yc[k] = (a0 * xc[k]) + (a1 * xp[k]) - (b1 * yp[k]) - (b2 * yb[k]); out[offset+k] = yc[k]; xp[k] = xc[k]; yb[k] = yp[k]; yp[k] = yc[k]; } } // backward filter for(int k=0; k<ch; k++) { xn[k] = CLAMPF(temp[((j + 1)*width - 1)*ch + k], Labmin[k], Labmax[k]); xa[k] = xn[k]; yn[k] = xn[k] * coefn; ya[k] = yn[k]; } for(int i=width - 1; i > -1; i--) { int offset = (i + j * width)*ch; for(int k=0; k<ch; k++) { xc[k] = CLAMPF(temp[offset+k], Labmin[k], Labmax[k]); yc[k] = (a2 * xn[k]) + (a3 * xa[k]) - (b1 * yn[k]) - (b2 * ya[k]); xa[k] = xn[k]; xn[k] = xc[k]; ya[k] = yn[k]; yn[k] = yc[k]; out[offset+k] += yc[k]; } } } }
void dt_gaussian_blur(dt_gaussian_t *g, const float *const in, float *const out) { const int width = g->width; const int height = g->height; const int ch = g->channels; float a0, a1, a2, a3, b1, b2, coefp, coefn; compute_gauss_params(g->sigma, g->order, &a0, &a1, &a2, &a3, &b1, &b2, &coefp, &coefn); float *const temp = g->buf; float *const Labmax = g->max; float *const Labmin = g->min; float *const buf = malloc((size_t)9 * ch * dt_get_num_threads() * sizeof(float)); // vertical blur column by column #ifdef _OPENMP #pragma omp parallel for default(none) shared(a0, a1, a2, a3, b1, b2, coefp, coefn) schedule(static) #endif for(int i = 0; i < width; i++) { const int threadnum = dt_get_thread_num(); float *xp = buf + (size_t)9 * ch * threadnum + 0; float *yb = buf + (size_t)9 * ch * threadnum + 1; float *yp = buf + (size_t)9 * ch * threadnum + 2; float *xc = buf + (size_t)9 * ch * threadnum + 3; float *yc = buf + (size_t)9 * ch * threadnum + 4; float *xn = buf + (size_t)9 * ch * threadnum + 5; float *xa = buf + (size_t)9 * ch * threadnum + 6; float *yn = buf + (size_t)9 * ch * threadnum + 7; float *ya = buf + (size_t)9 * ch * threadnum + 8; // forward filter for(int k = 0; k < ch; k++) { xp[k] = CLAMPF(in[(size_t)i * ch + k], Labmin[k], Labmax[k]); yb[k] = xp[k] * coefp; yp[k] = yb[k]; xc[k] = yc[k] = xn[k] = xa[k] = yn[k] = ya[k] = 0.0f; } for(int j = 0; j < height; j++) { size_t offset = ((size_t)j * width + i) * ch; for(int k = 0; k < ch; k++) { xc[k] = CLAMPF(in[offset + k], Labmin[k], Labmax[k]); yc[k] = (a0 * xc[k]) + (a1 * xp[k]) - (b1 * yp[k]) - (b2 * yb[k]); temp[offset + k] = yc[k]; xp[k] = xc[k]; yb[k] = yp[k]; yp[k] = yc[k]; } } // backward filter for(int k = 0; k < ch; k++) { xn[k] = CLAMPF(in[((size_t)(height - 1) * width + i) * ch + k], Labmin[k], Labmax[k]); xa[k] = xn[k]; yn[k] = xn[k] * coefn; ya[k] = yn[k]; } for(int j = height - 1; j > -1; j--) { size_t offset = ((size_t)j * width + i) * ch; for(int k = 0; k < ch; k++) { xc[k] = CLAMPF(in[offset + k], Labmin[k], Labmax[k]); yc[k] = (a2 * xn[k]) + (a3 * xa[k]) - (b1 * yn[k]) - (b2 * ya[k]); xa[k] = xn[k]; xn[k] = xc[k]; ya[k] = yn[k]; yn[k] = yc[k]; temp[offset + k] += yc[k]; } } } // horizontal blur line by line #ifdef _OPENMP #pragma omp parallel for default(none) shared(a0, a1, a2, a3, b1, b2, coefp, coefn) schedule(static) #endif for(int j = 0; j < height; j++) { const int threadnum = dt_get_thread_num(); float *xp = buf + (size_t)9 * ch * threadnum + 0; float *yb = buf + (size_t)9 * ch * threadnum + 1; float *yp = buf + (size_t)9 * ch * threadnum + 2; float *xc = buf + (size_t)9 * ch * threadnum + 3; float *yc = buf + (size_t)9 * ch * threadnum + 4; float *xn = buf + (size_t)9 * ch * threadnum + 5; float *xa = buf + (size_t)9 * ch * threadnum + 6; float *yn = buf + (size_t)9 * ch * threadnum + 7; float *ya = buf + (size_t)9 * ch * threadnum + 8; // forward filter for(int k = 0; k < ch; k++) { xp[k] = CLAMPF(temp[(size_t)j * width * ch + k], Labmin[k], Labmax[k]); yb[k] = xp[k] * coefp; yp[k] = yb[k]; xc[k] = yc[k] = xn[k] = xa[k] = yn[k] = ya[k] = 0.0f; } for(int i = 0; i < width; i++) { size_t offset = ((size_t)j * width + i) * ch; for(int k = 0; k < ch; k++) { xc[k] = CLAMPF(temp[offset + k], Labmin[k], Labmax[k]); yc[k] = (a0 * xc[k]) + (a1 * xp[k]) - (b1 * yp[k]) - (b2 * yb[k]); out[offset + k] = yc[k]; xp[k] = xc[k]; yb[k] = yp[k]; yp[k] = yc[k]; } } // backward filter for(int k = 0; k < ch; k++) { xn[k] = CLAMPF(temp[((size_t)(j + 1) * width - 1) * ch + k], Labmin[k], Labmax[k]); xa[k] = xn[k]; yn[k] = xn[k] * coefn; ya[k] = yn[k]; } for(int i = width - 1; i > -1; i--) { size_t offset = ((size_t)j * width + i) * ch; for(int k = 0; k < ch; k++) { xc[k] = CLAMPF(temp[offset + k], Labmin[k], Labmax[k]); yc[k] = (a2 * xn[k]) + (a3 * xa[k]) - (b1 * yn[k]) - (b2 * ya[k]); xa[k] = xn[k]; xn[k] = xc[k]; ya[k] = yn[k]; yn[k] = yc[k]; out[offset + k] += yc[k]; } } } free(buf); }