"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
This commit is contained in:
Axel Dörfler 2007-04-23 22:23:53 +00:00
parent be1f432648
commit 8b4bb46952
2 changed files with 151 additions and 3 deletions

View File

@ -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);
}

View File

@ -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;