From 6c8a47ebdf2d1c1693286258f97b1b173224db36 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 26 Jul 2018 00:52:58 +0200 Subject: [PATCH 1/6] AHD demosaic still has some integer processing, #4698 --- rtengine/demosaic_algos.cc | 99 ++++++++++++++++++++++++++------------ rtengine/rawimagesource.h | 1 + 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 4ba855185..39ac911ce 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -37,6 +37,7 @@ #include "sleef.c" #include "opthelper.h" #include "median.h" +#define BENCHMARK #include "StopWatch.h" #ifdef _OPENMP #include @@ -682,6 +683,41 @@ void RawImageSource::ppg_demosaic() free (image); } +void RawImageSource::border_interpolate(unsigned int border, float (*image)[3], unsigned int start, unsigned int end) +{ + unsigned row, col, y, x, f; + float sum[8]; + unsigned int width = W, height = H; + unsigned int colors = 3; + + if (end == 0 ) { + end = H; + } + + for (row = start; row < end; row++) + for (col = 0; col < width; col++) { + if (col == border && row >= border && row < height - border) { + col = width - border; + } + + memset (sum, 0, sizeof sum); + + for (y = row - 1; y != row + 2; y++) + for (x = col - 1; x != col + 2; x++) + if (y < height && x < width) { + f = fc(y, x); + sum[f] += image[y * width + x][f]; + sum[f + 4]++; + } + + f = fc(row, col); + + FORCC if (c != f && sum[c + 4]) { + image[row * width + col][c] = sum[c] / sum[c + 4]; + } + } +} + void RawImageSource::border_interpolate(unsigned int border, float (*image)[4], unsigned int start, unsigned int end) { unsigned row, col, y, x, f; @@ -2303,12 +2339,15 @@ void RawImageSource::igv_interpolate(int winw, int winh) void RawImageSource::ahd_demosaic() { - int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; - float (*pix)[4], (*rix)[3]; + BENCHFUN + int i, j, k, tr, tc, c, d, hm[2]; + float val; + float (*pix)[3], (*rix)[3]; static const int dir[4] = { -1, 1, -TS, TS }; float ldiff[2][4], abdiff[2][4], leps, abeps; - float xyz[3], xyz_cam[3][4]; - float* cbrt; + float xyz[3], xyz_cam[3][3]; + LUTf cbrt(65536); + float (*rgb)[TS][TS][3]; float (*lab)[TS][TS][3]; float (*lix)[3]; @@ -2316,7 +2355,6 @@ void RawImageSource::ahd_demosaic() double r; int width = W, height = H; - float (*image)[4]; unsigned int colors = 3; const double xyz_rgb[3][3] = { /* XYZ from RGB */ @@ -2332,15 +2370,13 @@ void RawImageSource::ahd_demosaic() plistener->setProgress (0.0); } - image = (float (*)[4]) calloc (H * W, sizeof * image); + float (*image)[3] = (float (*)[3]) calloc (H * W, sizeof * image); for (int ii = 0; ii < H; ii++) for (int jj = 0; jj < W; jj++) { image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; } - cbrt = (float (*)) calloc (0x10000, sizeof * cbrt); - for (i = 0; i < 0x10000; i++) { r = (double)i / 65535.0; cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; @@ -2363,40 +2399,40 @@ void RawImageSource::ahd_demosaic() int n_tiles = ((height - 7 + (TS - 7)) / (TS - 6)) * ((width - 7 + (TS - 7)) / (TS - 6)); int tile = 0; - for (top = 2; top < height - 5; top += TS - 6) - for (left = 2; left < width - 5; left += TS - 6) { + 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 (row = top; row < top + TS && row < height - 2; row++) { - col = left + (FC(row, left) & 1); + for (int row = top; row < top + TS && row < height - 2; row++) { + int col = left + (FC(row, left) & 1); for (c = FC(row, col); col < left + TS && col < width - 2; col += 2) { pix = image + (row * width + col); - val = 0.25 * ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 + val = 0.25f * ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 - pix[-2][c] - pix[2][c]) ; - rgb[0][row - top][col - left][1] = median(static_cast(val), pix[-1][1], pix[1][1]); - val = 0.25 * ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 + rgb[0][row - top][col - left][1] = median(val, pix[-1][1], pix[1][1]); + val = 0.25f * ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - pix[-2 * width][c] - pix[2 * width][c]) ; - rgb[1][row - top][col - left][1] = median(static_cast(val), pix[-width][1], pix[width][1]); + rgb[1][row - top][col - left][1] = median(val, pix[-width][1], pix[width][1]); } } /* Interpolate red and blue, and convert to CIELab: */ for (d = 0; d < 2; d++) - for (row = top + 1; row < top + TS - 1 && row < height - 3; row++) - for (col = left + 1; col < left + TS - 1 && col < width - 3; col++) { + for (int row = top + 1; row < top + TS - 1 && row < height - 3; row++) + for (int col = left + 1; col < left + TS - 1 && col < width - 3; col++) { pix = image + (row * width + col); rix = &rgb[d][row - top][col - left]; lix = &lab[d][row - top][col - left]; if ((c = 2 - FC(row, col)) == 1) { c = FC(row + 1, col); - val = pix[0][1] + (0.5 * ( pix[-1][2 - c] + pix[1][2 - c] + val = pix[0][1] + (0.5f * ( pix[-1][2 - c] + pix[1][2 - c] - rix[-1][1] - rix[1][1] ) ); rix[0][2 - c] = CLIP(val); - val = pix[0][1] + (0.5 * ( pix[-width][c] + pix[width][c] + val = pix[0][1] + (0.5f * ( pix[-width][c] + pix[width][c] - rix[-TS][1] - rix[TS][1] ) ); } else - val = rix[0][1] + (0.25 * ( pix[-width - 1][c] + pix[-width + 1][c] + val = rix[0][1] + (0.25f * ( pix[-width - 1][c] + pix[-width + 1][c] + pix[+width - 1][c] + pix[+width + 1][c] - rix[-TS - 1][1] - rix[-TS + 1][1] - rix[+TS - 1][1] - rix[+TS + 1][1]) ); @@ -2404,16 +2440,16 @@ void RawImageSource::ahd_demosaic() rix[0][c] = CLIP(val); c = FC(row, col); rix[0][c] = pix[0][c]; - xyz[0] = xyz[1] = xyz[2] = 0.0; + xyz[0] = xyz[1] = xyz[2] = 0.f; FORCC { xyz[0] += xyz_cam[0][c] * rix[0][c]; xyz[1] += xyz_cam[1][c] * rix[0][c]; xyz[2] += xyz_cam[2][c] * rix[0][c]; } - xyz[0] = CurveFactory::flinterp(cbrt, xyz[0]); - xyz[1] = CurveFactory::flinterp(cbrt, xyz[1]); - xyz[2] = CurveFactory::flinterp(cbrt, xyz[2]); + xyz[0] = cbrt[xyz[0]]; + xyz[1] = cbrt[xyz[1]]; + xyz[2] = cbrt[xyz[2]]; //xyz[0] = xyz[0] > 0.008856 ? pow(xyz[0]/65535,1/3.0) : 7.787*xyz[0] + 16/116.0; //xyz[1] = xyz[1] > 0.008856 ? pow(xyz[1]/65535,1/3.0) : 7.787*xyz[1] + 16/116.0; @@ -2427,17 +2463,17 @@ void RawImageSource::ahd_demosaic() /* Build homogeneity maps from the CIELab images: */ memset (homo, 0, 2 * TS * TS); - for (row = top + 2; row < top + TS - 2 && row < height - 4; row++) { + for (int row = top + 2; row < top + TS - 2 && row < height - 4; row++) { tr = row - top; - for (col = left + 2; col < left + TS - 2 && col < width - 4; col++) { + for (int col = left + 2; col < left + TS - 2 && col < width - 4; col++) { tc = col - left; for (d = 0; d < 2; d++) { lix = &lab[d][tr][tc]; for (i = 0; i < 4; i++) { - ldiff[d][i] = ABS(lix[0][0] - lix[dir[i]][0]); + 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]); } @@ -2457,10 +2493,10 @@ void RawImageSource::ahd_demosaic() } /* Combine the most homogenous pixels for the final result: */ - for (row = top + 3; row < top + TS - 3 && row < height - 5; row++) { + for (int row = top + 3; row < top + TS - 3 && row < height - 5; row++) { tr = row - top; - for (col = left + 3; col < left + TS - 3 && col < width - 5; col++) { + for (int col = left + 3; col < left + TS - 3 && col < width - 5; col++) { tc = col - left; for (d = 0; d < 2; d++) @@ -2473,7 +2509,7 @@ void RawImageSource::ahd_demosaic() FORC3 image[row * width + col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; } else FORC3 image[row * width + col][c] = - 0.5 * (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; + 0.5f * (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; } } @@ -2499,7 +2535,6 @@ void RawImageSource::ahd_demosaic() } free (image); - free (cbrt); } #undef TS diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 53d3e0dc1..aff7f4445 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -273,6 +273,7 @@ protected: void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); void rcd_demosaic(); + void border_interpolate(unsigned int border, float (*image)[3], unsigned int start = 0, unsigned int end = 0); void border_interpolate(unsigned int border, float (*image)[4], unsigned int start = 0, unsigned int end = 0); void border_interpolate2(int winw, int winh, int lborders, const array2D &rawData, array2D &red, array2D &green, array2D &blue); void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); From f3ecd14481b535224e4cad65c135a611fbabe7ef Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 1 Aug 2018 18:48:08 +0200 Subject: [PATCH 2/6] ahd demosaic, reduced processing time and memory usage, #4698 --- rtengine/demosaic_algos.cc | 256 ++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 132 deletions(-) diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 39ac911ce..a806268d0 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -2332,209 +2332,201 @@ void RawImageSource::igv_interpolate(int winw, int winh) /* 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 256 /* Tile Size */ -#define FORC(cnt) for (c=0; c < cnt; c++) -#define FORC3 FORC(3) +#define TS 144 void RawImageSource::ahd_demosaic() { BENCHFUN - int i, j, k, tr, tc, c, d, hm[2]; - float val; - float (*pix)[3], (*rix)[3]; - static const int dir[4] = { -1, 1, -TS, TS }; - float ldiff[2][4], abdiff[2][4], leps, abeps; - float xyz[3], xyz_cam[3][3]; + + constexpr int dir[4] = { -1, 1, -TS, TS }; + float xyz_cam[3][3]; LUTf cbrt(65536); - float (*rgb)[TS][TS][3]; - float (*lab)[TS][TS][3]; - float (*lix)[3]; - char (*homo)[TS][TS], *buffer; - double r; - int width = W, height = H; - unsigned int colors = 3; - const double xyz_rgb[3][3] = { /* XYZ from RGB */ + 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 } }; - const float d65_white[3] = { 0.950456, 1, 1.088754 }; + 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); } - float (*image)[3] = (float (*)[3]) calloc (H * W, sizeof * image); - - for (int ii = 0; ii < H; ii++) - for (int jj = 0; jj < W; jj++) { - image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - for (i = 0; i < 0x10000; i++) { - r = (double)i / 65535.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 (i = 0; i < 3; i++) - for (unsigned int j = 0; j < colors; j++) - for (xyz_cam[i][j] = k = 0; k < 3; k++) { + 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_interpolate(5, image); - buffer = (char *) malloc (13 * TS * TS * sizeof(float)); /* 1664 kB */ - //merror (buffer, "ahd_interpolate()"); - rgb = (float(*)[TS][TS][3]) buffer; - lab = (float(*)[TS][TS][3])(buffer + 6 * TS * TS * sizeof(float)); - homo = (char (*)[TS][TS]) (buffer + 12 * TS * TS * sizeof(float)); + border_interpolate2(W, H, 5, rawData, red, green, blue); - // helper variables for progress indication - int n_tiles = ((height - 7 + (TS - 7)) / (TS - 6)) * ((width - 7 + (TS - 7)) / (TS - 6)); - int tile = 0; +#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)); - for (int top = 2; top < height - 5; top += TS - 6) +#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: */ + // Interpolate green horizontally and vertically: for (int row = top; row < top + TS && row < height - 2; row++) { - int col = left + (FC(row, left) & 1); - - for (c = FC(row, col); col < left + TS && col < width - 2; col += 2) { - pix = image + (row * width + col); - val = 0.25f * ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 - - pix[-2][c] - pix[2][c]) ; - rgb[0][row - top][col - left][1] = median(val, pix[-1][1], pix[1][1]); - val = 0.25f * ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - - pix[-2 * width][c] - pix[2 * width][c]) ; - rgb[1][row - top][col - left][1] = median(val, pix[-width][1], pix[width][1]); + 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 (d = 0; d < 2; d++) - for (int row = top + 1; row < top + TS - 1 && row < height - 3; row++) - for (int col = left + 1; col < left + TS - 1 && col < width - 3; col++) { - pix = image + (row * width + col); + // 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 ((c = 2 - FC(row, col)) == 1) { - c = FC(row + 1, col); - val = pix[0][1] + (0.5f * ( pix[-1][2 - c] + pix[1][2 - c] - - rix[-1][1] - rix[1][1] ) ); - rix[0][2 - c] = CLIP(val); - val = pix[0][1] + (0.5f * ( pix[-width][c] + pix[width][c] - - rix[-TS][1] - rix[TS][1] ) ); - } else - val = rix[0][1] + (0.25f * ( pix[-width - 1][c] + pix[-width + 1][c] - + pix[+width - 1][c] + pix[+width + 1][c] + 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][c] = CLIP(val); - c = FC(row, col); - rix[0][c] = pix[0][c]; - xyz[0] = xyz[1] = xyz[2] = 0.f; - FORCC { - xyz[0] += xyz_cam[0][c] * rix[0][c]; - xyz[1] += xyz_cam[1][c] * rix[0][c]; - xyz[2] += xyz_cam[2][c] * rix[0][c]; + - 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]; } - xyz[0] = cbrt[xyz[0]]; - xyz[1] = cbrt[xyz[1]]; - xyz[2] = cbrt[xyz[2]]; + xyz0 = cbrt[xyz0]; + xyz1 = cbrt[xyz1]; + xyz2 = cbrt[xyz2]; - //xyz[0] = xyz[0] > 0.008856 ? pow(xyz[0]/65535,1/3.0) : 7.787*xyz[0] + 16/116.0; - //xyz[1] = xyz[1] > 0.008856 ? pow(xyz[1]/65535,1/3.0) : 7.787*xyz[1] + 16/116.0; - //xyz[2] = xyz[2] > 0.008856 ? pow(xyz[2]/65535,1/3.0) : 7.787*xyz[2] + 16/116.0; - - lix[0][0] = (116 * xyz[1] - 16); - lix[0][1] = 500 * (xyz[0] - xyz[1]); - lix[0][2] = 200 * (xyz[1] - xyz[2]); + 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: */ - memset (homo, 0, 2 * TS * TS); + // Build homogeneity maps from the CIELab images: for (int row = top + 2; row < top + TS - 2 && row < height - 4; row++) { - tr = row - top; + int tr = row - top; - for (int col = left + 2; col < left + TS - 2 && col < width - 4; col++) { - tc = col - left; - - for (d = 0; d < 2; d++) { + 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 (i = 0; i < 4; i++) { + 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]); } } - leps = min(max(ldiff[0][0], ldiff[0][1]), - max(ldiff[1][2], ldiff[1][3])); - abeps = min(max(abdiff[0][0], abdiff[0][1]), - max(abdiff[1][2], abdiff[1][3])); + 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 (d = 0; d < 2; d++) - for (i = 0; i < 4; i++) + 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: */ + // Combine the most homogenous pixels for the final result: for (int row = top + 3; row < top + TS - 3 && row < height - 5; row++) { - tr = row - top; + int tr = row - top; - for (int col = left + 3; col < left + TS - 3 && col < width - 5; col++) { - tc = col - left; + 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]; + } - for (d = 0; d < 2; d++) - for (hm[d] = 0, i = tr - 1; i <= tr + 1; i++) - for (j = tc - 1; j <= tc + 1; j++) { - hm[d] += homo[d][i][j]; - } - - if (hm[0] != hm[1]) { - FORC3 image[row * width + col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; - } else - FORC3 image[row * width + col][c] = - 0.5f * (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; + 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]); + } } } - tile++; - if(plistener) { - plistener->setProgress((double)tile / n_tiles); - } - } + 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); } - free (buffer); - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - red[i][j] = image[i * W + j][0]; - green[i][j] = image[i * W + j][1]; - blue[i][j] = image[i * W + j][2]; - } - } - - free (image); } #undef TS From c4bd557851e7fae6e3b6c999eb56b821bf50ffbd Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 1 Aug 2018 19:38:46 +0200 Subject: [PATCH 3/6] ahd demosaic: own compilation unit --- rtengine/CMakeLists.txt | 1 + rtengine/ahd_demosaic_RT.cc | 230 ++++++++++++++++++++++++++++++++++++ rtengine/demosaic_algos.cc | 207 +------------------------------- 3 files changed, 233 insertions(+), 205 deletions(-) create mode 100644 rtengine/ahd_demosaic_RT.cc 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); From 7b883f054fdde2e1a667cda0012ebe508327a88a Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 2 Aug 2018 16:14:57 +0200 Subject: [PATCH 4/6] ahd demosaic: further 10% speedup --- rtengine/ahd_demosaic_RT.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rtengine/ahd_demosaic_RT.cc b/rtengine/ahd_demosaic_RT.cc index f394fbfc7..75e3af970 100644 --- a/rtengine/ahd_demosaic_RT.cc +++ b/rtengine/ahd_demosaic_RT.cc @@ -28,6 +28,7 @@ #include "rt_math.h" #include "../rtgui/multilangmgr.h" #include "median.h" +#define BENCHMARK #include "StopWatch.h" namespace rtengine @@ -168,9 +169,7 @@ void RawImageSource::ahd_demosaic() 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]++; - } + homo[d][tr][tc] += ((ldiff[d][i] <= leps) * (abdiff[d][i] <= abeps)); } } } From 7f1d6d67bc9bbc521de39f5990bfc60b19dc249e Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 3 Aug 2018 17:43:37 +0200 Subject: [PATCH 5/6] ahd demosaic review changes --- rtengine/ahd_demosaic_RT.cc | 67 ++++++++++++++++++------------------- rtengine/demosaic_algos.cc | 35 ------------------- rtengine/rawimagesource.h | 1 - 3 files changed, 32 insertions(+), 71 deletions(-) diff --git a/rtengine/ahd_demosaic_RT.cc b/rtengine/ahd_demosaic_RT.cc index 75e3af970..a25ca1363 100644 --- a/rtengine/ahd_demosaic_RT.cc +++ b/rtengine/ahd_demosaic_RT.cc @@ -23,6 +23,7 @@ // Optimized for speed and reduced memory usage 2018 Ingo Weyrich // +#include #include "rtengine.h" #include "rawimagesource.h" #include "rt_math.h" @@ -52,14 +53,14 @@ void RawImageSource::ahd_demosaic() constexpr float d65_white[3] = { 0.950456, 1, 1.088754 }; - volatile double progress = 0.0; + 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; + for (int i = 0; i < 65536; i++) { + const double r = i / 65535.0; cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; } @@ -78,13 +79,10 @@ void RawImageSource::ahd_demosaic() #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)); + float *buffer = new float[13 * TS * TS]; /* 1053 kB per core */ + auto rgb = (float(*)[TS][TS][3]) buffer; + auto lab = (float(*)[TS][TS][3])(buffer + 6 * TS * TS); + auto homo = (uint16_t(*)[TS][TS])(buffer + 12 * TS * TS); #ifdef _OPENMP #pragma omp for collapse(2) schedule(dynamic) nowait @@ -94,7 +92,7 @@ void RawImageSource::ahd_demosaic() // 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]); + auto 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]); @@ -109,9 +107,9 @@ void RawImageSource::ahd_demosaic() 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]; + auto pix = &rawData[row][col]; + auto rix = &rgb[d][row - top][col - left]; + auto 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] ) )); @@ -125,23 +123,21 @@ void RawImageSource::ahd_demosaic() - 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; + float xyz[3] = {}; 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]; + xyz[0] += xyz_cam[0][c] * rix[0][c]; + xyz[1] += xyz_cam[1][c] * rix[0][c]; + xyz[2] += xyz_cam[2][c] * rix[0][c]; } - xyz0 = cbrt[xyz0]; - xyz1 = cbrt[xyz1]; - xyz2 = cbrt[xyz2]; + xyz[0] = cbrt[xyz[0]]; + xyz[1] = cbrt[xyz[1]]; + xyz[2] = cbrt[xyz[2]]; - lix[0][0] = 116.f * xyz1 - 16.f; - lix[0][1] = 500.f * (xyz0 - xyz1); - lix[0][2] = 200.f * (xyz1 - xyz2); + lix[0] = 116.f * xyz[1] - 16.f; + lix[1] = 500.f * (xyz[0] - xyz[1]); + lix[2] = 200.f * (xyz[1] - xyz[2]); } } @@ -149,10 +145,11 @@ void RawImageSource::ahd_demosaic() for (int row = top + 2; row < top + TS - 2 && row < height - 4; row++) { int tr = row - top; + float ldiff[2][4], abdiff[2][4]; 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]; + auto lix = &lab[d][tr][tc]; for (int i = 0; i < 4; i++) { ldiff[d][i] = std::fabs(lix[0][0] - lix[dir[i]][0]); @@ -161,15 +158,15 @@ void RawImageSource::ahd_demosaic() } } - 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])); + float leps = std::min(std::max(ldiff[0][0], ldiff[0][1]), + std::max(ldiff[1][2], ldiff[1][3])); + float abeps = std::min(std::max(abdiff[0][0], abdiff[0][1]), + std::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++) { - homo[d][tr][tc] += ((ldiff[d][i] <= leps) * (abdiff[d][i] <= abeps)); + homo[d][tr][tc] += (ldiff[d][i] <= leps) * (abdiff[d][i] <= abeps); } } } @@ -208,8 +205,8 @@ void RawImageSource::ahd_demosaic() #pragma omp critical (ahdprogress) #endif { - progress += (double)32 * ((TS - 32) * (TS - 32)) / (height * width); - progress = progress > 1.0 ? 1.0 : progress; + progress += 32.0 * SQR(TS - 32) / (height * width); + progress = std::min(progress, 1.0); plistener->setProgress(progress); } } @@ -217,7 +214,7 @@ void RawImageSource::ahd_demosaic() } } - free (buffer); + delete [] buffer; } if(plistener) { plistener->setProgress (1.0); diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 5955c758b..78b5490b5 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -682,41 +682,6 @@ void RawImageSource::ppg_demosaic() free (image); } -void RawImageSource::border_interpolate(unsigned int border, float (*image)[3], unsigned int start, unsigned int end) -{ - unsigned row, col, y, x, f; - float sum[8]; - unsigned int width = W, height = H; - unsigned int colors = 3; - - if (end == 0 ) { - end = H; - } - - for (row = start; row < end; row++) - for (col = 0; col < width; col++) { - if (col == border && row >= border && row < height - border) { - col = width - border; - } - - memset (sum, 0, sizeof sum); - - for (y = row - 1; y != row + 2; y++) - for (x = col - 1; x != col + 2; x++) - if (y < height && x < width) { - f = fc(y, x); - sum[f] += image[y * width + x][f]; - sum[f + 4]++; - } - - f = fc(row, col); - - FORCC if (c != f && sum[c + 4]) { - image[row * width + col][c] = sum[c] / sum[c + 4]; - } - } -} - void RawImageSource::border_interpolate(unsigned int border, float (*image)[4], unsigned int start, unsigned int end) { unsigned row, col, y, x, f; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index aff7f4445..53d3e0dc1 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -273,7 +273,6 @@ protected: void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); void rcd_demosaic(); - void border_interpolate(unsigned int border, float (*image)[3], unsigned int start = 0, unsigned int end = 0); void border_interpolate(unsigned int border, float (*image)[4], unsigned int start = 0, unsigned int end = 0); void border_interpolate2(int winw, int winh, int lborders, const array2D &rawData, array2D &red, array2D &green, array2D &blue); void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); From 5d8d757f7d4c47db6705fdb3f926e81eca8621b3 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 6 Aug 2018 23:59:07 +0200 Subject: [PATCH 6/6] ahd_demosaic: removed stopwatch and improved progress bar --- rtengine/ahd_demosaic_RT.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtengine/ahd_demosaic_RT.cc b/rtengine/ahd_demosaic_RT.cc index a25ca1363..7931bf17d 100644 --- a/rtengine/ahd_demosaic_RT.cc +++ b/rtengine/ahd_demosaic_RT.cc @@ -29,7 +29,7 @@ #include "rt_math.h" #include "../rtgui/multilangmgr.h" #include "median.h" -#define BENCHMARK +//#define BENCHMARK #include "StopWatch.h" namespace rtengine @@ -205,7 +205,7 @@ void RawImageSource::ahd_demosaic() #pragma omp critical (ahdprogress) #endif { - progress += 32.0 * SQR(TS - 32) / (height * width); + progress += 32.0 * SQR(TS - 6) / (height * width); progress = std::min(progress, 1.0); plistener->setProgress(progress); }