diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index ff3024beb..74497d7d0 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -32,6 +32,7 @@ set(RTENGINESOURCEFILES
EdgePreservingDecomposition.cc
FTblockDN.cc
PF_correct_RT.cc
+ ahd_demosaic_RT.cc
amaze_demosaic_RT.cc
cJSON.c
calc_distort.cc
diff --git a/rtengine/ahd_demosaic_RT.cc b/rtengine/ahd_demosaic_RT.cc
new file mode 100644
index 000000000..f394fbfc7
--- /dev/null
+++ b/rtengine/ahd_demosaic_RT.cc
@@ -0,0 +1,230 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2018 Ingo Weyrich (heckflosse67@gmx.de)
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+
+//
+// Adaptive Homogeneity-Directed interpolation is based on
+// the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+// Optimized for speed and reduced memory usage 2018 Ingo Weyrich
+//
+
+#include "rtengine.h"
+#include "rawimagesource.h"
+#include "rt_math.h"
+#include "../rtgui/multilangmgr.h"
+#include "median.h"
+#include "StopWatch.h"
+
+namespace rtengine
+{
+#define TS 144
+void RawImageSource::ahd_demosaic()
+{
+ BENCHFUN
+
+ constexpr int dir[4] = { -1, 1, -TS, TS };
+ float xyz_cam[3][3];
+ LUTf cbrt(65536);
+
+ int width = W, height = H;
+
+ constexpr double xyz_rgb[3][3] = { /* XYZ from RGB */
+ { 0.412453, 0.357580, 0.180423 },
+ { 0.212671, 0.715160, 0.072169 },
+ { 0.019334, 0.119193, 0.950227 }
+ };
+
+ constexpr float d65_white[3] = { 0.950456, 1, 1.088754 };
+
+ volatile double progress = 0.0;
+ if (plistener) {
+ plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AHD)));
+ plistener->setProgress (0.0);
+ }
+
+ for (int i = 0; i < 0x10000; i++) {
+ double r = (double)i / 65535.0;
+ cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0;
+ }
+
+ for (int i = 0; i < 3; i++)
+ for (unsigned int j = 0; j < 3; j++) {
+ xyz_cam[i][j] = 0;
+ for (int k = 0; k < 3; k++) {
+ xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i];
+ }
+ }
+
+ border_interpolate2(W, H, 5, rawData, red, green, blue);
+
+#ifdef _OPENMP
+#pragma omp parallel
+#endif
+{
+ int progresscounter = 0;
+ float (*pix), (*rix)[3];
+ float ldiff[2][4], abdiff[2][4];
+ float (*lix)[3];
+ char *buffer = (char *) malloc (12 * TS * TS * sizeof(float) + 2 * TS * TS * sizeof(uint16_t)); /* 1053 kB per core */
+ float (*rgb)[TS][TS][3] = (float(*)[TS][TS][3]) buffer;
+ float (*lab)[TS][TS][3] = (float(*)[TS][TS][3])(buffer + 6 * TS * TS * sizeof(float));
+ uint16_t (*homo)[TS][TS] = (uint16_t(*)[TS][TS])(buffer + 12 * TS * TS * sizeof(float));
+
+#ifdef _OPENMP
+ #pragma omp for collapse(2) schedule(dynamic) nowait
+#endif
+ for (int top = 2; top < height - 5; top += TS - 6) {
+ for (int left = 2; left < width - 5; left += TS - 6) {
+ // Interpolate green horizontally and vertically:
+ for (int row = top; row < top + TS && row < height - 2; row++) {
+ for (int col = left + (FC(row, left) & 1); col < std::min(left + TS, width - 2); col += 2) {
+ pix = &(rawData[row][col]);
+ float val0 = 0.25f * ((pix[-1] + pix[0] + pix[1]) * 2
+ - pix[-2] - pix[2]) ;
+ rgb[0][row - top][col - left][1] = median(val0, pix[-1], pix[1]);
+ float val1 = 0.25f * ((pix[-width] + pix[0] + pix[width]) * 2
+ - pix[-2 * width] - pix[2 * width]) ;
+ rgb[1][row - top][col - left][1] = median(val1, pix[-width], pix[width]);
+ }
+ }
+
+ // Interpolate red and blue, and convert to CIELab:
+ for (int d = 0; d < 2; d++)
+ for (int row = top + 1; row < top + TS - 1 && row < height - 3; row++) {
+ int cng = FC(row + 1, FC(row + 1, 0) & 1);
+ for (int col = left + 1; col < std::min(left + TS - 1, width - 3); col++) {
+ pix = &(rawData[row][col]);
+ rix = &rgb[d][row - top][col - left];
+ lix = &lab[d][row - top][col - left];
+ if (FC(row, col) == 1) {
+ rix[0][2 - cng] = CLIP(pix[0] + (0.5f * (pix[-1] + pix[1]
+ - rix[-1][1] - rix[1][1] ) ));
+ rix[0][cng] = CLIP(pix[0] + (0.5f * (pix[-width] + pix[width]
+ - rix[-TS][1] - rix[TS][1])));
+ rix[0][1] = pix[0];
+ } else {
+ rix[0][cng] = CLIP(rix[0][1] + (0.25f * (pix[-width - 1] + pix[-width + 1]
+ + pix[+width - 1] + pix[+width + 1]
+ - rix[-TS - 1][1] - rix[-TS + 1][1]
+ - rix[+TS - 1][1] - rix[+TS + 1][1])));
+ rix[0][2 - cng] = pix[0];
+ }
+ float xyz0 = 0.f;
+ float xyz1 = 0.f;
+ float xyz2 = 0.f;
+
+ for(unsigned int c = 0; c < 3; ++c) {
+ xyz0 += xyz_cam[0][c] * rix[0][c];
+ xyz1 += xyz_cam[1][c] * rix[0][c];
+ xyz2 += xyz_cam[2][c] * rix[0][c];
+ }
+
+ xyz0 = cbrt[xyz0];
+ xyz1 = cbrt[xyz1];
+ xyz2 = cbrt[xyz2];
+
+ lix[0][0] = 116.f * xyz1 - 16.f;
+ lix[0][1] = 500.f * (xyz0 - xyz1);
+ lix[0][2] = 200.f * (xyz1 - xyz2);
+ }
+ }
+
+ // Build homogeneity maps from the CIELab images:
+
+ for (int row = top + 2; row < top + TS - 2 && row < height - 4; row++) {
+ int tr = row - top;
+
+ for (int col = left + 2, tc = 2; col < left + TS - 2 && col < width - 4; col++, tc++) {
+ for (int d = 0; d < 2; d++) {
+ lix = &lab[d][tr][tc];
+
+ for (int i = 0; i < 4; i++) {
+ ldiff[d][i] = std::fabs(lix[0][0] - lix[dir[i]][0]);
+ abdiff[d][i] = SQR(lix[0][1] - lix[dir[i]][1])
+ + SQR(lix[0][2] - lix[dir[i]][2]);
+ }
+ }
+
+ float leps = min(max(ldiff[0][0], ldiff[0][1]),
+ max(ldiff[1][2], ldiff[1][3]));
+ float abeps = min(max(abdiff[0][0], abdiff[0][1]),
+ max(abdiff[1][2], abdiff[1][3]));
+
+ for (int d = 0; d < 2; d++) {
+ homo[d][tr][tc] = 0;
+ for (int i = 0; i < 4; i++) {
+ if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) {
+ homo[d][tr][tc]++;
+ }
+ }
+ }
+ }
+ }
+
+ // Combine the most homogenous pixels for the final result:
+ for (int row = top + 3; row < top + TS - 3 && row < height - 5; row++) {
+ int tr = row - top;
+
+ for (int col = left + 3, tc = 3; col < std::min(left + TS - 3, width - 5); col++, tc++) {
+ uint16_t hm0 = 0, hm1 = 0;
+ for (int i = tr - 1; i <= tr + 1; i++)
+ for (int j = tc - 1; j <= tc + 1; j++) {
+ hm0 += homo[0][i][j];
+ hm1 += homo[1][i][j];
+ }
+
+ if (hm0 != hm1) {
+ int dir = hm1 > hm0;
+ red[row][col] = rgb[dir][tr][tc][0];
+ green[row][col] = rgb[dir][tr][tc][1];
+ blue[row][col] = rgb[dir][tr][tc][2];
+ } else {
+ red[row][col] = 0.5f * (rgb[0][tr][tc][0] + rgb[1][tr][tc][0]);
+ green[row][col] = 0.5f * (rgb[0][tr][tc][1] + rgb[1][tr][tc][1]);
+ blue[row][col] = 0.5f * (rgb[0][tr][tc][2] + rgb[1][tr][tc][2]);
+ }
+ }
+ }
+
+ if(plistener) {
+ progresscounter++;
+
+ if(progresscounter % 32 == 0) {
+#ifdef _OPENMP
+ #pragma omp critical (ahdprogress)
+#endif
+ {
+ progress += (double)32 * ((TS - 32) * (TS - 32)) / (height * width);
+ progress = progress > 1.0 ? 1.0 : progress;
+ plistener->setProgress(progress);
+ }
+ }
+ }
+
+ }
+ }
+ free (buffer);
+}
+ if(plistener) {
+ plistener->setProgress (1.0);
+ }
+
+}
+#undef TS
+
+}
\ No newline at end of file
diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc
index a806268d0..5955c758b 100644
--- a/rtengine/demosaic_algos.cc
+++ b/rtengine/demosaic_algos.cc
@@ -37,7 +37,6 @@
#include "sleef.c"
#include "opthelper.h"
#include "median.h"
-#define BENCHMARK
#include "StopWatch.h"
#ifdef _OPENMP
#include
@@ -1221,7 +1220,7 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &r
// apply low pass filter on differential colors
#ifdef _OPENMP
- #pragma omp for
+ #pragma omp for
#endif
for (int rr = 4; rr < rr1 - 4; rr++)
@@ -1447,7 +1446,7 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &r
// interpolate R/B at B/R location
#ifdef _OPENMP
- #pragma omp for
+ #pragma omp for
#endif
for (int rr = 1; rr < rr1 - 1; rr++)
@@ -2328,208 +2327,6 @@ void RawImageSource::igv_interpolate(int winw, int winh)
}
#endif
-
-/*
- Adaptive Homogeneity-Directed interpolation is based on
- the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
- Optimized for speed and reduced memory usage 2018 Ingo Weyrich
- */
-
-#define TS 144
-void RawImageSource::ahd_demosaic()
-{
- BENCHFUN
-
- constexpr int dir[4] = { -1, 1, -TS, TS };
- float xyz_cam[3][3];
- LUTf cbrt(65536);
-
- int width = W, height = H;
-
- constexpr double xyz_rgb[3][3] = { /* XYZ from RGB */
- { 0.412453, 0.357580, 0.180423 },
- { 0.212671, 0.715160, 0.072169 },
- { 0.019334, 0.119193, 0.950227 }
- };
-
- constexpr float d65_white[3] = { 0.950456, 1, 1.088754 };
-
- volatile double progress = 0.0;
- if (plistener) {
- plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AHD)));
- plistener->setProgress (0.0);
- }
-
- for (int i = 0; i < 0x10000; i++) {
- double r = (double)i / 65535.0;
- cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0;
- }
-
- for (int i = 0; i < 3; i++)
- for (unsigned int j = 0; j < 3; j++) {
- xyz_cam[i][j] = 0;
- for (int k = 0; k < 3; k++) {
- xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i];
- }
- }
-
- border_interpolate2(W, H, 5, rawData, red, green, blue);
-
-#ifdef _OPENMP
-#pragma omp parallel
-#endif
-{
- int progresscounter = 0;
- float (*pix), (*rix)[3];
- float ldiff[2][4], abdiff[2][4];
- float (*lix)[3];
- char *buffer = (char *) malloc (12 * TS * TS * sizeof(float) + 2 * TS * TS * sizeof(uint16_t)); /* 1053 kB per core */
- float (*rgb)[TS][TS][3] = (float(*)[TS][TS][3]) buffer;
- float (*lab)[TS][TS][3] = (float(*)[TS][TS][3])(buffer + 6 * TS * TS * sizeof(float));
- uint16_t (*homo)[TS][TS] = (uint16_t(*)[TS][TS])(buffer + 12 * TS * TS * sizeof(float));
-
-#ifdef _OPENMP
- #pragma omp for collapse(2) schedule(dynamic) nowait
-#endif
- for (int top = 2; top < height - 5; top += TS - 6) {
- for (int left = 2; left < width - 5; left += TS - 6) {
- // Interpolate green horizontally and vertically:
- for (int row = top; row < top + TS && row < height - 2; row++) {
- for (int col = left + (FC(row, left) & 1); col < std::min(left + TS, width - 2); col += 2) {
- pix = &(rawData[row][col]);
- float val0 = 0.25f * ((pix[-1] + pix[0] + pix[1]) * 2
- - pix[-2] - pix[2]) ;
- rgb[0][row - top][col - left][1] = median(val0, pix[-1], pix[1]);
- float val1 = 0.25f * ((pix[-width] + pix[0] + pix[width]) * 2
- - pix[-2 * width] - pix[2 * width]) ;
- rgb[1][row - top][col - left][1] = median(val1, pix[-width], pix[width]);
- }
- }
-
- // Interpolate red and blue, and convert to CIELab:
- for (int d = 0; d < 2; d++)
- for (int row = top + 1; row < top + TS - 1 && row < height - 3; row++) {
- int cng = FC(row + 1, FC(row + 1, 0) & 1);
- for (int col = left + 1; col < std::min(left + TS - 1, width - 3); col++) {
- pix = &(rawData[row][col]);
- rix = &rgb[d][row - top][col - left];
- lix = &lab[d][row - top][col - left];
- if (FC(row, col) == 1) {
- rix[0][2 - cng] = CLIP(pix[0] + (0.5f * (pix[-1] + pix[1]
- - rix[-1][1] - rix[1][1] ) ));
- rix[0][cng] = CLIP(pix[0] + (0.5f * (pix[-width] + pix[width]
- - rix[-TS][1] - rix[TS][1])));
- rix[0][1] = pix[0];
- } else {
- rix[0][cng] = CLIP(rix[0][1] + (0.25f * (pix[-width - 1] + pix[-width + 1]
- + pix[+width - 1] + pix[+width + 1]
- - rix[-TS - 1][1] - rix[-TS + 1][1]
- - rix[+TS - 1][1] - rix[+TS + 1][1])));
- rix[0][2 - cng] = pix[0];
- }
- float xyz0 = 0.f;
- float xyz1 = 0.f;
- float xyz2 = 0.f;
-
- for(unsigned int c = 0; c < 3; ++c) {
- xyz0 += xyz_cam[0][c] * rix[0][c];
- xyz1 += xyz_cam[1][c] * rix[0][c];
- xyz2 += xyz_cam[2][c] * rix[0][c];
- }
-
- xyz0 = cbrt[xyz0];
- xyz1 = cbrt[xyz1];
- xyz2 = cbrt[xyz2];
-
- lix[0][0] = 116.f * xyz1 - 16.f;
- lix[0][1] = 500.f * (xyz0 - xyz1);
- lix[0][2] = 200.f * (xyz1 - xyz2);
- }
- }
-
- // Build homogeneity maps from the CIELab images:
-
- for (int row = top + 2; row < top + TS - 2 && row < height - 4; row++) {
- int tr = row - top;
-
- for (int col = left + 2, tc = 2; col < left + TS - 2 && col < width - 4; col++, tc++) {
- for (int d = 0; d < 2; d++) {
- lix = &lab[d][tr][tc];
-
- for (int i = 0; i < 4; i++) {
- ldiff[d][i] = std::fabs(lix[0][0] - lix[dir[i]][0]);
- abdiff[d][i] = SQR(lix[0][1] - lix[dir[i]][1])
- + SQR(lix[0][2] - lix[dir[i]][2]);
- }
- }
-
- float leps = min(max(ldiff[0][0], ldiff[0][1]),
- max(ldiff[1][2], ldiff[1][3]));
- float abeps = min(max(abdiff[0][0], abdiff[0][1]),
- max(abdiff[1][2], abdiff[1][3]));
-
- for (int d = 0; d < 2; d++) {
- homo[d][tr][tc] = 0;
- for (int i = 0; i < 4; i++) {
- if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) {
- homo[d][tr][tc]++;
- }
- }
- }
- }
- }
-
- // Combine the most homogenous pixels for the final result:
- for (int row = top + 3; row < top + TS - 3 && row < height - 5; row++) {
- int tr = row - top;
-
- for (int col = left + 3, tc = 3; col < std::min(left + TS - 3, width - 5); col++, tc++) {
- uint16_t hm0 = 0, hm1 = 0;
- for (int i = tr - 1; i <= tr + 1; i++)
- for (int j = tc - 1; j <= tc + 1; j++) {
- hm0 += homo[0][i][j];
- hm1 += homo[1][i][j];
- }
-
- if (hm0 != hm1) {
- int dir = hm1 > hm0;
- red[row][col] = rgb[dir][tr][tc][0];
- green[row][col] = rgb[dir][tr][tc][1];
- blue[row][col] = rgb[dir][tr][tc][2];
- } else {
- red[row][col] = 0.5f * (rgb[0][tr][tc][0] + rgb[1][tr][tc][0]);
- green[row][col] = 0.5f * (rgb[0][tr][tc][1] + rgb[1][tr][tc][1]);
- blue[row][col] = 0.5f * (rgb[0][tr][tc][2] + rgb[1][tr][tc][2]);
- }
- }
- }
-
- if(plistener) {
- progresscounter++;
-
- if(progresscounter % 32 == 0) {
-#ifdef _OPENMP
- #pragma omp critical (ahdprogress)
-#endif
- {
- progress += (double)32 * ((TS - 32) * (TS - 32)) / (height * width);
- progress = progress > 1.0 ? 1.0 : progress;
- plistener->setProgress(progress);
- }
- }
- }
-
- }
- }
- free (buffer);
-}
- if(plistener) {
- plistener->setProgress (1.0);
- }
-
-}
-#undef TS
-
void RawImageSource::nodemosaic(bool bw)
{
red(W, H);