From 8b4bb46952ddff761742952134f7d70043720700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 23 Apr 2007 22:23:53 +0000 Subject: [PATCH] "Ported" wavelet denoising code from dcraw - not tested, probably won't work yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20790 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/translators/raw/RAW.cpp | 150 +++++++++++++++++++++++++++- src/add-ons/translators/raw/RAW.h | 4 +- 2 files changed, 151 insertions(+), 3 deletions(-) diff --git a/src/add-ons/translators/raw/RAW.cpp b/src/add-ons/translators/raw/RAW.cpp index a518c731a7..b7ce42938d 100644 --- a/src/add-ons/translators/raw/RAW.cpp +++ b/src/add-ons/translators/raw/RAW.cpp @@ -119,7 +119,7 @@ DCRaw::DCRaw(BPositionIO& stream) fDNGVersion(0), fIsTIFF(false), fImageData(NULL), - fThreshold(0), + fThreshold(0.0f), fHalfSize(false), fUseCameraWhiteBalance(true), fUseAutoWhiteBalance(true), @@ -1023,6 +1023,154 @@ DCRaw::_ScaleColors() void DCRaw::_WaveletDenoise() { + if (fProgressMonitor != NULL) + fProgressMonitor("Wavelet Denoise", 8, fProgressData); + + float *fimg, *temp, mul[2], avg, diff; + int32 scale = 1, sh, c, i, j, k, m, row, col, size, numColors, dim = 0; + int32 wlast; + ushort *window[4]; + // Daubechies 9-tap/7-tap filter + static const float wlet[] = { 1.149604398, -1.586134342, + -0.05298011854, 0.8829110762, 0.4435068522 }; + + while ((fMeta.maximum << scale) < 0x10000) { + scale++; + } + fMeta.maximum <<= fMeta.maximum << --scale; + fMeta.black <<= scale; + + while ((1UL << dim) < fOutputWidth || (1UL << dim) < fOutputHeight) { + dim++; + } + + fimg = (float *)calloc((1UL << dim*2) + (1UL << dim) + 2, sizeof *fimg); + if (fimg == NULL) + return; + + temp = fimg + (1 << dim * 2) + 1; + numColors = fColors; + if (numColors == 3 && fFilters) + numColors++; + + for (c = 0; c < numColors; c++) { + // denoise R,G1,B,G3 individually + for (row = 0; row < (int32)fOutputHeight; row++) { + for (col = 0; col < (int32)fOutputWidth; col++) { + fimg[(row << dim) + col] + = fImageData[row * fOutputWidth + col][c] << scale; + } + } + for (size = 1UL << dim; size > 1; size >>= 1) { + for (sh = 0; sh <= dim; sh += dim) { + for (i = 0; i < size; i++) { + for (j = 0; j < size; j++) { + temp[j] = fimg[(i << (dim-sh))+(j << sh)]; + } + for (k = 1; k < 5; k += 2) { + temp[size] = temp[size - 2]; + for (m = 1; m < size; m += 2) { + temp[m] += wlet[k] * (temp[m-1] + temp[m+1]); + } + temp[-1] = temp[1]; + for (m = 0; m < size; m += 2) { + temp[m] += wlet[k+1] * (temp[m-1] + temp[m+1]); + } + } + for (m = 0; m < size; m++) { + temp[m] *= (m & 1) ? 1/wlet[0] : wlet[0]; + } + for (j = k = 0; j < size; j++, k+=2) { + if (k == size) + k = 1; + fimg[(i << (dim-sh))+(j << sh)] = temp[k]; + } + } + } + } + + for (i = 0; i < (1 << dim * 2); i++) { + if (fimg[i] < -fThreshold) + fimg[i] += fThreshold; + else if (fimg[i] > fThreshold) + fimg[i] -= fThreshold; + else + fimg[i] = 0; + } + + for (size = 2; size <= (1 << dim); size <<= 1) { + for (sh = dim; sh >= 0; sh -= dim) { + for (i = 0; i < size; i++) { + for (j = k = 0; j < size; j++, k+=2) { + if (k == size) + k = 1; + temp[k] = fimg[(i << (dim-sh))+(j << sh)]; + } + for (m = 0; m < size; m++) { + temp[m] *= (m & 1) ? wlet[0] : 1/wlet[0]; + } + for (k = 3; k > 0; k-=2) { + temp[-1] = temp[1]; + for (m = 0; m < size; m += 2) { + temp[m] -= wlet[k+1] * (temp[m-1] + temp[m+1]); + } + temp[size] = temp[size - 2]; + for (m = 1; m < size; m += 2) { + temp[m] -= wlet[k] * (temp[m-1] + temp[m+1]); + } + } + for (j = 0; j < size; j++) { + fimg[(i << (dim-sh))+(j << sh)] = temp[j]; + } + } + } + } + + for (row = 0; row < (int32)fOutputHeight; row++) { + for (col = 0; col < (int32)fOutputWidth; col++) { + fImageData[row * fOutputWidth + col][c] + = (uint16)CLIP(fimg[(row << dim) + col] + 0.5); + } + } + } + + if (fFilters && fColors == 3) { + // pull G1 and G3 closer together + for (row = 0; row < 2; row++) { + mul[row] = 0.125 * fMeta.pre_multipliers[FC(row + 1, 0) | 1] + / fMeta.pre_multipliers[FC(row, 0) | 1]; + } + for (i = 0; i < 4; i++) { + window[i] = (ushort *) fimg + fInputWidth * i; + } + for (wlast = -1, row = 1; row < (int32)fInputHeight - 1; row++) { + while (wlast < (int32)row + 1) { + for (wlast++, i=0; i < 4; i++) { + window[(i+3) & 3] = window[i]; + } + for (col = FC(wlast,1) & 1; col < (int32)fInputWidth; col += 2) { + window[2][col] = _Bayer(col, wlast); + } + } + + for (col = (FC(row, 0) & 1)+1; col < (int32)fInputWidth - 1; col += 2) { + avg = ( window[0][col - 1] + window[0][col + 1] + + window[2][col - 1] + window[2][col + 1] - fMeta.black * 4) + * mul[row & 1] + (window[1][col] - fMeta.black) * 0.5 + fMeta.black; + diff = _Bayer(col, row) - avg; + + if (diff < -fThreshold / M_SQRT2) + diff += fThreshold / M_SQRT2; + else if (diff > fThreshold / M_SQRT2) + diff -= fThreshold / M_SQRT2; + else + diff = 0; + _Bayer(col, row) = (uint16)CLIP(avg + diff + 0.5); + } + } + } + + free(fimg); } diff --git a/src/add-ons/translators/raw/RAW.h b/src/add-ons/translators/raw/RAW.h index e23923d89f..bd9dfa27ec 100644 --- a/src/add-ons/translators/raw/RAW.h +++ b/src/add-ons/translators/raw/RAW.h @@ -28,7 +28,7 @@ struct image_meta_info { uint32 dng_version; uint32 shot_order; int32 black; - double maximum; + int32 maximum; float camera_multipliers[4]; float pre_multipliers[4]; float rgb_camera[3][4]; /* RGB from camera color */ @@ -144,7 +144,7 @@ class DCRaw { uint16 (*fImageData)[4]; // output image data - int32 fThreshold; + float fThreshold; int32 fShrink; bool fHalfSize; bool fUseCameraWhiteBalance;