352 const float *
const input,
358 const float highlights,
363 if(wd <= 1 || ht <= 1)
return 0;
367 int last_level = num_levels-1;
368 if(b && b->mode == 2)
369 last_level = num_levels > 4 ? 4 : num_levels-1;
370 const int max_supp = 1<<last_level;
374 if(b && b->mode == 2)
375 padded[0] =
ll_pad_input(input, wd, ht, max_supp, &w, &h, b);
377 padded[0] =
ll_pad_input(input, wd, ht, max_supp, &w, &h, 0);
378 if(padded[0] == NULL)
385 for(
int l=1;l<=last_level;l++)
388 if(padded[l] == NULL)
397 for(
int l=0;l<=last_level;l++)
400 if(output[l] == NULL)
408 for(
int l=1;l<last_level;l++)
410 gauss_reduce(padded[last_level-1], output[last_level],
dl(w,last_level-1),
dl(h,last_level-1));
419 for(
int k=0;
k<
num_gamma;
k++)
for(
int l=0;l<=last_level;l++)
422 if(buf[
k][l] == NULL)
434 apply_curve(buf[
k][0], padded[0], w, h, max_supp, gamma[
k],
sigma, shadows, highlights, clarity);
437 for(
int l=1;l<=last_level;l++)
444 if(b && b->mode == 2)
446 const float isize = powf(2.0f, last_level) / b->roi->scale;
447 const float psize = isize / b->buf->width * b->wd;
448 const float pl = log2f(psize);
449 const int pl0 = CLAMP((
int)pl, 0, b->num_levels-1), pl1 = CLAMP((
int)(pl+1), 0, b->num_levels-1);
450 const float weight = CLAMP(pl-pl0, 0, 1);
451 const float mul0 = 1.0/powf(2.0f, pl0);
452 const float mul1 = 1.0/powf(2.0f, pl1);
453 const float mul = powf(2.0f, last_level);
454 const int pw =
dl(w,last_level), ph =
dl(h,last_level);
455 const int pw0 =
dl(b->pwd, pl0), ph0 =
dl(b->pht, pl0);
456 const int pw1 =
dl(b->pwd, pl1), ph1 =
dl(b->pht, pl1);
460#pragma omp parallel for collapse(2) default(shared)
462 for(
int j=0;j<ph;j++)
for(
int i=0;
i<pw;
i++)
465 float ix = ((
i*mul - max_supp) + b->roi->x)/b->roi->scale;
466 float iy = ((j*mul - max_supp) + b->roi->y)/b->roi->scale;
468 float px = CLAMP(ix / (
float)b->buf->width * b->wd + (b->pwd-b->wd)/2.0f, 0, b->pwd);
469 float py = CLAMP(iy / (
float)b->buf->height * b->ht + (b->pht-b->ht)/2.0f, 0, b->pht);
471 int px0 = CLAMP(px*mul0, 0, pw0-1);
472 int py0 = CLAMP(py*mul0, 0, ph0-1);
473 int px1 = CLAMP(px*mul1, 0, pw1-1);
474 int py1 = CLAMP(py*mul1, 0, ph1-1);
476 float f0x = CLAMP(px*mul0 - px0, 0.0f, 1.0f);
477 float f0y = CLAMP(py*mul0 - py0, 0.0f, 1.0f);
478 float f1x = CLAMP(px*mul1 - px1, 0.0f, 1.0f);
479 float f1y = CLAMP(py*mul1 - py1, 0.0f, 1.0f);
481 (1.0f-f0x)*(1.0f-f0y)*b->output[pl0][CLAMP(py0 , 0, ph0-1)*pw0 + CLAMP(px0 , 0, pw0-1)]+
482 ( f0x)*(1.0f-f0y)*b->output[pl0][CLAMP(py0 , 0, ph0-1)*pw0 + CLAMP(px0+1, 0, pw0-1)]+
483 (1.0f-f0x)*( f0y)*b->output[pl0][CLAMP(py0+1, 0, ph0-1)*pw0 + CLAMP(px0 , 0, pw0-1)]+
484 ( f0x)*( f0y)*b->output[pl0][CLAMP(py0+1, 0, ph0-1)*pw0 + CLAMP(px0+1, 0, pw0-1)];
486 (1.0f-f1x)*(1.0f-f1y)*b->output[pl1][CLAMP(py1 , 0, ph1-1)*pw1 + CLAMP(px1 , 0, pw1-1)]+
487 ( f1x)*(1.0f-f1y)*b->output[pl1][CLAMP(py1 , 0, ph1-1)*pw1 + CLAMP(px1+1, 0, pw1-1)]+
488 (1.0f-f1x)*( f1y)*b->output[pl1][CLAMP(py1+1, 0, ph1-1)*pw1 + CLAMP(px1 , 0, pw1-1)]+
489 ( f1x)*( f1y)*b->output[pl1][CLAMP(py1+1, 0, ph1-1)*pw1 + CLAMP(px1+1, 0, pw1-1)];
491 float c0 = b->output[pl0][py0*pw0 + px0];
492 float c1 = b->output[pl1][py1*pw1 + px1];
500 for(
int l=last_level-1;l >= 0; l--)
502 const int pw =
dl(w,l), ph =
dl(h,l);
507 for(
int j=0;j<ph;j++)
for(
int i=0;
i<pw;
i++)
509 const float v = padded[l][j*pw+
i];
513 const float a =
CLAMPS((
v - gamma[lo])/(gamma[hi]-gamma[lo]), 0.0f, 1.0f);
514 const float l0 =
ll_laplacian(buf[lo][l+1], buf[lo][l],
i, j, pw, ph);
516 output[l][j*pw+
i] += l0 * (1.0f-a) +
l1 * a;
525 for(
int j=0;j<ht;j++)
for(
int i=0;
i<wd;
i++)
527 out[4*(j*wd+
i)+0] = 100.0f * output[0][(j+max_supp)*w+max_supp+
i];
528 out[4*(j*wd+
i)+1] = input[4*(j*wd+
i)+1];
529 out[4*(j*wd+
i)+2] = input[4*(j*wd+
i)+2];
531 if(b && b->mode == 1)
538 b->num_levels = num_levels;
539 for(
int l=0;l<num_levels;l++) b->output[l] = output[l];
544 const int keep_preview = (b && b->mode == 1 && err == 0);
547 if(!keep_preview || l)