diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 8774ce9f0..936c3bd16 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -22,7 +22,6 @@ #include "rawimagesource.h" #include "rawimagesource_i.h" #include "jaggedarray.h" -#include "median.h" #include "rawimage.h" #include "mytime.h" #include "iccmatrices.h" diff --git a/rtengine/median.h b/rtengine/median.h index c2c969492..d5e88d9de 100644 --- a/rtengine/median.h +++ b/rtengine/median.h @@ -18,17 +18,8 @@ */ #include "rt_math.h" -#define SORT3(a1,a2,a3,b1,b2,b3) \ - { \ - b2 = min(a1,a2);\ - b1 = min(b2,a3);\ - b3 = max(a1,a2);\ - b2 = max(b2, min(b3,a3));\ - b3 = max(b3,a3);\ - } - - -#define NETWORKSORT4OF6(s0,s1,s2,s3,s4,s5,d0,d1,d2,d3,d4,d5,temp) \ +// middle 4 of 6 elements, +#define MIDDLE4OF6(s0,s1,s2,s3,s4,s5,d0,d1,d2,d3,d4,d5,temp) \ {\ d1 = min(s1,s2);\ d2 = max(s1,s2);\ @@ -39,28 +30,35 @@ d1 = max(d0,d1);\ d0 = temp;\ d4 = min(s4,s5);\ d5 = max(s4,s5);\ -temp = min(s3,d5);\ +d3 = min(s3,d5);\ d5 = max(s3,d5);\ -d3 = temp;\ temp = min(d3,d4);\ d4 = max(d3,d4);\ -d3 = temp;\ -d3 = max(d0,d3);\ -temp = min(d1,d4);\ -d4 = max(d1,d4);\ -d1 = temp;\ +d3 = max(d0,temp);\ d2 = min(d2,d5);\ -temp = min(d2,d4);\ -d4 = max(d2,d4);\ -d2 = temp;\ -temp = min(d1,d3);\ -d3 = max(d1,d3);\ -d1 = temp;\ -temp = min(d2,d3);\ -d3 = max(d2,d3);\ -d2 = temp;\ } +// middle 4 of 6 elements, vectorized +#define VMIDDLE4OF6(s0,s1,s2,s3,s4,s5,d0,d1,d2,d3,d4,d5,temp) \ +{\ +d1 = vminf(s1,s2);\ +d2 = vmaxf(s1,s2);\ +d0 = vminf(s0,d2);\ +d2 = vmaxf(s0,d2);\ +temp = vminf(d0,d1);\ +d1 = vmaxf(d0,d1);\ +d0 = temp;\ +d4 = vminf(s4,s5);\ +d5 = vmaxf(s4,s5);\ +d3 = vminf(s3,d5);\ +d5 = vmaxf(s3,d5);\ +temp = vminf(d3,d4);\ +d4 = vmaxf(d3,d4);\ +d3 = vmaxf(d0,temp);\ +d2 = vminf(d2,d5);\ +} + + #define MEDIAN7(s0,s1,s2,s3,s4,s5,s6,t0,t1,t2,t3,t4,t5,t6,median) \ {\ t0 = min(s0,s5);\ @@ -77,13 +75,36 @@ t5 = max(t3,t5);\ t3 = median;\ median = min(t2,t6);\ t6 = max(t2,t6);\ -t2 = median;\ -t3 = max(t2,t3);\ +t3 = max(median,t3);\ t3 = min(t3,t6);\ t4 = min(t4,t5);\ median = min(t1,t4);\ t4 = max(t1,t4);\ -t1 = median;\ -t3 = max(t1,t3);\ +t3 = max(median,t3);\ median = min(t3,t4);\ } + +#define VMEDIAN7(s0,s1,s2,s3,s4,s5,s6,t0,t1,t2,t3,t4,t5,t6,median) \ +{\ +t0 = vminf(s0,s5);\ +t5 = vmaxf(s0,s5);\ +t3 = vmaxf(t0,s3);\ +t0 = vminf(t0,s3);\ +t1 = vminf(s1,s6);\ +t6 = vmaxf(s1,s6);\ +t2 = vminf(s2,s4);\ +t4 = vmaxf(s2,s4);\ +t1 = vmaxf(t0,t1);\ +median = vminf(t3,t5);\ +t5 = vmaxf(t3,t5);\ +t3 = median;\ +median = vminf(t2,t6);\ +t6 = vmaxf(t2,t6);\ +t3 = vmaxf(median,t3);\ +t3 = vminf(t3,t6);\ +t4 = vminf(t4,t5);\ +median = vminf(t1,t4);\ +t4 = vmaxf(t1,t4);\ +t3 = vmaxf(median,t3);\ +median = vminf(t3,t4);\ +} diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 0125f1e63..29481fa58 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -3387,33 +3387,30 @@ int RawImageSource::defTransform (int tran) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Thread called part -void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, const int row_from, const int row_to) +void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to) { - int W = im->width; + const int W = im->width; + constexpr float onebynine = 1.f / 9.f; - array2D rbconv_Y (W, 3); - array2D rbconv_I (W, 3); - array2D rbconv_Q (W, 3); - array2D rbout_I (W, 3); - array2D rbout_Q (W, 3); +#ifdef __SSE2__ + vfloat buffer[12]; + vfloat* pre1 = &buffer[0]; + vfloat* pre2 = &buffer[3]; + vfloat* post1 = &buffer[6]; + vfloat* post2 = &buffer[9]; - float row_I[W]; - float row_Q[W]; + vfloat middle[6]; - float buffer[3 * 8]; - float* pre1_I = &buffer[0]; - float* pre2_I = &buffer[3]; - float* post1_I = &buffer[6]; - float* post2_I = &buffer[9]; - float* pre1_Q = &buffer[12]; - float* pre2_Q = &buffer[15]; - float* post1_Q = &buffer[18]; - float* post2_Q = &buffer[21]; +#else + float buffer[12]; + float* pre1 = &buffer[0]; + float* pre2 = &buffer[3]; + float* post1 = &buffer[6]; + float* post2 = &buffer[9]; - float middle_I[6]; - float middle_Q[6]; - float* tmp; + float middle[6]; +#endif int px = (row_from - 1) % 3, cx = row_from % 3, nx = 0; @@ -3433,82 +3430,113 @@ void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, const i convert_row_to_YIQ (im->r(i + 1), im->g(i + 1), im->b(i + 1), rbconv_Y[nx], rbconv_I[nx], rbconv_Q[nx], W); - SORT3(rbconv_I[px][0], rbconv_I[cx][0], rbconv_I[nx][0], pre1_I[0], pre1_I[1], pre1_I[2]); - SORT3(rbconv_I[px][1], rbconv_I[cx][1], rbconv_I[nx][1], pre2_I[0], pre2_I[1], pre2_I[2]); - SORT3(rbconv_Q[px][0], rbconv_Q[cx][0], rbconv_Q[nx][0], pre1_Q[0], pre1_Q[1], pre1_Q[2]); - SORT3(rbconv_Q[px][1], rbconv_Q[cx][1], rbconv_Q[nx][1], pre2_Q[0], pre2_Q[1], pre2_Q[2]); +#ifdef __SSE2__ + pre1[0] = _mm_setr_ps(rbconv_I[px][0], rbconv_Q[px][0], 0, 0) , pre1[1] = _mm_setr_ps(rbconv_I[cx][0], rbconv_Q[cx][0], 0, 0), pre1[2] = _mm_setr_ps(rbconv_I[nx][0], rbconv_Q[nx][0], 0, 0); + pre2[0] = _mm_setr_ps(rbconv_I[px][1], rbconv_Q[px][1], 0, 0) , pre2[1] = _mm_setr_ps(rbconv_I[cx][1], rbconv_Q[cx][1], 0, 0), pre2[2] = _mm_setr_ps(rbconv_I[nx][1], rbconv_Q[nx][1], 0, 0); + vfloat temp[7]; + + // fill first element in rbout_I and rbout_Q + rbout_I[cx][0] = rbconv_I[cx][0]; + rbout_Q[cx][0] = rbconv_Q[cx][0]; // median I channel - float temp[7]; - for (int j = 1; j < W - 2; j += 2) { - SORT3(rbconv_I[px][j + 1], rbconv_I[cx][j + 1], rbconv_I[nx][j + 1], post1_I[0], post1_I[1], post1_I[2]); - NETWORKSORT4OF6(pre2_I[0], pre2_I[1], pre2_I[2], post1_I[0], post1_I[1], post1_I[2], middle_I[0], middle_I[1], middle_I[2], middle_I[3], middle_I[4], middle_I[5], temp[0]); - SORT3(rbconv_I[px][j + 2], rbconv_I[cx][j + 2], rbconv_I[nx][j + 2], post2_I[0], post2_I[1], post2_I[2]); - MEDIAN7(pre1_I[0], pre1_I[1], pre1_I[2], middle_I[1], middle_I[2], middle_I[3], middle_I[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_I[cx][j]); - MEDIAN7(post2_I[0], post2_I[1], post2_I[2], middle_I[1], middle_I[2], middle_I[3], middle_I[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_I[cx][j + 1]); - tmp = pre1_I; - pre1_I = post1_I; - post1_I = tmp; - tmp = pre2_I; - pre2_I = post2_I; - post2_I = tmp; - + post1[0] = _mm_setr_ps(rbconv_I[px][j + 1], rbconv_Q[px][j + 1], 0, 0), post1[1] = _mm_setr_ps(rbconv_I[cx][j + 1], rbconv_Q[cx][j + 1], 0, 0), post1[2] = _mm_setr_ps(rbconv_I[nx][j + 1], rbconv_Q[nx][j + 1], 0, 0); + VMIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); + vfloat medianval; + VMEDIAN7(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], medianval); + rbout_I[cx][j] = medianval[0]; + rbout_Q[cx][j] = medianval[1]; + post2[0] = _mm_setr_ps(rbconv_I[px][j + 2], rbconv_Q[px][j + 2], 0, 0), post2[1] = _mm_setr_ps(rbconv_I[cx][j + 2], rbconv_Q[cx][j + 2], 0, 0), post2[2] = _mm_setr_ps(rbconv_I[nx][j + 2], rbconv_Q[nx][j + 2], 0, 0); + VMEDIAN7(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], medianval); + rbout_I[cx][j + 1] = medianval[0]; + rbout_Q[cx][j + 1] = medianval[1]; + std::swap(pre1, post1); + std::swap(pre2, post2); } - // median Q channel - for (int j = 1; j < W - 2; j += 2) { - SORT3(rbconv_Q[px][j + 1], rbconv_Q[cx][j + 1], rbconv_Q[nx][j + 1], post1_Q[0], post1_Q[1], post1_Q[2]); - NETWORKSORT4OF6(pre2_Q[0], pre2_Q[1], pre2_Q[2], post1_Q[0], post1_Q[1], post1_Q[2], middle_Q[0], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], middle_Q[5], temp[0]); - SORT3(rbconv_Q[px][j + 2], rbconv_Q[cx][j + 2], rbconv_Q[nx][j + 2], post2_Q[0], post2_Q[1], post2_Q[2]); - MEDIAN7(pre1_Q[0], pre1_Q[1], pre1_Q[2], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_Q[cx][j]); - MEDIAN7(post2_Q[0], post2_Q[1], post2_Q[2], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_Q[cx][j + 1]); - tmp = pre1_Q; - pre1_Q = post1_Q; - post1_Q = tmp; - tmp = pre2_Q; - pre2_Q = post2_Q; - post2_Q = tmp; - } - - // fill first and last element in rbout - rbout_I[cx][0] = rbconv_I[cx][0]; + // fill last elements in rbout_I and rbout_Q rbout_I[cx][W - 1] = rbconv_I[cx][W - 1]; rbout_I[cx][W - 2] = rbconv_I[cx][W - 2]; - rbout_Q[cx][0] = rbconv_Q[cx][0]; rbout_Q[cx][W - 1] = rbconv_Q[cx][W - 1]; rbout_Q[cx][W - 2] = rbconv_Q[cx][W - 2]; +#else + pre1[0] = rbconv_I[px][0], pre1[1] = rbconv_I[cx][0], pre1[2] = rbconv_I[nx][0]; + pre2[0] = rbconv_I[px][1], pre2[1] = rbconv_I[cx][1], pre2[2] = rbconv_I[nx][1]; + float temp[7]; + + // fill first element in rbout_I + rbout_I[cx][0] = rbconv_I[cx][0]; + + // median I channel + for (int j = 1; j < W - 2; j += 2) { + post1[0] = rbconv_I[px][j + 1], post1[1] = rbconv_I[cx][j + 1], post1[2] = rbconv_I[nx][j + 1]; + MIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); + MEDIAN7(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_I[cx][j]); + post2[0] = rbconv_I[px][j + 2], post2[1] = rbconv_I[cx][j + 2], post2[2] = rbconv_I[nx][j + 2]; + MEDIAN7(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_I[cx][j + 1]); + std::swap(pre1, post1); + std::swap(pre2, post2); + } + + // fill last elements in rbout_I + rbout_I[cx][W - 1] = rbconv_I[cx][W - 1]; + rbout_I[cx][W - 2] = rbconv_I[cx][W - 2]; + + pre1[0] = rbconv_Q[px][0], pre1[1] = rbconv_Q[cx][0], pre1[2] = rbconv_Q[nx][0]; + pre2[0] = rbconv_Q[px][1], pre2[1] = rbconv_Q[cx][1], pre2[2] = rbconv_Q[nx][1]; + + // fill first element in rbout_Q + rbout_Q[cx][0] = rbconv_Q[cx][0]; + + // median Q channel + for (int j = 1; j < W - 2; j += 2) { + post1[0] = rbconv_Q[px][j + 1], post1[1] = rbconv_Q[cx][j + 1], post1[2] = rbconv_Q[nx][j + 1]; + MIDDLE4OF6(pre2[0], pre2[1], pre2[2], post1[0], post1[1], post1[2], middle[0], middle[1], middle[2], middle[3], middle[4], middle[5], temp[0]); + MEDIAN7(pre1[0], pre1[1], pre1[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_Q[cx][j]); + post2[0] = rbconv_Q[px][j + 2], post2[1] = rbconv_Q[cx][j + 2], post2[2] = rbconv_Q[nx][j + 2]; + MEDIAN7(post2[0], post2[1], post2[2], middle[1], middle[2], middle[3], middle[4], temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], rbout_Q[cx][j + 1]); + std::swap(pre1, post1); + std::swap(pre2, post2); + } + + // fill last elements in rbout_Q + rbout_Q[cx][W - 1] = rbconv_Q[cx][W - 1]; + rbout_Q[cx][W - 2] = rbconv_Q[cx][W - 2]; +#endif + // blur i-1th row if (i > row_from) { + convert_to_RGB (im->r(i - 1, 0), im->g(i - 1, 0), im->b(i - 1, 0), rbconv_Y[px][0], rbout_I[px][0], rbout_Q[px][0]); + #ifdef _OPENMP #pragma omp simd #endif for (int j = 1; j < W - 1; j++) { - row_I[j] = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbout_I[nx][j - 1] + rbout_I[nx][j] + rbout_I[nx][j + 1]) / 9; - row_Q[j] = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbout_Q[nx][j - 1] + rbout_Q[nx][j] + rbout_Q[nx][j + 1]) / 9; + float I = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbout_I[nx][j - 1] + rbout_I[nx][j] + rbout_I[nx][j + 1]) * onebynine; + float Q = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbout_Q[nx][j - 1] + rbout_Q[nx][j] + rbout_Q[nx][j + 1]) * onebynine; + convert_to_RGB (im->r(i - 1, j), im->g(i - 1, j), im->b(i - 1, j), rbconv_Y[px][j], I, Q); } - row_I[0] = rbout_I[px][0]; - row_Q[0] = rbout_Q[px][0]; - row_I[W - 1] = rbout_I[px][W - 1]; - row_Q[W - 1] = rbout_Q[px][W - 1]; - convert_row_to_RGB (im->r(i - 1), im->g(i - 1), im->b(i - 1), rbconv_Y[px], row_I, row_Q, W); + convert_to_RGB (im->r(i - 1, W - 1), im->g(i - 1, W - 1), im->b(i - 1, W - 1), rbconv_Y[px][W - 1], rbout_I[px][W - 1], rbout_Q[px][W - 1]); } } // blur last 3 row and finalize H-1th row + convert_to_RGB (im->r(row_to - 1, 0), im->g(row_to - 1, 0), im->b(row_to - 1, 0), rbconv_Y[cx][0], rbout_I[cx][0], rbout_Q[cx][0]); +#ifdef _OPENMP + #pragma omp simd +#endif + for (int j = 1; j < W - 1; j++) { - row_I[j] = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbconv_I[nx][j - 1] + rbconv_I[nx][j] + rbconv_I[nx][j + 1]) / 9; - row_Q[j] = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbconv_Q[nx][j - 1] + rbconv_Q[nx][j] + rbconv_Q[nx][j + 1]) / 9; + float I = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbconv_I[nx][j - 1] + rbconv_I[nx][j] + rbconv_I[nx][j + 1]) * onebynine; + float Q = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbconv_Q[nx][j - 1] + rbconv_Q[nx][j] + rbconv_Q[nx][j + 1]) * onebynine; + convert_to_RGB (im->r(row_to - 1, j), im->g(row_to - 1, j), im->b(row_to - 1, j), rbconv_Y[cx][j], I, Q); } - row_I[0] = rbout_I[cx][0]; - row_Q[0] = rbout_Q[cx][0]; - row_I[W - 1] = rbout_I[cx][W - 1]; - row_Q[W - 1] = rbout_Q[cx][W - 1]; - convert_row_to_RGB (im->r(row_to - 1), im->g(row_to - 1), im->b(row_to - 1), rbconv_Y[cx], row_I, row_Q, W); + convert_to_RGB (im->r(row_to - 1, W - 1), im->g(row_to - 1, W - 1), im->b(row_to - 1, W - 1), rbconv_Y[cx][W - 1], rbout_I[cx][W - 1], rbout_Q[cx][W - 1]); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -3521,24 +3549,33 @@ void RawImageSource::processFalseColorCorrection (Imagefloat* im, const int ste return; } - for (int t = 0; t < steps; t++) { #ifdef _OPENMP - #pragma omp parallel - { - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = (im->height - 2) / nthreads; + #pragma omp parallel + { + multi_array2D buffer (W, 3); + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = (im->height - 2) / nthreads; - if (tid < nthreads - 1) - { - processFalseColorCorrectionThread (im, 1 + tid * blk, 1 + (tid + 1)*blk); - } else - { processFalseColorCorrectionThread (im, 1 + tid * blk, im->height - 1); } + for (int t = 0; t < steps; t++) { + + if (tid < nthreads - 1) { + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, 1 + (tid + 1)*blk); + } else { + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 + tid * blk, im->height - 1); + } + + #pragma omp barrier } -#else - processFalseColorCorrectionThread (im, 1 , im->height - 1); -#endif } +#else + multi_array2D buffer (W, 3); + + for (int t = 0; t < steps; t++) { + processFalseColorCorrectionThread (im, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], 1 , im->height - 1); + } + +#endif } // Some camera input profiles need gamma preprocessing diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 35da831a0..124aa22d9 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -95,7 +95,7 @@ protected: void hphd_vertical (float** hpmap, int col_from, int col_to); void hphd_horizontal (float** hpmap, int row_from, int row_to); void hphd_green (float** hpmap); - void processFalseColorCorrectionThread (Imagefloat* im, const int row_from, const int row_to); + void processFalseColorCorrectionThread (Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to); void hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip, const RAWParams &raw, float* hlmax); int defTransform (int tran); void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); @@ -209,6 +209,7 @@ protected: void processFalseColorCorrection (Imagefloat* i, const int steps); inline void convert_row_to_YIQ (const float* const r, const float* const g, const float* const b, float* Y, float* I, float* Q, const int W); inline void convert_row_to_RGB (float* r, float* g, float* b, const float* const Y, const float* const I, const float* const Q, const int W); + inline void convert_to_RGB (float &r, float &g, float &b, const float Y, const float I, const float Q); inline void convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob); inline void interpolate_row_g (float* agh, float* agv, int i); diff --git a/rtengine/rawimagesource_i.h b/rtengine/rawimagesource_i.h index 83e834924..f5685b0ef 100644 --- a/rtengine/rawimagesource_i.h +++ b/rtengine/rawimagesource_i.h @@ -51,6 +51,13 @@ inline void RawImageSource::convert_row_to_RGB (float* r, float* g, float* b, co } } +inline void RawImageSource::convert_to_RGB (float &r, float &g, float &b, const float Y, const float I, const float Q) +{ + r = Y + 0.956f * I + 0.621f * Q; + g = Y - 0.272f * I - 0.647f * Q; + b = Y - 1.105f * I + 1.702f * Q; +} + inline void RawImageSource::convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob) {