100 const int border = margin + 3;
104 for(
int j = 0; j <
height; j++)
109 memset(sum, 0,
sizeof(
float) * 8);
110 for(
int y = j - 1; y != j + 2; y++)
112 for(
int x =
i - 1;
x !=
i + 2;
x++)
116 const int f =
FC(y,
x, filters);
117 sum[
f] += fmaxf(0.0f, in[(
size_t)y *
width +
x]);
122 const int f =
FC(j,
i, filters);
123 for(
int c = 0; c < 3; c++)
125 if(c !=
f && sum[c + 4] > 0.0f)
126 out[4 * ((size_t)j *
width +
i) + c] = sum[c] / sum[c + 4];
128 out[4 * ((size_t)j *
width +
i) + c] = fmaxf(0.0f, in[(
size_t)j *
width +
i]);
131 out[4 * ((size_t)j *
width +
i) + 3] = 0.0f;
136 const float *input = in;
138 for(
int j = 3; j <
height - 3; j++)
140 float *buf =
out + (size_t)4 *
width * j + 4 * 3;
141 const float *buf_in = input + (size_t)
width * j + 3;
144 if(
i == border && j >= border && j <
height - border)
147 buf =
out + (size_t)4 *
width * j + 4 *
i;
148 buf_in = input + (size_t)
width * j +
i;
152 const int c =
FC(j,
i, filters);
154 const float pc = fmaxf(0.0f, buf_in[0]);
158 const float pym = fmaxf(0.0f, buf_in[-
width * 1]);
159 const float pym2 = fmaxf(0.0f, buf_in[-
width * 2]);
160 const float pym3 = fmaxf(0.0f, buf_in[-
width * 3]);
161 const float pyM = fmaxf(0.0f, buf_in[+
width * 1]);
162 const float pyM2 = fmaxf(0.0f, buf_in[+
width * 2]);
163 const float pyM3 = fmaxf(0.0f, buf_in[+
width * 3]);
164 const float pxm = fmaxf(0.0f, buf_in[-1]);
165 const float pxm2 = fmaxf(0.0f, buf_in[-2]);
166 const float pxm3 = fmaxf(0.0f, buf_in[-3]);
167 const float pxM = fmaxf(0.0f, buf_in[+1]);
168 const float pxM2 = fmaxf(0.0f, buf_in[+2]);
169 const float pxM3 = fmaxf(0.0f, buf_in[+3]);
171 const float guessx = (pxm + pc + pxM) * 2.0f - pxM2 - pxm2;
172 const float diffx = (fabsf(pxm2 - pc) + fabsf(pxM2 - pc) + fabsf(pxm - pxM)) * 3.0f
173 + (fabsf(pxM3 - pxM) + fabsf(pxm3 - pxm)) * 2.0f;
174 const float guessy = (pym + pc + pyM) * 2.0f - pyM2 - pym2;
175 const float diffy = (fabsf(pym2 - pc) + fabsf(pyM2 - pc) + fabsf(pym - pyM)) * 3.0f
176 + (fabsf(pyM3 - pyM) + fabsf(pym3 - pym)) * 2.0f;
180 const float m = fminf(pym, pyM);
181 const float M = fmaxf(pym, pyM);
182 color[1] = fmaxf(fminf(guessy * .25f,
M),
m);
186 const float m = fminf(pxm, pxM);
187 const float M = fmaxf(pxm, pxM);
188 color[1] = fmaxf(fminf(guessx * .25f,
M),
m);
195 memcpy(buf,
color,
sizeof(
float) * 4);
204 for(
int j = 1; j <
height - 1; j++)
206 float *buf =
out + (size_t)4 *
width * j + 4;
209 if(
i == margin && j >= margin && j <
height - margin)
214 const int c =
FC(j,
i, filters);
216 const int linesize = 4 *
width;
219 if(__builtin_expect(c & 1, 1))
223 const float *nt = buf - linesize;
224 const float *nb = buf + linesize;
225 const float *nl = buf - 4;
226 const float *nr = buf + 4;
227 if(
FC(j,
i + 1, filters) == 0)
229 color[2] = (nt[2] + nb[2] + 2.0f *
color[1] - nt[1] - nb[1]) * .5f;
230 color[0] = (nl[0] + nr[0] + 2.0f *
color[1] - nl[1] - nr[1]) * .5f;
235 color[0] = (nt[0] + nb[0] + 2.0f *
color[1] - nt[1] - nb[1]) * .5f;
236 color[2] = (nl[2] + nr[2] + 2.0f *
color[1] - nl[1] - nr[1]) * .5f;
242 const float *ntl = buf - 4 - linesize;
243 const float *ntr = buf + 4 - linesize;
244 const float *nbl = buf - 4 + linesize;
245 const float *nbr = buf + 4 + linesize;
250 const float diff1 = fabsf(ntl[2] - nbr[2]) + fabsf(ntl[1] -
color[1]) + fabsf(nbr[1] -
color[1]);
251 const float guess1 = ntl[2] + nbr[2] + 2.0f *
color[1] - ntl[1] - nbr[1];
252 const float diff2 = fabsf(ntr[2] - nbl[2]) + fabsf(ntr[1] -
color[1]) + fabsf(nbl[1] -
color[1]);
253 const float guess2 = ntr[2] + nbl[2] + 2.0f *
color[1] - ntr[1] - nbl[1];
255 color[2] = guess2 * .5f;
256 else if(diff1 < diff2)
257 color[2] = guess1 * .5f;
259 color[2] = (guess1 + guess2) * .25f;
263 const float diff1 = fabsf(ntl[0] - nbr[0]) + fabsf(ntl[1] -
color[1]) + fabsf(nbr[1] -
color[1]);
264 const float guess1 = ntl[0] + nbr[0] + 2.0f *
color[1] - ntl[1] - nbr[1];
265 const float diff2 = fabsf(ntr[0] - nbl[0]) + fabsf(ntr[1] -
color[1]) + fabsf(nbl[1] -
color[1]);
266 const float guess2 = ntr[0] + nbl[0] + 2.0f *
color[1] - ntr[1] - nbl[1];
268 color[0] = guess2 * .5f;
269 else if(diff1 < diff2)
270 color[0] = guess1 * .5f;
272 color[0] = (guess1 + guess2) * .25f;
275 memcpy(buf,
color,
sizeof(
float) * 4);
283 const dt_iop_roi_t *
const roi_in,
const uint32_t filters)
296 const float scaler = fmaxf(
piece->dsc_in.processed_maximum[0], fmaxf(
piece->dsc_in.processed_maximum[1],
piece->dsc_in.processed_maximum[2]));
297 const float revscaler = 1.0f / scaler;
330 #pragma omp for schedule(simd:dynamic, 6) collapse(2) nowait
332 for(
int tile_vertical = 0; tile_vertical < num_vertical; tile_vertical++)
334 for(
int tile_horizontal = 0; tile_horizontal < num_horizontal; tile_horizontal++)
346 for(
int row = rowStart;
row < rowEnd;
row++)
348 const int c0 =
FC(
row, colStart, filters);
349 const int c1 =
FC(
row, colStart + 1, filters);
350 for(
int col = colStart, indx = (
row - rowStart) *
RCD_TILESIZE, in_indx =
row *
width + colStart; col < colEnd; col++, indx++, in_indx++)
352 cfa[indx] =
rgb[c0][indx] =
rgb[
c1][indx] =
safe_in(in[in_indx], revscaler);
361 for(
int col = 4, indx =
row *
RCD_TILESIZE + col; col < tileCols - 4; col++, indx++ )
363 bufferV[
row - 3][col - 4] = sqf((cfa[indx -
w3] - cfa[indx -
w1] - cfa[indx +
w1] + cfa[indx +
w3]) - 3.0f * (cfa[indx -
w2] + cfa[indx +
w2]) + 6.0f * cfa[indx]);
372 float* V0 = bufferV[0];
373 float* V1 = bufferV[1];
374 float* V2 = bufferV[2];
375 for(
int row = 4;
row < tileRows - 4;
row++ )
377 for(
int col = 3, indx =
row *
RCD_TILESIZE + col; col < tileCols - 3; col++, indx++)
379 bufferH[col - 3] = sqf((cfa[indx - 3] - cfa[indx - 1] - cfa[indx + 1] + cfa[indx + 3]) - 3.0f * (cfa[indx - 2] + cfa[indx + 2]) + 6.0f * cfa[indx]);
381 for(
int col = 4, indx = (
row + 1) *
RCD_TILESIZE + col; col < tileCols - 4; col++, indx++)
383 V2[col - 4] = sqf((cfa[indx -
w3] - cfa[indx -
w1] - cfa[indx +
w1] + cfa[indx +
w3]) - 3.0f * (cfa[indx -
w2] + cfa[indx +
w2]) + 6.0f * cfa[indx]);
385 for(
int col = 4, indx =
row *
RCD_TILESIZE + col; col < tileCols - 4; col++, indx++ )
387 const float V_Stat = fmaxf(
epssq, V0[col - 4] + V1[col - 4] + V2[col - 4]);
388 const float H_Stat = fmaxf(
epssq, bufferH[col - 4] + bufferH[col - 3] + bufferH[col - 2]);
389 VH_Dir[indx] = V_Stat / ( V_Stat + H_Stat );
392 float* tmp = V0; V0 = V1; V1 = V2; V2 = tmp;
397 for(
int row = 2;
row < tileRows - 2;
row++)
399 for(
int col = 2 + (
FC(
row, 0, filters) & 1), indx =
row *
RCD_TILESIZE + col, lp_indx = indx / 2; col < tileCols - 2; col += 2, indx +=2, lp_indx++)
401 lpf[lp_indx] = cfa[indx]
402 + 0.5f * (cfa[indx -
w1] + cfa[indx +
w1] + cfa[indx - 1] + cfa[indx + 1])
403 + 0.25f * (cfa[indx -
w1 - 1] + cfa[indx -
w1 + 1] + cfa[indx +
w1 - 1] + cfa[indx +
w1 + 1]);
409 for(
int row = 4;
row < tileRows - 4;
row++)
411 for(
int col = 4 + (
FC(
row, 0, filters) & 1), indx =
row *
RCD_TILESIZE + col, lpindx = indx / 2; col < tileCols - 4; col += 2, indx += 2, lpindx++)
413 const float cfai = cfa[indx];
416 const float N_Grad =
eps + fabs(cfa[indx -
w1] - cfa[indx +
w1]) + fabs(cfai - cfa[indx -
w2]) + fabs(cfa[indx -
w1] - cfa[indx -
w3]) + fabs(cfa[indx -
w2] - cfa[indx -
w4]);
417 const float S_Grad =
eps + fabs(cfa[indx -
w1] - cfa[indx +
w1]) + fabs(cfai - cfa[indx +
w2]) + fabs(cfa[indx +
w1] - cfa[indx +
w3]) + fabs(cfa[indx +
w2] - cfa[indx +
w4]);
418 const float W_Grad =
eps + fabs(cfa[indx - 1] - cfa[indx + 1]) + fabs(cfai - cfa[indx - 2]) + fabs(cfa[indx - 1] - cfa[indx - 3]) + fabs(cfa[indx - 2] - cfa[indx - 4]);
419 const float E_Grad =
eps + fabs(cfa[indx - 1] - cfa[indx + 1]) + fabs(cfai - cfa[indx + 2]) + fabs(cfa[indx + 1] - cfa[indx + 3]) + fabs(cfa[indx + 2] - cfa[indx + 4]);
422 const float lpfi = lpf[lpindx];
423 const float N_Est = cfa[indx -
w1] * (lpfi + lpfi) / (
eps + lpfi + lpf[lpindx -
w1]);
424 const float S_Est = cfa[indx +
w1] * (lpfi + lpfi) / (
eps + lpfi + lpf[lpindx +
w1]);
425 const float W_Est = cfa[indx - 1] * (lpfi + lpfi) / (
eps + lpfi + lpf[lpindx - 1]);
426 const float E_Est = cfa[indx + 1] * (lpfi + lpfi) / (
eps + lpfi + lpf[lpindx + 1]);
429 const float V_Est = (S_Grad * N_Est + N_Grad * S_Est) / (N_Grad + S_Grad);
430 const float H_Est = (W_Grad * E_Est + E_Grad * W_Est) / (E_Grad + W_Grad);
434 const float VH_Central_Value = VH_Dir[indx];
435 const float VH_Neighbourhood_Value = 0.25f * (VH_Dir[indx -
w1 - 1] + VH_Dir[indx -
w1 + 1] + VH_Dir[indx +
w1 - 1] + VH_Dir[indx +
w1 + 1]);
436 const float VH_Disc = (fabs(0.5f - VH_Central_Value) < fabs(0.5f - VH_Neighbourhood_Value)) ? VH_Neighbourhood_Value : VH_Central_Value;
438 rgb[1][indx] =
intp(VH_Disc, H_Est, V_Est);
445 for(
int row = 3;
row < tileRows - 3;
row++)
447 for(
int col = 3, indx =
row *
RCD_TILESIZE + col, indx2 = indx / 2; col < tileCols - 3; col+=2, indx+=2, indx2++)
449 P_CDiff_Hpf[indx2] = sqf((cfa[indx -
w3 - 3] - cfa[indx -
w1 - 1] - cfa[indx +
w1 + 1] + cfa[indx +
w3 + 3]) - 3.0f * (cfa[indx -
w2 - 2] + cfa[indx +
w2 + 2]) + 6.0f * cfa[indx]);
450 Q_CDiff_Hpf[indx2] = sqf((cfa[indx -
w3 + 3] - cfa[indx -
w1 + 1] - cfa[indx +
w1 - 1] + cfa[indx +
w3 - 3]) - 3.0f * (cfa[indx -
w2 + 2] + cfa[indx +
w2 - 2]) + 6.0f * cfa[indx]);
454 for(
int row = 4;
row < tileRows - 4;
row++)
456 for(
int col = 4 + (
FC(
row, 0, filters) & 1), indx =
row *
RCD_TILESIZE + col, indx2 = indx / 2, indx3 = (indx -
w1 - 1) / 2, indx4 = (indx +
w1 - 1) / 2; col < tileCols - 4; col += 2, indx += 2, indx2++, indx3++, indx4++ )
458 const float P_Stat = fmaxf(
epssq, P_CDiff_Hpf[indx3] + P_CDiff_Hpf[indx2] + P_CDiff_Hpf[indx4 + 1]);
459 const float Q_Stat = fmaxf(
epssq, Q_CDiff_Hpf[indx3 + 1] + Q_CDiff_Hpf[indx2] + Q_CDiff_Hpf[indx4]);
460 PQ_Dir[indx2] = P_Stat / (P_Stat + Q_Stat);
465 for(
int row = 4;
row < tileRows - 4;
row++)
467 for(
int col = 4 + (
FC(
row, 0, filters) & 1), indx =
row *
RCD_TILESIZE + col, c = 2 -
FC(
row, col, filters), pqindx = indx / 2, pqindx2 = (indx -
w1 - 1) / 2, pqindx3 = (indx +
w1 - 1) / 2; col < tileCols - 4; col += 2, indx += 2, pqindx++, pqindx2++, pqindx3++)
470 const float PQ_Central_Value = PQ_Dir[pqindx];
471 const float PQ_Neighbourhood_Value = 0.25f * (PQ_Dir[pqindx2] + PQ_Dir[pqindx2 + 1] + PQ_Dir[pqindx3] + PQ_Dir[pqindx3 + 1]);
473 const float PQ_Disc = (fabs(0.5f - PQ_Central_Value) < fabs(0.5f - PQ_Neighbourhood_Value)) ? PQ_Neighbourhood_Value : PQ_Central_Value;
476 const float NW_Grad =
eps + fabs(
rgb[c][indx -
w1 - 1] -
rgb[c][indx +
w1 + 1]) + fabs(
rgb[c][indx -
w1 - 1] -
rgb[c][indx -
w3 - 3]) + fabs(
rgb[1][indx] -
rgb[1][indx -
w2 - 2]);
477 const float NE_Grad =
eps + fabs(
rgb[c][indx -
w1 + 1] -
rgb[c][indx +
w1 - 1]) + fabs(
rgb[c][indx -
w1 + 1] -
rgb[c][indx -
w3 + 3]) + fabs(
rgb[1][indx] -
rgb[1][indx -
w2 + 2]);
478 const float SW_Grad =
eps + fabs(
rgb[c][indx -
w1 + 1] -
rgb[c][indx +
w1 - 1]) + fabs(
rgb[c][indx +
w1 - 1] -
rgb[c][indx +
w3 - 3]) + fabs(
rgb[1][indx] -
rgb[1][indx +
w2 - 2]);
479 const float SE_Grad =
eps + fabs(
rgb[c][indx -
w1 - 1] -
rgb[c][indx +
w1 + 1]) + fabs(
rgb[c][indx +
w1 + 1] -
rgb[c][indx +
w3 + 3]) + fabs(
rgb[1][indx] -
rgb[1][indx +
w2 + 2]);
482 const float NW_Est =
rgb[c][indx -
w1 - 1] -
rgb[1][indx -
w1 - 1];
483 const float NE_Est =
rgb[c][indx -
w1 + 1] -
rgb[1][indx -
w1 + 1];
484 const float SW_Est =
rgb[c][indx +
w1 - 1] -
rgb[1][indx +
w1 - 1];
485 const float SE_Est =
rgb[c][indx +
w1 + 1] -
rgb[1][indx +
w1 + 1];
488 const float P_Est = (NW_Grad * SE_Est + SE_Grad * NW_Est) / (NW_Grad + SE_Grad);
489 const float Q_Est = (NE_Grad * SW_Est + SW_Grad * NE_Est) / (NE_Grad + SW_Grad);
492 rgb[c][indx] =
rgb[1][indx] +
intp(PQ_Disc, Q_Est, P_Est);
497 for(
int row = 4;
row < tileRows - 4;
row++)
499 for(
int col = 4 + (
FC(
row, 1, filters) & 1), indx =
row *
RCD_TILESIZE + col; col < tileCols - 4; col += 2, indx +=2)
502 const float VH_Central_Value = VH_Dir[indx];
503 const float VH_Neighbourhood_Value = 0.25f * (VH_Dir[indx -
w1 - 1] + VH_Dir[indx -
w1 + 1] + VH_Dir[indx +
w1 - 1] + VH_Dir[indx +
w1 + 1]);
504 const float VH_Disc = (fabs(0.5f - VH_Central_Value) < fabs(0.5f - VH_Neighbourhood_Value) ) ? VH_Neighbourhood_Value : VH_Central_Value;
505 const float rgb1 =
rgb[1][indx];
506 const float N1 =
eps + fabs(rgb1 -
rgb[1][indx -
w2]);
507 const float S1 =
eps + fabs(rgb1 -
rgb[1][indx +
w2]);
508 const float W1 =
eps + fabs(rgb1 -
rgb[1][indx - 2]);
509 const float E1 =
eps + fabs(rgb1 -
rgb[1][indx + 2]);
511 const float rgb1mw1 =
rgb[1][indx -
w1];
512 const float rgb1pw1 =
rgb[1][indx +
w1];
513 const float rgb1m1 =
rgb[1][indx - 1];
514 const float rgb1p1 =
rgb[1][indx + 1];
516 for(
int c = 0; c <= 2; c += 2)
518 const float SNabs = fabs(
rgb[c][indx -
w1] -
rgb[c][indx +
w1]);
519 const float EWabs = fabs(
rgb[c][indx - 1] -
rgb[c][indx + 1]);
522 const float N_Grad = N1 + SNabs + fabs(
rgb[c][indx -
w1] -
rgb[c][indx -
w3]);
523 const float S_Grad = S1 + SNabs + fabs(
rgb[c][indx +
w1] -
rgb[c][indx +
w3]);
524 const float W_Grad = W1 + EWabs + fabs(
rgb[c][indx - 1] -
rgb[c][indx - 3]);
525 const float E_Grad = E1 + EWabs + fabs(
rgb[c][indx + 1] -
rgb[c][indx + 3]);
528 const float N_Est =
rgb[c][indx -
w1] - rgb1mw1;
529 const float S_Est =
rgb[c][indx +
w1] - rgb1pw1;
530 const float W_Est =
rgb[c][indx - 1] - rgb1m1;
531 const float E_Est =
rgb[c][indx + 1] - rgb1p1;
534 const float V_Est = (N_Grad * S_Est + S_Grad * N_Est) / (N_Grad + S_Grad);
535 const float H_Est = (E_Grad * W_Est + W_Grad * E_Est) / (E_Grad + W_Grad);
538 rgb[c][indx] = rgb1 +
intp(VH_Disc, H_Est, V_Est);
544 const int first_vertical = rowStart +
RCD_BORDER;
545 const int last_vertical = rowEnd -
RCD_BORDER;
546 const int first_horizontal = colStart +
RCD_BORDER;
547 const int last_horizontal = colEnd -
RCD_BORDER;
548 for(
int row = first_vertical;
row < last_vertical;
row++)
550 for(
int col = first_horizontal, idx = (
row - rowStart) *
RCD_TILESIZE + col - colStart, o_idx = (
row *
width + col) * 4; col < last_horizontal; col++, o_idx += 4, idx++)
552 out[o_idx] = scaler * fmaxf(0.0f,
rgb[0][idx]);
553 out[o_idx+1] = scaler * fmaxf(0.0f,
rgb[1][idx]);
554 out[o_idx+2] = scaler * fmaxf(0.0f,
rgb[2][idx]);
574 const gboolean smooth)
581 cl_mem dev_aux = NULL;
582 cl_mem dev_tmp = NULL;
583 cl_mem dev_green_eq = NULL;
588 cl_mem VH_dir = NULL;
589 cl_mem PQ_dir = NULL;
590 cl_mem VP_diff = NULL;
591 cl_mem HQ_diff = NULL;
608 dev_in = dev_green_eq;
618 const int myborder = 3;
627 if(err != CL_SUCCESS)
goto error;
633 .cellsize =
sizeof(float) * 1, .overhead = 0,
634 .sizex = 64, .sizey = 64 };
637 const int myborder = 32;
639 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
648 if(err != CL_SUCCESS)
goto error;
654 .cellsize = 4 *
sizeof(float), .overhead = 0,
655 .sizex = 64, .sizey = 64 };
658 const int myborder = 16;
660 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
669 if(err != CL_SUCCESS)
goto error;
694 const float scaler = 1.0f / fmaxf(
piece->dsc_in.processed_maximum[0], fmaxf(
piece->dsc_in.processed_maximum[1],
piece->dsc_in.processed_maximum[2]));
705 if(err != CL_SUCCESS)
goto error;
713 .cellsize =
sizeof(float), .overhead = 0,
714 .sizex = 64, .sizey = 64 };
718 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
724 sizeof(
float) * (locopt.
sizex + 8) * (locopt.
sizey + 8), NULL);
726 if(err != CL_SUCCESS)
goto error;
739 if(err != CL_SUCCESS)
goto error;
752 if(err != CL_SUCCESS)
goto error;
766 if(err != CL_SUCCESS)
goto error;
775 if(err != CL_SUCCESS)
goto error;
785 if(err != CL_SUCCESS)
goto error;
795 if(err != CL_SUCCESS)
goto error;
797 const float scaler = fmaxf(
piece->dsc_in.processed_maximum[0], fmaxf(
piece->dsc_in.processed_maximum[1],
piece->dsc_in.processed_maximum[2]));
813 if(err != CL_SUCCESS)
goto error;
825 dev_green_eq = cfa = rgb0 = rgb1 = rgb2 = VH_dir = PQ_dir = VP_diff = HQ_diff = NULL;
851 dev_aux = dev_green_eq = dev_tmp = cfa = rgb0 = rgb1 = rgb2 = VH_dir = PQ_dir = VP_diff = HQ_diff = NULL;