From 036114c6044db66413c1f83aeb4083f67c0ad437 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 5 Feb 2016 23:30:46 +0100 Subject: [PATCH 1/4] Fix border und highlight reconstruction issues for Nikon D1x files --- rtengine/rawimagesource.cc | 202 +++++++++++++++++++++++-------------- rtengine/rawimagesource.h | 4 +- 2 files changed, 131 insertions(+), 75 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 2a5f42d56..702003ce8 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -308,7 +308,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre defGain = 0.0; // compute image area to render in order to provide the requested part of the image - int sx1, sy1, imwidth, imheight, fw; + int sx1, sy1, imwidth, imheight, fw, d1xHeightOdd; transformRect (pp, tran, sx1, sy1, imwidth, imheight, fw); // check possible overflows @@ -323,6 +323,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre } if (d1x) { + d1xHeightOdd = maximheight & 1; maximheight /= 2; } @@ -364,7 +365,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre #pragma omp for #endif - for (int ix = 0; ix < imheight; ix++) { + for (int ix = 0; ix < (d1x ? maximheight : imheight); ix++) { int i = sy1 + skip * ix; if (i >= maxy - skip) { @@ -396,7 +397,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre // exposure this means that we can clip away local highlights which actually // are not clipped. We have to do that though as we only check pixel by pixel // and don't know if this will transition into a clipped area, if so we need - // to clip also surrounding to make a good color transition + // to clip also surrounding to make a good colour transition rtot = CLIP(rtot); gtot = CLIP(gtot); btot = CLIP(btot); @@ -444,7 +445,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip, raw, hlmax); } - transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, fw); + transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, d1x ? maximheight : imheight, fw, d1xHeightOdd, !hrp.hrenabled && has_clipping); } @@ -1077,7 +1078,7 @@ SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thres return counter; } -void RawImageSource::rotateLine (float* line, PlanarPtr &channel, int tran, int i, int w, int h) +void RawImageSource::rotateLine (const float* const line, PlanarPtr &channel, const int tran, const int i, const int w, const int h) { if ((tran & TR_ROT) == TR_R180) @@ -1091,8 +1092,8 @@ void RawImageSource::rotateLine (float* line, PlanarPtr &channel, int tra } else if ((tran & TR_ROT) == TR_R270) - for (int j = 0; j < w; j++) { - channel(w - 1 - j, i) = line[j]; + for (int j = 0, cj = w - 1; j < w; j++, cj--) { + channel(cj, i) = line[j]; } else for (int j = 0; j < w; j++) { @@ -1102,7 +1103,7 @@ void RawImageSource::rotateLine (float* line, PlanarPtr &channel, int tra //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imwidth, int imheight, int fw) +void RawImageSource::transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imwidth, int imheight, int fw, bool d1xHeightOdd, bool d1xClip) { // Fuji SuperCCD rotation + coarse rotation @@ -1168,13 +1169,19 @@ void RawImageSource::transLine (float* red, float* green, float* blue, int i, Im // Nikon D1X vertical interpolation + coarse rotation else if (d1x) { // copy new pixels - if ((tran & TR_ROT) == TR_R180) { + if ((tran & TR_ROT) == TR_R180) { // rotate 2 times left or two times right for (int j = 0; j < imwidth; j++) { image->r(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = red[j]; image->g(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = green[j]; image->b(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = blue[j]; } - + if (i == 0) { + for (int j = 0; j < imwidth; j++) { + image->r(2 * imheight - 1, imwidth - 1 - j) = red[j]; + image->g(2 * imheight - 1, imwidth - 1 - j) = green[j]; + image->b(2 * imheight - 1, imwidth - 1 - j) = blue[j]; + } + } if (i == 1 || i == 2) { // linear interpolation int row = 2 * imheight - 1 - 2 * i; @@ -1184,7 +1191,16 @@ void RawImageSource::transLine (float* red, float* green, float* blue, int i, Im image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; } - } else if (i == imheight - 1) { + if(i == 2 && d1xHeightOdd) { + int row = 2 * imheight; + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row - 2, col)) / 2; + image->g(row, col) = (green[j] + image->g(row - 2, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row - 2, col)) / 2; + } + } + } else if (i == imheight - 1 || i == imheight - 2) { int row = 2 * imheight - 1 - 2 * i; for (int j = 0; j < imwidth; j++) { @@ -1207,12 +1223,24 @@ void RawImageSource::transLine (float* red, float* green, float* blue, int i, Im for (int j = 0; j < imwidth; j++) { int col = imwidth - 1 - j; - image->r(row, col) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(row - 1, col) + 0.5625 * image->r(row + 1, col) - 0.0625 * image->r(row + 3, col))); - image->g(row, col) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(row - 1, col) + 0.5625 * image->g(row + 1, col) - 0.0625 * image->g(row + 3, col))); - image->b(row, col) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(row - 1, col) + 0.5625 * image->b(row + 1, col) - 0.0625 * image->b(row + 3, col))); + image->r(row, col) = MAX(0.f, -0.0625f * (red[j] + image->r(row + 3, col)) + 0.5625f * (image->r(row - 1, col) + image->r(row + 1, col))); + image->g(row, col) = MAX(0.f, -0.0625f * (green[j] + image->g(row + 3, col)) + 0.5625f * (image->g(row - 1, col) + image->g(row + 1, col))); + image->b(row, col) = MAX(0.f, -0.0625f * (blue[j] + image->b(row + 3, col)) + 0.5625f * (image->b(row - 1, col) + image->b(row + 1, col))); + if(d1xClip) { + image->r(row, col) = MIN(image->r(row, col), MAXVALF); + image->g(row, col) = MIN(image->g(row, col), MAXVALF); + image->b(row, col) = MIN(image->b(row, col), MAXVALF); + } + } + } + } else if ((tran & TR_ROT) == TR_R90) { // rotate right + if( i == 0) { + for (int j = 0; j < imwidth; j++) { + image->r(j, 2 * imheight - 1) = red[j]; + image->g(j, 2 * imheight - 1) = green[j]; + image->b(j, 2 * imheight - 1) = blue[j]; } } - } else if ((tran & TR_ROT) == TR_R90) { for (int j = 0; j < imwidth; j++) { image->r(j, 2 * imheight - 2 - 2 * i) = red[j]; image->g(j, 2 * imheight - 2 - 2 * i) = green[j]; @@ -1226,6 +1254,11 @@ void RawImageSource::transLine (float* red, float* green, float* blue, int i, Im image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + if(d1xHeightOdd && i == 2) { + image->r(j, 2 * imheight) = (red[j] + image->r(j, 2 * imheight - 2)) / 2; + image->g(j, 2 * imheight) = (green[j] + image->g(j, 2 * imheight - 2)) / 2; + image->b(j, 2 * imheight) = (blue[j] + image->b(j, 2 * imheight - 2)) / 2; + } } } else if (i == imheight - 1) { int col = 2 * imheight - 1 - 2 * i; @@ -1235,9 +1268,7 @@ void RawImageSource::transLine (float* red, float* green, float* blue, int i, Im image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; } - col = 2 * imheight - 1 - 2 * i + 2; - for (int j = 0; j < imwidth; j++) { image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; @@ -1247,68 +1278,106 @@ void RawImageSource::transLine (float* red, float* green, float* blue, int i, Im int col = 2 * imheight - 1 - 2 * i + 2; for (int j = 0; j < imwidth; j++) { - image->r(j, col) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(j, col - 1) + 0.5625 * image->r(j, col + 1) - 0.0625 * image->r(j, col + 3))); - image->g(j, col) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(j, col - 1) + 0.5625 * image->g(j, col + 1) - 0.0625 * image->g(j, col + 3))); - image->b(j, col) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(j, col - 1) + 0.5625 * image->b(j, col + 1) - 0.0625 * image->b(j, col + 3))); + image->r(j, col) = MAX(0.f, -0.0625f * (red[j] + image->r(j, col + 3)) + 0.5625f * (image->r(j, col - 1) + image->r(j, col + 1))); + image->g(j, col) = MAX(0.f, -0.0625f * (green[j] + image->g(j, col + 3)) + 0.5625f * (image->g(j, col - 1) + image->g(j, col + 1))); + image->b(j, col) = MAX(0.f, -0.0625f * (blue[j] + image->b(j, col + 3)) + 0.5625f * (image->b(j, col - 1) + image->b(j, col + 1))); + if(d1xClip) { + image->r(j, col) = MIN(image->r(j, col), MAXVALF); + image->g(j, col) = MIN(image->g(j, col), MAXVALF); + image->b(j, col) = MIN(image->b(j, col), MAXVALF); + } } } - } else if ((tran & TR_ROT) == TR_R270) { - for (int j = 0; j < imwidth; j++) { - image->r(imwidth - 1 - j, 2 * i) = red[j]; - image->g(imwidth - 1 - j, 2 * i) = green[j]; - image->b(imwidth - 1 - j, 2 * i) = blue[j]; - } - - if (i == 1 || i == 2) { // linear interpolation - for (int j = 0; j < imwidth; j++) { - int row = imwidth - 1 - j; + } else if ((tran & TR_ROT) == TR_R270) { // rotate left + if (i == 0) { + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i) = red[j]; + image->g(row, 2 * i) = green[j]; + image->b(row, 2 * i) = blue[j]; + } + } else if (i == 1 || i == 2) { // linear interpolation + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i) = red[j]; + image->g(row, 2 * i) = green[j]; + image->b(row, 2 * i) = blue[j]; image->r(row, 2 * i - 1) = (red[j] + image->r(row, 2 * i - 2)) * 0.5f; image->g(row, 2 * i - 1) = (green[j] + image->g(row, 2 * i - 2)) * 0.5f; image->b(row, 2 * i - 1) = (blue[j] + image->b(row, 2 * i - 2)) * 0.5f; } - } else if (i == imheight - 1) { - for (int j = 0; j < imwidth; j++) { - int row = imwidth - 1 - j; - image->r(row, 2 * i - 1) = (red[j] + image->r(row, 2 * i - 2)) * 0.5f; - image->g(row, 2 * i - 1) = (green[j] + image->g(row, 2 * i - 2)) * 0.5f; - image->b(row, 2 * i - 1) = (blue[j] + image->b(row, 2 * i - 2)) * 0.5f; - image->r(row, 2 * i - 3) = (image->r(row, 2 * i - 2) + image->r(row, 2 * i - 4)) * 0.5f; - image->g(row, 2 * i - 3) = (image->g(row, 2 * i - 2) + image->g(row, 2 * i - 4)) * 0.5f; - image->b(row, 2 * i - 3) = (image->b(row, 2 * i - 2) + image->b(row, 2 * i - 4)) * 0.5f; - } - } else if (i > 0 && i < imheight - 1) { // vertical bicubic interpolationi - for (int j = 0; j < imwidth; j++) { - int row = imwidth - 1 - j; - image->r(row, 2 * i - 3) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(row, 2 * i - 2) + 0.5625 * image->r(row, 2 * i - 4) - 0.0625 * image->r(row, 2 * i - 6))); - image->g(row, 2 * i - 3) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(row, 2 * i - 2) + 0.5625 * image->g(row, 2 * i - 4) - 0.0625 * image->g(row, 2 * i - 6))); - image->b(row, 2 * i - 3) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(row, 2 * i - 2) + 0.5625 * image->b(row, 2 * i - 4) - 0.0625 * image->b(row, 2 * i - 6))); + } else if (i > 0 && i < imheight) { // vertical bicubic interpolation + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i - 3) = MAX(0.f, -0.0625f * (red[j] + image->r(row, 2 * i - 6)) + 0.5625f * (image->r(row, 2 * i - 2) + image->r(row, 2 * i - 4))); + image->g(row, 2 * i - 3) = MAX(0.f, -0.0625f * (green[j] + image->g(row, 2 * i - 6)) + 0.5625f * (image->g(row, 2 * i - 2) + image->g(row, 2 * i - 4))); + image->b(row, 2 * i - 3) = MAX(0.f, -0.0625f * (blue[j] + image->b(row, 2 * i - 6)) + 0.5625f * (image->b(row, 2 * i - 2) + image->b(row, 2 * i - 4))); + if(d1xClip) { + image->r(row, 2 * i - 3) = MIN(image->r(row, 2 * i - 3), MAXVALF); + image->g(row, 2 * i - 3) = MIN(image->g(row, 2 * i - 3), MAXVALF); + image->b(row, 2 * i - 3) = MIN(image->b(row, 2 * i - 3), MAXVALF); + } + image->r(row, 2 * i) = red[j]; + image->g(row, 2 * i) = green[j]; + image->b(row, 2 * i) = blue[j]; } } - } else { + if (i == imheight - 1) { + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i - 1) = MAX(0.f, -0.0625f * (red[j] + image->r(row, 2 * i - 4)) + 0.5625f * (image->r(row, 2 * i) + image->r(row, 2 * i - 2))); + image->g(row, 2 * i - 1) = MAX(0.f, -0.0625f * (green[j] + image->g(row, 2 * i - 4)) + 0.5625f * (image->g(row, 2 * i) + image->g(row, 2 * i - 2))); + image->b(row, 2 * i - 1) = MAX(0.f, -0.0625f * (blue[j] + image->b(row, 2 * i - 4)) + 0.5625f * (image->b(row, 2 * i) + image->b(row, 2 * i - 2))); + if(d1xClip) { + image->r(j, 2 * i - 1) = MIN(image->r(j, 2 * i - 1), MAXVALF); + image->g(j, 2 * i - 1) = MIN(image->g(j, 2 * i - 1), MAXVALF); + image->b(j, 2 * i - 1) = MIN(image->b(j, 2 * i - 1), MAXVALF); + } + image->r(row, 2 * i + 1) = (red[j] + image->r(row, 2 * i - 1)) / 2; + image->g(row, 2 * i + 1) = (green[j] + image->g(row, 2 * i - 1)) / 2; + image->b(row, 2 * i + 1) = (blue[j] + image->b(row, 2 * i - 1)) / 2; + if (d1xHeightOdd) { + image->r(row, 2 * i + 2) = (red[j] + image->r(row, 2 * i - 2)) / 2; + image->g(row, 2 * i + 2) = (green[j] + image->g(row, 2 * i - 2)) / 2; + image->b(row, 2 * i + 2) = (blue[j] + image->b(row, 2 * i - 2)) / 2; + } + } + } + } else { // no coarse rotation rotateLine (red, image->r, tran, 2 * i, imwidth, imheight); rotateLine (green, image->g, tran, 2 * i, imwidth, imheight); rotateLine (blue, image->b, tran, 2 * i, imwidth, imheight); - if (i == 1 || i == 2) { // linear interpolation for (int j = 0; j < imwidth; j++) { image->r(2 * i - 1, j) = (red[j] + image->r(2 * i - 2, j)) / 2; image->g(2 * i - 1, j) = (green[j] + image->g(2 * i - 2, j)) / 2; image->b(2 * i - 1, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; } - } else if (i == imheight - 1) { + } else if (i > 2 && i < imheight) { // vertical bicubic interpolation for (int j = 0; j < imwidth; j++) { - image->r(2 * i - 3, j) = (image->r(2 * i - 4, j) + image->r(2 * i - 2, j)) / 2; - image->g(2 * i - 3, j) = (image->g(2 * i - 4, j) + image->g(2 * i - 2, j)) / 2; - image->b(2 * i - 3, j) = (image->b(2 * i - 4, j) + image->b(2 * i - 2, j)) / 2; - image->r(2 * i - 1, j) = (red[j] + image->r(2 * i - 2, j)) / 2; - image->g(2 * i - 1, j) = (green[j] + image->g(2 * i - 2, j)) / 2; - image->b(2 * i - 1, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; + image->r(2 * i - 3, j) = MAX(0.f, -0.0625f * (red[j] + image->r(2 * i - 6, j)) + 0.5625f * (image->r(2 * i - 2, j) + image->r(2 * i - 4, j))); + image->g(2 * i - 3, j) = MAX(0.f, -0.0625f * (green[j] + image->g(2 * i - 6, j)) + 0.5625f * (image->g(2 * i - 2, j) + image->g(2 * i - 4, j))); + image->b(2 * i - 3, j) = MAX(0.f, -0.0625f * (blue[j] + image->b(2 * i - 6, j)) + 0.5625f * (image->b(2 * i - 2, j) + image->b(2 * i - 4, j))); + if(d1xClip) { + image->r(2 * i - 3, j) = MIN(image->r(2 * i - 3, j), MAXVALF); + image->g(2 * i - 3, j) = MIN(image->g(2 * i - 3, j), MAXVALF); + image->b(2 * i - 3, j) = MIN(image->b(2 * i - 3, j), MAXVALF); + } } - } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolationi + } if (i == imheight - 1) { for (int j = 0; j < imwidth; j++) { - image->r(2 * i - 3, j) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(2 * i - 2, j) + 0.5625 * image->r(2 * i - 4, j) - 0.0625 * image->r(2 * i - 6, j))); - image->g(2 * i - 3, j) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(2 * i - 2, j) + 0.5625 * image->g(2 * i - 4, j) - 0.0625 * image->g(2 * i - 6, j))); - image->b(2 * i - 3, j) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(2 * i - 2, j) + 0.5625 * image->b(2 * i - 4, j) - 0.0625 * image->b(2 * i - 6, j))); + image->r(2 * i - 1, j) = MAX(0.f, -0.0625f * (red[j] + image->r(2 * i - 4, j)) + 0.5625f * (image->r(2 * i, j) + image->r(2 * i - 2, j))); + image->g(2 * i - 1, j) = MAX(0.f, -0.0625f * (green[j] + image->g(2 * i - 4, j)) + 0.5625f * (image->g(2 * i, j) + image->g(2 * i - 2, j))); + image->b(2 * i - 1, j) = MAX(0.f, -0.0625f * (blue[j] + image->b(2 * i - 4, j)) + 0.5625f * (image->b(2 * i, j) + image->b(2 * i - 2, j))); + if(d1xClip) { + image->r(2 * i - 1, j) = MIN(image->r(2 * i - 1, j), MAXVALF); + image->g(2 * i - 1, j) = MIN(image->g(2 * i - 1, j), MAXVALF); + image->b(2 * i - 1, j) = MIN(image->b(2 * i - 1, j), MAXVALF); + } + image->r(2 * i + 1, j) = (red[j] + image->r(2 * i - 1, j)) / 2; + image->g(2 * i + 1, j) = (green[j] + image->g(2 * i - 1, j)) / 2; + image->b(2 * i + 1, j) = (blue[j] + image->b(2 * i - 1, j)) / 2; + if (d1xHeightOdd) { + image->r(2 * i + 2, j) = (red[j] + image->r(2 * i - 2, j)) / 2; + image->g(2 * i + 2, j) = (green[j] + image->g(2 * i - 2, j)) / 2; + image->b(2 * i + 2, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; + } } } } @@ -1333,7 +1402,7 @@ void RawImageSource::getFullSize (int& w, int& h, int tr) h = (H - ri->get_FujiWidth()) * 2 + 1; } else if (d1x) { w = W; - h = 2 * H - 1; + h = 2 * H; } else { w = W; h = H; @@ -1355,17 +1424,8 @@ void RawImageSource::getSize (int tran, PreviewProps pp, int& w, int& h) { tran = defTransform (tran); - -// if (fuji) { -// return; -// } -// else if (d1x) { -// return; -// } -// else { w = pp.w / pp.skip + (pp.w % pp.skip > 0); h = pp.h / pp.skip + (pp.h % pp.skip > 0); -// } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1426,10 +1486,6 @@ int RawImageSource::load (Glib::ustring fname, bool batch) d1x = ! ri->get_model().compare("D1X"); - if (d1x) { - border = 8; - } - if(ri->getSensorType() == ST_FUJI_XTRANS) { border = 7; } else if(ri->getSensorType() == ST_FOVEON) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 10057d58a..06fc341a3 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -130,7 +130,7 @@ protected: void processFalseColorCorrectionThread (Imagefloat* im, int row_from, 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 rotateLine (float* line, PlanarPtr &channel, int tran, int i, int w, int h); + void rotateLine (const float* const line, PlanarPtr &channel, const int tran, const int i, const int w, const int h); void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); void transformPosition (int x, int y, int tran, int& tx, int& ty); @@ -303,7 +303,7 @@ protected: void xtransborder_interpolate (int border); void xtrans_interpolate (int passes, bool useCieLab); void fast_xtrans_interpolate (); - void transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imw, int imh, int fw); + void transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imw, int imh, int fw, bool d1xHeightOdd = false, bool d1xClip = false); void hflip (Imagefloat* im); void vflip (Imagefloat* im); From 23db45b3a24f3830bcaba6dd8d82eb6193012b6d Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 7 Feb 2016 00:27:19 +0100 Subject: [PATCH 2/4] Moved some helper functions to anonymous namespace and did some further cleanups --- rtengine/rawimagesource.cc | 762 ++++++++++++++++++++----------------- rtengine/rawimagesource.h | 12 - 2 files changed, 409 insertions(+), 365 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 702003ce8..d6413d563 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -25,13 +25,10 @@ #include "median.h" #include "rawimage.h" #include "mytime.h" -#include "iccmatrices.h" #include "iccstore.h" -#include "image8.h" #include "curves.h" #include "dfmanager.h" #include "ffmanager.h" -#include "../rtgui/options.h" #include "dcp.h" #include "rt_math.h" #include "improcfun.h" @@ -39,11 +36,375 @@ #include #endif #include "opthelper.h" -#include "StopWatch.h" #define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) #undef CLIPD #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) +namespace +{ + +void rotateLine (const float* const line, rtengine::PlanarPtr &channel, const int tran, const int i, const int w, const int h) +{ + switch(tran & TR_ROT) { + case TR_R180: + for (int j = 0; j < w; j++) { + channel(h - 1 - i, w - 1 - j) = line[j]; + } + + break; + + case TR_R90: + for (int j = 0; j < w; j++) { + channel(j, h - 1 - i) = line[j]; + } + + break; + + case TR_R270: + for (int j = 0; j < w; j++) { + channel(w - 1 - j, i) = line[j]; + } + + break; + + case TR_NONE: + for (int j = 0; j < w; j++) { + channel(i, j) = line[j]; + } + } +} + +void transLineStandard (const float* const red, const float* const green, const float* const blue, const int i, rtengine::Imagefloat* const image, const int tran, const int imwidth, const int imheight) +{ + // conventional CCD coarse rotation + rotateLine (red, image->r, tran, i, imwidth, imheight); + rotateLine (green, image->g, tran, i, imwidth, imheight); + rotateLine (blue, image->b, tran, i, imwidth, imheight); +} + +void transLineFuji (const float* const red, const float* const green, const float* const blue, const int i, rtengine::Imagefloat* const image, const int tran, const int imwidth, const int imheight, const int fw) +{ + + // Fuji SuperCCD rotation + coarse rotation + int start = ABS(fw - i); + int w = fw * 2 + 1; + int h = (imheight - fw) * 2 + 1; + int end = min(h + fw - i, w - fw + i); + + switch(tran & TR_ROT) { + case TR_R180: + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && y < image->height && y >= 0 && x < image->width) { + image->r(image->height - 1 - y, image->width - 1 - x) = red[j]; + image->g(image->height - 1 - y, image->width - 1 - x) = green[j]; + image->b(image->height - 1 - y, image->width - 1 - x) = blue[j]; + } + } + + break; + + case TR_R270: + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && x < image->height && y >= 0 && y < image->width) { + image->r(image->height - 1 - x, y) = red[j]; + image->g(image->height - 1 - x, y) = green[j]; + image->b(image->height - 1 - x, y) = blue[j]; + } + } + + break; + + case TR_R90: + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && y < image->width && y >= 0 && x < image->height) { + image->r(x, image->width - 1 - y) = red[j]; + image->g(x, image->width - 1 - y) = green[j]; + image->b(x, image->width - 1 - y) = blue[j]; + } + } + + break; + + case TR_NONE: + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && y < image->height && y >= 0 && x < image->width) { + image->r(y, x) = red[j]; + image->g(y, x) = green[j]; + image->b(y, x) = blue[j]; + } + } + } +} + +void transLineD1x (const float* const red, const float* const green, const float* const blue, const int i, rtengine::Imagefloat* const image, const int tran, const int imwidth, const int imheight, const bool oddHeight, const bool clip) +{ + // Nikon D1X has an uncommon sensor with 4028 x 1324 sensels. + // Vertical sensel size is 2x horizontal sensel size + // We have to do vertical interpolation for the 'missing' rows + // We do that in combination with coarse rotation + + switch(tran & TR_ROT) { + case TR_R180: // rotate 180 degree + for (int j = 0; j < imwidth; j++) { + image->r(2 * (imheight - 1 - i), imwidth - 1 - j) = red[j]; + image->g(2 * (imheight - 1 - i), imwidth - 1 - j) = green[j]; + image->b(2 * (imheight - 1 - i), imwidth - 1 - j) = blue[j]; + } + + if (i == 0) { + for (int j = 0; j < imwidth; j++) { + image->r(2 * imheight - 1, imwidth - 1 - j) = red[j]; + image->g(2 * imheight - 1, imwidth - 1 - j) = green[j]; + image->b(2 * imheight - 1, imwidth - 1 - j) = blue[j]; + } + } + + if (i == 1 || i == 2) { // linear interpolation + int row = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; + image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; + } + + if(i == 2 && oddHeight) { + int row = 2 * imheight; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row - 2, col)) / 2; + image->g(row, col) = (green[j] + image->g(row - 2, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row - 2, col)) / 2; + } + } + } else if (i == imheight - 1 || i == imheight - 2) { + int row = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; + image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; + } + + row = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; + image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; + } + } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolation + int row = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = MAX(0.f, -0.0625f * (red[j] + image->r(row + 3, col)) + 0.5625f * (image->r(row - 1, col) + image->r(row + 1, col))); + image->g(row, col) = MAX(0.f, -0.0625f * (green[j] + image->g(row + 3, col)) + 0.5625f * (image->g(row - 1, col) + image->g(row + 1, col))); + image->b(row, col) = MAX(0.f, -0.0625f * (blue[j] + image->b(row + 3, col)) + 0.5625f * (image->b(row - 1, col) + image->b(row + 1, col))); + + if(clip) { + image->r(row, col) = MIN(image->r(row, col), rtengine::MAXVALF); + image->g(row, col) = MIN(image->g(row, col), rtengine::MAXVALF); + image->b(row, col) = MIN(image->b(row, col), rtengine::MAXVALF); + } + } + } + + break; + + case TR_R90: // rotate right + if( i == 0) { + for (int j = 0; j < imwidth; j++) { + image->r(j, 2 * imheight - 1) = red[j]; + image->g(j, 2 * imheight - 1) = green[j]; + image->b(j, 2 * imheight - 1) = blue[j]; + } + } + + for (int j = 0; j < imwidth; j++) { + image->r(j, 2 * (imheight - 1 - i)) = red[j]; + image->g(j, 2 * (imheight - 1 - i)) = green[j]; + image->b(j, 2 * (imheight - 1 - i)) = blue[j]; + } + + if (i == 1 || i == 2) { // linear interpolation + int col = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; + image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; + image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + + if(oddHeight && i == 2) { + image->r(j, 2 * imheight) = (red[j] + image->r(j, 2 * imheight - 2)) / 2; + image->g(j, 2 * imheight) = (green[j] + image->g(j, 2 * imheight - 2)) / 2; + image->b(j, 2 * imheight) = (blue[j] + image->b(j, 2 * imheight - 2)) / 2; + } + } + } else if (i == imheight - 1) { + int col = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; + image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; + image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + } + + col = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; + image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; + image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + } + } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolation + int col = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = MAX(0.f, -0.0625f * (red[j] + image->r(j, col + 3)) + 0.5625f * (image->r(j, col - 1) + image->r(j, col + 1))); + image->g(j, col) = MAX(0.f, -0.0625f * (green[j] + image->g(j, col + 3)) + 0.5625f * (image->g(j, col - 1) + image->g(j, col + 1))); + image->b(j, col) = MAX(0.f, -0.0625f * (blue[j] + image->b(j, col + 3)) + 0.5625f * (image->b(j, col - 1) + image->b(j, col + 1))); + + if(clip) { + image->r(j, col) = MIN(image->r(j, col), rtengine::MAXVALF); + image->g(j, col) = MIN(image->g(j, col), rtengine::MAXVALF); + image->b(j, col) = MIN(image->b(j, col), rtengine::MAXVALF); + } + } + } + + break; + + case TR_R270: // rotate left + if (i == 0) { + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i) = red[j]; + image->g(row, 2 * i) = green[j]; + image->b(row, 2 * i) = blue[j]; + } + } else if (i == 1 || i == 2) { // linear interpolation + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i) = red[j]; + image->g(row, 2 * i) = green[j]; + image->b(row, 2 * i) = blue[j]; + image->r(row, 2 * i - 1) = (red[j] + image->r(row, 2 * i - 2)) * 0.5f; + image->g(row, 2 * i - 1) = (green[j] + image->g(row, 2 * i - 2)) * 0.5f; + image->b(row, 2 * i - 1) = (blue[j] + image->b(row, 2 * i - 2)) * 0.5f; + } + } else if (i > 0 && i < imheight) { // vertical bicubic interpolation + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i - 3) = MAX(0.f, -0.0625f * (red[j] + image->r(row, 2 * i - 6)) + 0.5625f * (image->r(row, 2 * i - 2) + image->r(row, 2 * i - 4))); + image->g(row, 2 * i - 3) = MAX(0.f, -0.0625f * (green[j] + image->g(row, 2 * i - 6)) + 0.5625f * (image->g(row, 2 * i - 2) + image->g(row, 2 * i - 4))); + image->b(row, 2 * i - 3) = MAX(0.f, -0.0625f * (blue[j] + image->b(row, 2 * i - 6)) + 0.5625f * (image->b(row, 2 * i - 2) + image->b(row, 2 * i - 4))); + + if(clip) { + image->r(row, 2 * i - 3) = MIN(image->r(row, 2 * i - 3), rtengine::MAXVALF); + image->g(row, 2 * i - 3) = MIN(image->g(row, 2 * i - 3), rtengine::MAXVALF); + image->b(row, 2 * i - 3) = MIN(image->b(row, 2 * i - 3), rtengine::MAXVALF); + } + + image->r(row, 2 * i) = red[j]; + image->g(row, 2 * i) = green[j]; + image->b(row, 2 * i) = blue[j]; + } + } + + if (i == imheight - 1) { + for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { + image->r(row, 2 * i - 1) = MAX(0.f, -0.0625f * (red[j] + image->r(row, 2 * i - 4)) + 0.5625f * (image->r(row, 2 * i) + image->r(row, 2 * i - 2))); + image->g(row, 2 * i - 1) = MAX(0.f, -0.0625f * (green[j] + image->g(row, 2 * i - 4)) + 0.5625f * (image->g(row, 2 * i) + image->g(row, 2 * i - 2))); + image->b(row, 2 * i - 1) = MAX(0.f, -0.0625f * (blue[j] + image->b(row, 2 * i - 4)) + 0.5625f * (image->b(row, 2 * i) + image->b(row, 2 * i - 2))); + + if(clip) { + image->r(j, 2 * i - 1) = MIN(image->r(j, 2 * i - 1), rtengine::MAXVALF); + image->g(j, 2 * i - 1) = MIN(image->g(j, 2 * i - 1), rtengine::MAXVALF); + image->b(j, 2 * i - 1) = MIN(image->b(j, 2 * i - 1), rtengine::MAXVALF); + } + + image->r(row, 2 * i + 1) = (red[j] + image->r(row, 2 * i - 1)) / 2; + image->g(row, 2 * i + 1) = (green[j] + image->g(row, 2 * i - 1)) / 2; + image->b(row, 2 * i + 1) = (blue[j] + image->b(row, 2 * i - 1)) / 2; + + if (oddHeight) { + image->r(row, 2 * i + 2) = (red[j] + image->r(row, 2 * i - 2)) / 2; + image->g(row, 2 * i + 2) = (green[j] + image->g(row, 2 * i - 2)) / 2; + image->b(row, 2 * i + 2) = (blue[j] + image->b(row, 2 * i - 2)) / 2; + } + } + } + + break; + + case TR_NONE: // no coarse rotation + rotateLine (red, image->r, tran, 2 * i, imwidth, imheight); + rotateLine (green, image->g, tran, 2 * i, imwidth, imheight); + rotateLine (blue, image->b, tran, 2 * i, imwidth, imheight); + + if (i == 1 || i == 2) { // linear interpolation + for (int j = 0; j < imwidth; j++) { + image->r(2 * i - 1, j) = (red[j] + image->r(2 * i - 2, j)) / 2; + image->g(2 * i - 1, j) = (green[j] + image->g(2 * i - 2, j)) / 2; + image->b(2 * i - 1, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; + } + } else if (i > 2 && i < imheight) { // vertical bicubic interpolation + for (int j = 0; j < imwidth; j++) { + image->r(2 * i - 3, j) = MAX(0.f, -0.0625f * (red[j] + image->r(2 * i - 6, j)) + 0.5625f * (image->r(2 * i - 2, j) + image->r(2 * i - 4, j))); + image->g(2 * i - 3, j) = MAX(0.f, -0.0625f * (green[j] + image->g(2 * i - 6, j)) + 0.5625f * (image->g(2 * i - 2, j) + image->g(2 * i - 4, j))); + image->b(2 * i - 3, j) = MAX(0.f, -0.0625f * (blue[j] + image->b(2 * i - 6, j)) + 0.5625f * (image->b(2 * i - 2, j) + image->b(2 * i - 4, j))); + + if(clip) { + image->r(2 * i - 3, j) = MIN(image->r(2 * i - 3, j), rtengine::MAXVALF); + image->g(2 * i - 3, j) = MIN(image->g(2 * i - 3, j), rtengine::MAXVALF); + image->b(2 * i - 3, j) = MIN(image->b(2 * i - 3, j), rtengine::MAXVALF); + } + } + } + + if (i == imheight - 1) { + for (int j = 0; j < imwidth; j++) { + image->r(2 * i - 1, j) = MAX(0.f, -0.0625f * (red[j] + image->r(2 * i - 4, j)) + 0.5625f * (image->r(2 * i, j) + image->r(2 * i - 2, j))); + image->g(2 * i - 1, j) = MAX(0.f, -0.0625f * (green[j] + image->g(2 * i - 4, j)) + 0.5625f * (image->g(2 * i, j) + image->g(2 * i - 2, j))); + image->b(2 * i - 1, j) = MAX(0.f, -0.0625f * (blue[j] + image->b(2 * i - 4, j)) + 0.5625f * (image->b(2 * i, j) + image->b(2 * i - 2, j))); + + if(clip) { + image->r(2 * i - 1, j) = MIN(image->r(2 * i - 1, j), rtengine::MAXVALF); + image->g(2 * i - 1, j) = MIN(image->g(2 * i - 1, j), rtengine::MAXVALF); + image->b(2 * i - 1, j) = MIN(image->b(2 * i - 1, j), rtengine::MAXVALF); + } + + image->r(2 * i + 1, j) = (red[j] + image->r(2 * i - 1, j)) / 2; + image->g(2 * i + 1, j) = (green[j] + image->g(2 * i - 1, j)) / 2; + image->b(2 * i + 1, j) = (blue[j] + image->b(2 * i - 1, j)) / 2; + + if (oddHeight) { + image->r(2 * i + 2, j) = (red[j] + image->r(2 * i - 2, j)) / 2; + image->g(2 * i + 2, j) = (green[j] + image->g(2 * i - 2, j)) / 2; + image->b(2 * i + 2, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; + } + } + } + } +} + +} + + namespace rtengine { @@ -323,8 +684,12 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre } if (d1x) { + // D1X has only half of the required rows + // we interpolate the missing ones later to get correct aspect ratio + // if the height is odd we also have to add an additional row to avoid a black line d1xHeightOdd = maximheight & 1; maximheight /= 2; + imheight = maximheight; } // correct if overflow (very rare), but not fuji because it is corrected in transline @@ -342,9 +707,9 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre hlmax[0] = clmax[0] * rm; hlmax[1] = clmax[1] * gm; hlmax[2] = clmax[2] * bm; - const bool has_clipping = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]); - //if (sx1+skip*imwidth>maxx) imwidth --; // very hard to fix this situation without an 'if' in the loop. + const bool doClip = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]) && !hrp.hrenabled; + float area = skip * skip; rm /= area; gm /= area; @@ -355,17 +720,15 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre { #endif // render the requested image part - float* line_red = new float[imwidth]; - float* line_grn = new float[imwidth]; - float* line_blue = new float[imwidth]; - //printf("clip[0]=%f clip[1]=%f clip[2]=%f\n",hlmax[0],hlmax[1],hlmax[2]); - + float line_red[imwidth] ALIGNED16; + float line_grn[imwidth] ALIGNED16; + float line_blue[imwidth] ALIGNED16; #ifdef _OPENMP #pragma omp for #endif - for (int ix = 0; ix < (d1x ? maximheight : imheight); ix++) { + for (int ix = 0; ix < imheight; ix++) { int i = sy1 + skip * ix; if (i >= maxy - skip) { @@ -374,12 +737,9 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) { for (int j = 0, jx = sx1; j < imwidth; j++, jx += skip) { - if (jx >= maxx - skip) { - jx = maxx - skip - 1; // avoid trouble - } + jx = jx >= (maxx - skip) ? jx = maxx - skip - 1 : jx; // avoid trouble - float rtot, gtot, btot; - rtot = gtot = btot = 0; + float rtot = 0.f, gtot = 0.f, btot = 0.f; for (int m = 0; m < skip; m++) for (int n = 0; n < skip; n++) { @@ -392,7 +752,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre gtot *= gm; btot *= bm; - if (!hrp.hrenabled && has_clipping) { + if (doClip) { // note: as hlmax[] can be larger than CLIP and we can later apply negative // exposure this means that we can clip away local highlights which actually // are not clipped. We have to do that though as we only check pixel by pixel @@ -427,7 +787,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre gtot *= gm; btot *= bm; - if (!hrp.hrenabled && has_clipping) { + if (doClip) { rtot = CLIP(rtot); gtot = CLIP(gtot); btot = CLIP(btot); @@ -445,13 +805,16 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip, raw, hlmax); } - transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, d1x ? maximheight : imheight, fw, d1xHeightOdd, !hrp.hrenabled && has_clipping); + if(d1x) { + transLineD1x (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, d1xHeightOdd, doClip); + } else if(fuji) { + transLineFuji (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, fw); + } else { + transLineStandard (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight); + } } - delete [] line_red; - delete [] line_grn; - delete [] line_blue; #ifdef _OPENMP } #endif @@ -504,8 +867,6 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre } } - - // Flip if needed if (tran & TR_HFLIP) { hflip (image); @@ -515,11 +876,14 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre vflip (image); } - // Color correction (only when running on full resolution) - if (ri->getSensorType() != ST_NONE && pp.skip == 1) { - if (ri->getSensorType() == ST_BAYER) { + // Colour correction (only when running on full resolution) + if(pp.skip == 1) { + switch(ri->getSensorType()) { + case ST_BAYER: processFalseColorCorrection (image, raw.bayersensor.ccSteps); - } else if (ri->getSensorType() == ST_FUJI_XTRANS) { + break; + + case ST_FUJI_XTRANS: processFalseColorCorrection (image, raw.xtranssensor.ccSteps); } } @@ -548,7 +912,7 @@ void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* interpolateBadPixelsBayer: correct raw pixels looking at the bitmap - * takes into consideration if there are multiple bad pixels in the neighborhood + * takes into consideration if there are multiple bad pixels in the neighbourhood */ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) { @@ -575,8 +939,8 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) // diagonal interpolation if(FC(row, col) == 1) { - // green channel. We can use closer pixels than for red or blue channel. Distance to center pixel is sqrt(2) => weighting is 0.70710678 - // For green channel following pixels will be used for interpolation. Pixel to be interpolated is in center. + // green channel. We can use closer pixels than for red or blue channel. Distance to centre pixel is sqrt(2) => weighting is 0.70710678 + // For green channel following pixels will be used for interpolation. Pixel to be interpolated is in centre. // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad // 0 0 0 0 0 // 0 1 0 1 0 @@ -593,8 +957,8 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) norm += dirwt; } } else { - // red and blue channel. Distance to center pixel is sqrt(8) => weighting is 0.35355339 - // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center. + // red and blue channel. Distance to centre pixel is sqrt(8) => weighting is 0.35355339 + // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in centre. // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad // 1 0 0 0 1 // 0 0 0 0 0 @@ -612,8 +976,8 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) } } - // channel independent. Distance to center pixel is 2 => weighting is 0.5 - // Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in center. + // channel independent. Distance to centre pixel is 2 => weighting is 0.5 + // Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in centre. // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad // 0 0 1 0 0 // 0 0 0 0 0 @@ -635,7 +999,7 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) norm += dirwt; } - if (LIKELY(norm > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% + if (LIKELY(norm > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999% rawData[row][col] = wtdsum / (2.f * norm); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps counter++; } else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens @@ -665,7 +1029,7 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) } /* interpolateBadPixels3Colours: correct raw pixels looking at the bitmap - * takes into consideration if there are multiple bad pixels in the neighborhood + * takes into consideration if there are multiple bad pixels in the neighbourhood */ int RawImageSource::interpolateBadPixelsNColours( PixelsMap &bitmapBads, const int colours ) { @@ -1078,318 +1442,6 @@ SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thres return counter; } -void RawImageSource::rotateLine (const float* const line, PlanarPtr &channel, const int tran, const int i, const int w, const int h) -{ - - if ((tran & TR_ROT) == TR_R180) - for (int j = 0; j < w; j++) { - channel(h - 1 - i, w - 1 - j) = line[j]; - } - - else if ((tran & TR_ROT) == TR_R90) - for (int j = 0; j < w; j++) { - channel(j, h - 1 - i) = line[j]; - } - - else if ((tran & TR_ROT) == TR_R270) - for (int j = 0, cj = w - 1; j < w; j++, cj--) { - channel(cj, i) = line[j]; - } - else - for (int j = 0; j < w; j++) { - channel(i, j) = line[j]; - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imwidth, int imheight, int fw, bool d1xHeightOdd, bool d1xClip) -{ - - // Fuji SuperCCD rotation + coarse rotation - if (fuji) { - int start = ABS(fw - i); - int w = fw * 2 + 1; - int h = (imheight - fw) * 2 + 1; - - if ((tran & TR_ROT) == TR_R180) { - int end = min(h + fw - i, w - fw + i); - - for (int j = start; j < end; j++) { - int y = i + j - fw; - int x = fw - i + j; - - if (x >= 0 && y < image->height && y >= 0 && x < image->width) { - image->r(image->height - 1 - y, image->width - 1 - x) = red[j]; - image->g(image->height - 1 - y, image->width - 1 - x) = green[j]; - image->b(image->height - 1 - y, image->width - 1 - x) = blue[j]; - } - } - } else if ((tran & TR_ROT) == TR_R270) { - int end = min(h + fw - i, w - fw + i); - - for (int j = start; j < end; j++) { - int y = i + j - fw; - int x = fw - i + j; - - if (x >= 0 && x < image->height && y >= 0 && y < image->width) { - image->r(image->height - 1 - x, y) = red[j]; - image->g(image->height - 1 - x, y) = green[j]; - image->b(image->height - 1 - x, y) = blue[j]; - } - } - } else if ((tran & TR_ROT) == TR_R90) { - int end = min(h + fw - i, w - fw + i); - - for (int j = start; j < end; j++) { - int y = i + j - fw; - int x = fw - i + j; - - if (x >= 0 && y < image->width && y >= 0 && x < image->height) { - image->r(x, image->width - 1 - y) = red[j]; - image->g(x, image->width - 1 - y) = green[j]; - image->b(x, image->width - 1 - y) = blue[j]; - } - } - } else { - int end = min(h + fw - i, w - fw + i); - - for (int j = start; j < end; j++) { - int y = i + j - fw; - int x = fw - i + j; - - if (x >= 0 && y < image->height && y >= 0 && x < image->width) { - image->r(y, x) = red[j]; - image->g(y, x) = green[j]; - image->b(y, x) = blue[j]; - } - } - } - } - // Nikon D1X vertical interpolation + coarse rotation - else if (d1x) { - // copy new pixels - if ((tran & TR_ROT) == TR_R180) { // rotate 2 times left or two times right - for (int j = 0; j < imwidth; j++) { - image->r(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = red[j]; - image->g(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = green[j]; - image->b(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = blue[j]; - } - if (i == 0) { - for (int j = 0; j < imwidth; j++) { - image->r(2 * imheight - 1, imwidth - 1 - j) = red[j]; - image->g(2 * imheight - 1, imwidth - 1 - j) = green[j]; - image->b(2 * imheight - 1, imwidth - 1 - j) = blue[j]; - } - } - if (i == 1 || i == 2) { // linear interpolation - int row = 2 * imheight - 1 - 2 * i; - - for (int j = 0; j < imwidth; j++) { - int col = imwidth - 1 - j; - image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; - image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; - image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; - } - if(i == 2 && d1xHeightOdd) { - int row = 2 * imheight; - for (int j = 0; j < imwidth; j++) { - int col = imwidth - 1 - j; - image->r(row, col) = (red[j] + image->r(row - 2, col)) / 2; - image->g(row, col) = (green[j] + image->g(row - 2, col)) / 2; - image->b(row, col) = (blue[j] + image->b(row - 2, col)) / 2; - } - } - } else if (i == imheight - 1 || i == imheight - 2) { - int row = 2 * imheight - 1 - 2 * i; - - for (int j = 0; j < imwidth; j++) { - int col = imwidth - 1 - j; - image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; - image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; - image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; - } - - row = 2 * imheight - 1 - 2 * i + 2; - - for (int j = 0; j < imwidth; j++) { - int col = imwidth - 1 - j; - image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; - image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; - image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; - } - } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolation - int row = 2 * imheight - 1 - 2 * i + 2; - - for (int j = 0; j < imwidth; j++) { - int col = imwidth - 1 - j; - image->r(row, col) = MAX(0.f, -0.0625f * (red[j] + image->r(row + 3, col)) + 0.5625f * (image->r(row - 1, col) + image->r(row + 1, col))); - image->g(row, col) = MAX(0.f, -0.0625f * (green[j] + image->g(row + 3, col)) + 0.5625f * (image->g(row - 1, col) + image->g(row + 1, col))); - image->b(row, col) = MAX(0.f, -0.0625f * (blue[j] + image->b(row + 3, col)) + 0.5625f * (image->b(row - 1, col) + image->b(row + 1, col))); - if(d1xClip) { - image->r(row, col) = MIN(image->r(row, col), MAXVALF); - image->g(row, col) = MIN(image->g(row, col), MAXVALF); - image->b(row, col) = MIN(image->b(row, col), MAXVALF); - } - } - } - } else if ((tran & TR_ROT) == TR_R90) { // rotate right - if( i == 0) { - for (int j = 0; j < imwidth; j++) { - image->r(j, 2 * imheight - 1) = red[j]; - image->g(j, 2 * imheight - 1) = green[j]; - image->b(j, 2 * imheight - 1) = blue[j]; - } - } - for (int j = 0; j < imwidth; j++) { - image->r(j, 2 * imheight - 2 - 2 * i) = red[j]; - image->g(j, 2 * imheight - 2 - 2 * i) = green[j]; - image->b(j, 2 * imheight - 2 - 2 * i) = blue[j]; - } - - if (i == 1 || i == 2) { // linear interpolation - int col = 2 * imheight - 1 - 2 * i; - - for (int j = 0; j < imwidth; j++) { - image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; - image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; - image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; - if(d1xHeightOdd && i == 2) { - image->r(j, 2 * imheight) = (red[j] + image->r(j, 2 * imheight - 2)) / 2; - image->g(j, 2 * imheight) = (green[j] + image->g(j, 2 * imheight - 2)) / 2; - image->b(j, 2 * imheight) = (blue[j] + image->b(j, 2 * imheight - 2)) / 2; - } - } - } else if (i == imheight - 1) { - int col = 2 * imheight - 1 - 2 * i; - - for (int j = 0; j < imwidth; j++) { - image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; - image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; - image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; - } - col = 2 * imheight - 1 - 2 * i + 2; - for (int j = 0; j < imwidth; j++) { - image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; - image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; - image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; - } - } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolation - int col = 2 * imheight - 1 - 2 * i + 2; - - for (int j = 0; j < imwidth; j++) { - image->r(j, col) = MAX(0.f, -0.0625f * (red[j] + image->r(j, col + 3)) + 0.5625f * (image->r(j, col - 1) + image->r(j, col + 1))); - image->g(j, col) = MAX(0.f, -0.0625f * (green[j] + image->g(j, col + 3)) + 0.5625f * (image->g(j, col - 1) + image->g(j, col + 1))); - image->b(j, col) = MAX(0.f, -0.0625f * (blue[j] + image->b(j, col + 3)) + 0.5625f * (image->b(j, col - 1) + image->b(j, col + 1))); - if(d1xClip) { - image->r(j, col) = MIN(image->r(j, col), MAXVALF); - image->g(j, col) = MIN(image->g(j, col), MAXVALF); - image->b(j, col) = MIN(image->b(j, col), MAXVALF); - } - } - } - } else if ((tran & TR_ROT) == TR_R270) { // rotate left - if (i == 0) { - for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { - image->r(row, 2 * i) = red[j]; - image->g(row, 2 * i) = green[j]; - image->b(row, 2 * i) = blue[j]; - } - } else if (i == 1 || i == 2) { // linear interpolation - for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { - image->r(row, 2 * i) = red[j]; - image->g(row, 2 * i) = green[j]; - image->b(row, 2 * i) = blue[j]; - image->r(row, 2 * i - 1) = (red[j] + image->r(row, 2 * i - 2)) * 0.5f; - image->g(row, 2 * i - 1) = (green[j] + image->g(row, 2 * i - 2)) * 0.5f; - image->b(row, 2 * i - 1) = (blue[j] + image->b(row, 2 * i - 2)) * 0.5f; - } - } else if (i > 0 && i < imheight) { // vertical bicubic interpolation - for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { - image->r(row, 2 * i - 3) = MAX(0.f, -0.0625f * (red[j] + image->r(row, 2 * i - 6)) + 0.5625f * (image->r(row, 2 * i - 2) + image->r(row, 2 * i - 4))); - image->g(row, 2 * i - 3) = MAX(0.f, -0.0625f * (green[j] + image->g(row, 2 * i - 6)) + 0.5625f * (image->g(row, 2 * i - 2) + image->g(row, 2 * i - 4))); - image->b(row, 2 * i - 3) = MAX(0.f, -0.0625f * (blue[j] + image->b(row, 2 * i - 6)) + 0.5625f * (image->b(row, 2 * i - 2) + image->b(row, 2 * i - 4))); - if(d1xClip) { - image->r(row, 2 * i - 3) = MIN(image->r(row, 2 * i - 3), MAXVALF); - image->g(row, 2 * i - 3) = MIN(image->g(row, 2 * i - 3), MAXVALF); - image->b(row, 2 * i - 3) = MIN(image->b(row, 2 * i - 3), MAXVALF); - } - image->r(row, 2 * i) = red[j]; - image->g(row, 2 * i) = green[j]; - image->b(row, 2 * i) = blue[j]; - } - } - if (i == imheight - 1) { - for (int j = imwidth - 1, row = 0; j >= 0; j--, row++) { - image->r(row, 2 * i - 1) = MAX(0.f, -0.0625f * (red[j] + image->r(row, 2 * i - 4)) + 0.5625f * (image->r(row, 2 * i) + image->r(row, 2 * i - 2))); - image->g(row, 2 * i - 1) = MAX(0.f, -0.0625f * (green[j] + image->g(row, 2 * i - 4)) + 0.5625f * (image->g(row, 2 * i) + image->g(row, 2 * i - 2))); - image->b(row, 2 * i - 1) = MAX(0.f, -0.0625f * (blue[j] + image->b(row, 2 * i - 4)) + 0.5625f * (image->b(row, 2 * i) + image->b(row, 2 * i - 2))); - if(d1xClip) { - image->r(j, 2 * i - 1) = MIN(image->r(j, 2 * i - 1), MAXVALF); - image->g(j, 2 * i - 1) = MIN(image->g(j, 2 * i - 1), MAXVALF); - image->b(j, 2 * i - 1) = MIN(image->b(j, 2 * i - 1), MAXVALF); - } - image->r(row, 2 * i + 1) = (red[j] + image->r(row, 2 * i - 1)) / 2; - image->g(row, 2 * i + 1) = (green[j] + image->g(row, 2 * i - 1)) / 2; - image->b(row, 2 * i + 1) = (blue[j] + image->b(row, 2 * i - 1)) / 2; - if (d1xHeightOdd) { - image->r(row, 2 * i + 2) = (red[j] + image->r(row, 2 * i - 2)) / 2; - image->g(row, 2 * i + 2) = (green[j] + image->g(row, 2 * i - 2)) / 2; - image->b(row, 2 * i + 2) = (blue[j] + image->b(row, 2 * i - 2)) / 2; - } - } - } - } else { // no coarse rotation - rotateLine (red, image->r, tran, 2 * i, imwidth, imheight); - rotateLine (green, image->g, tran, 2 * i, imwidth, imheight); - rotateLine (blue, image->b, tran, 2 * i, imwidth, imheight); - if (i == 1 || i == 2) { // linear interpolation - for (int j = 0; j < imwidth; j++) { - image->r(2 * i - 1, j) = (red[j] + image->r(2 * i - 2, j)) / 2; - image->g(2 * i - 1, j) = (green[j] + image->g(2 * i - 2, j)) / 2; - image->b(2 * i - 1, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; - } - } else if (i > 2 && i < imheight) { // vertical bicubic interpolation - for (int j = 0; j < imwidth; j++) { - image->r(2 * i - 3, j) = MAX(0.f, -0.0625f * (red[j] + image->r(2 * i - 6, j)) + 0.5625f * (image->r(2 * i - 2, j) + image->r(2 * i - 4, j))); - image->g(2 * i - 3, j) = MAX(0.f, -0.0625f * (green[j] + image->g(2 * i - 6, j)) + 0.5625f * (image->g(2 * i - 2, j) + image->g(2 * i - 4, j))); - image->b(2 * i - 3, j) = MAX(0.f, -0.0625f * (blue[j] + image->b(2 * i - 6, j)) + 0.5625f * (image->b(2 * i - 2, j) + image->b(2 * i - 4, j))); - if(d1xClip) { - image->r(2 * i - 3, j) = MIN(image->r(2 * i - 3, j), MAXVALF); - image->g(2 * i - 3, j) = MIN(image->g(2 * i - 3, j), MAXVALF); - image->b(2 * i - 3, j) = MIN(image->b(2 * i - 3, j), MAXVALF); - } - } - } if (i == imheight - 1) { - for (int j = 0; j < imwidth; j++) { - image->r(2 * i - 1, j) = MAX(0.f, -0.0625f * (red[j] + image->r(2 * i - 4, j)) + 0.5625f * (image->r(2 * i, j) + image->r(2 * i - 2, j))); - image->g(2 * i - 1, j) = MAX(0.f, -0.0625f * (green[j] + image->g(2 * i - 4, j)) + 0.5625f * (image->g(2 * i, j) + image->g(2 * i - 2, j))); - image->b(2 * i - 1, j) = MAX(0.f, -0.0625f * (blue[j] + image->b(2 * i - 4, j)) + 0.5625f * (image->b(2 * i, j) + image->b(2 * i - 2, j))); - if(d1xClip) { - image->r(2 * i - 1, j) = MIN(image->r(2 * i - 1, j), MAXVALF); - image->g(2 * i - 1, j) = MIN(image->g(2 * i - 1, j), MAXVALF); - image->b(2 * i - 1, j) = MIN(image->b(2 * i - 1, j), MAXVALF); - } - image->r(2 * i + 1, j) = (red[j] + image->r(2 * i - 1, j)) / 2; - image->g(2 * i + 1, j) = (green[j] + image->g(2 * i - 1, j)) / 2; - image->b(2 * i + 1, j) = (blue[j] + image->b(2 * i - 1, j)) / 2; - if (d1xHeightOdd) { - image->r(2 * i + 2, j) = (red[j] + image->r(2 * i - 2, j)) / 2; - image->g(2 * i + 2, j) = (green[j] + image->g(2 * i - 2, j)) / 2; - image->b(2 * i + 2, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; - } - } - } - } - } // if nikon dx1 - // other (conventional) CCD coarse rotation - else { - rotateLine (red, image->r, tran, i, imwidth, imheight); - rotateLine (green, image->g, tran, i, imwidth, imheight); - rotateLine (blue, image->b, tran, i, imwidth, imheight); - } -} - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void RawImageSource::getFullSize (int& w, int& h, int tr) @@ -2172,6 +2224,7 @@ void RawImageSource::retinexPrepareCurves(RetinexParams retinexParams, LUTf &cdc } else { CurveFactory::curveDehaContL (retinexcontlutili, retinexParams.cdcurve, cdcurve, 1, lhist16RETI, histLRETI); } + CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI); retinexParams.getCurves(retinextransmissionCurve); @@ -2498,6 +2551,7 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC } } } + rgbSourceModified = false; // tricky handling for Color propagation t5.set(); @@ -2804,8 +2858,9 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw { // TODO: Change type of black[] to float to avoid conversions unsigned short black[4] = { - (unsigned short)ri->get_cblack(0), (unsigned short)ri->get_cblack(1), - (unsigned short)ri->get_cblack(2), (unsigned short)ri->get_cblack(3)}; + (unsigned short)ri->get_cblack(0), (unsigned short)ri->get_cblack(1), + (unsigned short)ri->get_cblack(2), (unsigned short)ri->get_cblack(3) + }; if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) { if (!rawData) { @@ -4281,7 +4336,8 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU const float mult[4] = { 65535.0f / ri->get_white(0), 65535.0f / ri->get_white(1), 65535.0f / ri->get_white(2), - 65535.0f / ri->get_white(3) }; + 65535.0f / ri->get_white(3) + }; #ifdef _OPENMP int numThreads; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 06fc341a3..a1bac4363 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -59,7 +59,6 @@ template void freeArray (T** a, int H) template void freeArray2 (T** a, int H) { - //for (int i=0; i &channel, const int tran, const int i, const int w, const int h); void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); void transformPosition (int x, int y, int tran, int& tx, int& ty); @@ -151,7 +149,6 @@ public: int load (Glib::ustring fname, bool batch = false); void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse); void demosaic (const RAWParams &raw); -// void retinex (RAWParams raw, ColorManagementParams cmp, RetinexParams lcur, LUTf & cdcurve, bool dehacontlutili); void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); void retinexPrepareCurves (RetinexParams retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI); void retinexPrepareBuffers (ColorManagementParams cmp, RetinexParams retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI); @@ -231,13 +228,7 @@ public: void boxblur2(float** src, float** dst, float** temp, int H, int W, int box ); void boxblur_resamp(float **src, float **dst, float** temp, int H, int W, int box, int samp ); void MSR(float** luminance, float **originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); -// void MSR(LabImage* lab, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve); - - //void boxblur_resamp(float **red, float **green, float **blue, int H, int W, float thresh[3], float max[3], - // multi_array2D & hfsize, multi_array2D & hilite, int box ); void HLRecovery_inpaint (float** red, float** green, float** blue); - //void HLRecovery_inpaint (); - static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax); @@ -277,8 +268,6 @@ protected: void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); void lmmse_interpolate_omp(int winw, int winh, int iterations); -// void MSR(LabImage* lab, int width, int height, int skip, const LCurveParams &lcur); - void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); @@ -303,7 +292,6 @@ protected: void xtransborder_interpolate (int border); void xtrans_interpolate (int passes, bool useCieLab); void fast_xtrans_interpolate (); - void transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imw, int imh, int fw, bool d1xHeightOdd = false, bool d1xClip = false); void hflip (Imagefloat* im); void vflip (Imagefloat* im); From 2532a5e27c3961b1480e3b20704a3ffce64b3904 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 7 Feb 2016 00:39:38 +0100 Subject: [PATCH 3/4] Some further cleanup of code (mainly using macros for SSE to increase readability) --- rtengine/rawimagesource.cc | 51 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index d6413d563..78470ecb7 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1408,6 +1408,7 @@ SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thres #ifdef __SSE2__ // sum up 5*4 = 20 values using SSE + // 10 fabs function calls and float 10 additions with SSE vfloat sum = vabsf(LVFU(cfablur[(rr - 2) * W + cc - 2])) + vabsf(LVFU(cfablur[(rr - 1) * W + cc - 2])); sum += vabsf(LVFU(cfablur[(rr) * W + cc - 2])); sum += vabsf(LVFU(cfablur[(rr + 1) * W + cc - 2])); @@ -1421,7 +1422,7 @@ SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thres } #else - + // 25 fabs function calls and 25 float additions without SSE for (int mm = rr - 2; mm <= rr + 2; mm++) { for (int nn = cc - 2; nn <= cc + 2; nn++) { hfnbrave += fabsf(cfablur[mm * W + nn]); @@ -2099,11 +2100,11 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar vfloat H, S, L; int pos; Color::rgb2hsl(LVFU(red[i][j]), LVFU(green[i][j]), LVFU(blue[i][j]), H, S, L); - _mm_storeu_ps(&conversionBuffer[0][i - border][j - border], H); - _mm_storeu_ps(&conversionBuffer[1][i - border][j - border], S); + STVFU(conversionBuffer[0][i - border][j - border], H); + STVFU(conversionBuffer[1][i - border][j - border], S); L *= c32768; - _mm_storeu_ps(&conversionBuffer[2][i - border][j - border], L); - _mm_storeu_ps(&conversionBuffer[3][i - border][j - border], H); + STVFU(conversionBuffer[2][i - border][j - border], L); + STVFU(conversionBuffer[3][i - border][j - border], H); if(lhist16RETI) { for(int p = 0; p < 4; p++) { @@ -2423,9 +2424,9 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC vfloat R, G, B; Color::hsl2rgb(LVFU(conversionBuffer[0][i - border][j - border]), LVFU(conversionBuffer[1][i - border][j - border]), LVFU(LBuffer[i - border][j - border]) / c32768, R, G, B); - _mm_storeu_ps(&red[i][j], R); - _mm_storeu_ps(&green[i][j], G); - _mm_storeu_ps(&blue[i][j], B); + STVFU(red[i][j], R); + STVFU(green[i][j], G); + STVFU(blue[i][j], B); } #endif @@ -2510,9 +2511,9 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC Color::Lab2XYZ(LVFU(LBuffer[i - border][j - border]), LVFU(conversionBuffer[0][i - border][j - border]), LVFU(conversionBuffer[1][i - border][j - border]), x_, y_, z_) ; Color::xyz2rgb(x_, y_, z_, R, G, B, wipv); - _mm_storeu_ps(&red[i][j], R); - _mm_storeu_ps(&green[i][j], G); - _mm_storeu_ps(&blue[i][j], B); + STVFU(red[i][j], R); + STVFU(green[i][j], G); + STVFU(blue[i][j], B); } @@ -3034,9 +3035,9 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur //vertical blur #ifdef __SSE2__ - __m128 leninitv = _mm_set1_ps( (float)((int)(boxH / 2 + 1))); - __m128 onev = _mm_set1_ps( 1.0f ); - __m128 temp1v, temp2v, lenv, lenp1v, lenm1v; + vfloat leninitv = F2V( (float)((int)(boxH / 2 + 1))); + vfloat onev = F2V( 1.0f ); + vfloat temp1v, temp2v, lenv, lenp1v, lenm1v; int row; #ifdef _OPENMP #pragma omp for @@ -3052,29 +3053,29 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur temp2v += LVFU(cfatmp[(i + 1) * W + col]) / lenv; } - _mm_storeu_ps(&cfablur[0 * W + col], temp1v); - _mm_storeu_ps(&cfablur[1 * W + col], temp2v); + STVFU(cfablur[0 * W + col], temp1v); + STVFU(cfablur[1 * W + col], temp2v); for (row = 2; row < boxH + 2; row += 2) { lenp1v = lenv + onev; temp1v = (temp1v * lenv + LVFU(cfatmp[(row + boxH) * W + col])) / lenp1v; temp2v = (temp2v * lenv + LVFU(cfatmp[(row + boxH + 1) * W + col])) / lenp1v; - _mm_storeu_ps( &cfablur[row * W + col], temp1v); - _mm_storeu_ps( &cfablur[(row + 1)*W + col], temp2v); + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[(row + 1)*W + col], temp2v); lenv = lenp1v; } for (; row < H - boxH - 1; row += 2) { temp1v = temp1v + (LVFU(cfatmp[(row + boxH) * W + col]) - LVFU(cfatmp[(row - boxH - 2) * W + col])) / lenv; temp2v = temp2v + (LVFU(cfatmp[(row + 1 + boxH) * W + col]) - LVFU(cfatmp[(row + 1 - boxH - 2) * W + col])) / lenv; - _mm_storeu_ps(&cfablur[row * W + col], temp1v); - _mm_storeu_ps(&cfablur[(row + 1)*W + col], temp2v); + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[(row + 1)*W + col], temp2v); } for(; row < H - boxH; row++) { temp1v = temp1v + (LVFU(cfatmp[(row + boxH) * W + col]) - LVFU(cfatmp[(row - boxH - 2) * W + col])) / lenv; - _mm_storeu_ps(&cfablur[row * W + col], temp1v); - __m128 swapv = temp1v; + STVFU(cfablur[row * W + col], temp1v); + vfloat swapv = temp1v; temp1v = temp2v; temp2v = swapv; @@ -3084,15 +3085,15 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur lenm1v = lenv - onev; temp1v = (temp1v * lenv - LVFU(cfatmp[(row - boxH - 2) * W + col])) / lenm1v; temp2v = (temp2v * lenv - LVFU(cfatmp[(row - boxH - 1) * W + col])) / lenm1v; - _mm_storeu_ps(&cfablur[row * W + col], temp1v); - _mm_storeu_ps(&cfablur[(row + 1)*W + col], temp2v); + STVFU(cfablur[row * W + col], temp1v); + STVFU(cfablur[(row + 1)*W + col], temp2v); lenv = lenm1v; } for(; row < H; row++) { lenm1v = lenv - onev; temp1v = (temp1v * lenv - LVFU(cfatmp[(row - boxH - 2) * W + col])) / lenm1v; - _mm_storeu_ps(&cfablur[(row)*W + col], temp1v); + STVFU(cfablur[(row)*W + col], temp1v); } } From ed25099a59307694acc10a38e952cca448c56ca0 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 7 Feb 2016 15:23:51 +0100 Subject: [PATCH 4/4] Added some switch defaults and removed a cast --- rtengine/rawimagesource.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 78470ecb7..0d8c9abd3 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -68,6 +68,7 @@ void rotateLine (const float* const line, rtengine::PlanarPtr &channel, c break; case TR_NONE: + default: for (int j = 0; j < w; j++) { channel(i, j) = line[j]; } @@ -135,6 +136,7 @@ void transLineFuji (const float* const red, const float* const green, const floa break; case TR_NONE: + default: for (int j = start; j < end; j++) { int y = i + j - fw; int x = fw - i + j; @@ -352,6 +354,7 @@ void transLineD1x (const float* const red, const float* const green, const float break; case TR_NONE: // no coarse rotation + default: rotateLine (red, image->r, tran, 2 * i, imwidth, imheight); rotateLine (green, image->g, tran, 2 * i, imwidth, imheight); rotateLine (blue, image->b, tran, 2 * i, imwidth, imheight); @@ -3035,7 +3038,7 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur //vertical blur #ifdef __SSE2__ - vfloat leninitv = F2V( (float)((int)(boxH / 2 + 1))); + vfloat leninitv = F2V(boxH / 2 + 1); vfloat onev = F2V( 1.0f ); vfloat temp1v, temp2v, lenv, lenp1v, lenm1v; int row;