From d2a4faea147429e8dcf32f98e68b5039b0403e50 Mon Sep 17 00:00:00 2001 From: Ingo Date: Sun, 4 Jan 2015 18:40:45 +0100 Subject: [PATCH] Reduced peak memory usage of Noise Reduction, Issue 2557 #119 and #123 --- rtengine/cplx_wavelet_dec.cc | 4 ++- rtengine/cplx_wavelet_dec.h | 48 ++++++++++++++++++++++------------- rtengine/cplx_wavelet_level.h | 28 ++++++++++---------- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/rtengine/cplx_wavelet_dec.cc b/rtengine/cplx_wavelet_dec.cc index abdfbcff8..9c4d77ab6 100644 --- a/rtengine/cplx_wavelet_dec.cc +++ b/rtengine/cplx_wavelet_dec.cc @@ -28,7 +28,9 @@ namespace rtengine { delete wavelet_decomp[i]; } delete[] wavfilt_anal; - delete[] wavfilt_synth; + delete[] wavfilt_synth; + if(coeff0) + delete [] coeff0; } }; diff --git a/rtengine/cplx_wavelet_dec.h b/rtengine/cplx_wavelet_dec.h index 3cadf295a..4547fb3bd 100644 --- a/rtengine/cplx_wavelet_dec.h +++ b/rtengine/cplx_wavelet_dec.h @@ -25,7 +25,7 @@ #include #include "cplx_wavelet_level.h" -#include "cplx_wavelet_filter_coeffs.h" +#include "cplx_wavelet_filter_coeffs.h" namespace rtengine { @@ -46,9 +46,7 @@ namespace rtengine { float *wavfilt_anal; float *wavfilt_synth; - int testfilt_len, testfilt_offset; - float *testfilt_anal; - float *testfilt_synth; + float *coeff0; wavelet_level * wavelet_decomp[maxlevels]; @@ -86,7 +84,7 @@ namespace rtengine { int maxlevel() const { - return lvltot; + return lvltot+1; } int subsample() const @@ -99,7 +97,7 @@ namespace rtengine { template wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling) - : lvltot(0), subsamp(subsampling), m_w(width), m_h(height) + : lvltot(0), subsamp(subsampling), m_w(width), m_h(height), coeff0(NULL) { //initialize wavelet filters wavfilt_len = Daub4_len; @@ -120,14 +118,22 @@ namespace rtengine { int padding = 0;//pow(2, maxlvl);//must be a multiple of two lvltot=0; - wavelet_decomp[lvltot] = new wavelet_level(src, lvltot/*level*/, subsamp, padding/*padding*/, m_w, m_h, \ - wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset); - while(lvltot < maxlvl) { + E *buffer[2]; + buffer[0] = new E[(m_w/2+1)*(m_h/2+1)]; + buffer[1] = new E[(m_w/2+1)*(m_h/2+1)]; + int bufferindex = 0; + + wavelet_decomp[lvltot] = new wavelet_level(src, buffer[bufferindex^1], lvltot/*level*/, subsamp, padding/*padding*/, m_w, m_h, \ + wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset); + while(lvltot < maxlvl-1) { lvltot++; - wavelet_decomp[lvltot] = new wavelet_level(wavelet_decomp[lvltot-1]->lopass()/*lopass*/, lvltot/*level*/, subsamp, 0/*no padding*/, \ + bufferindex ^= 1; + wavelet_decomp[lvltot] = new wavelet_level(buffer[bufferindex], buffer[bufferindex^1]/*lopass*/, lvltot/*level*/, subsamp, 0/*no padding*/, \ wavelet_decomp[lvltot-1]->width(), wavelet_decomp[lvltot-1]->height(), \ - wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset); - } + wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset); + } + coeff0 = buffer[bufferindex^1]; + delete[] buffer[bufferindex]; } template @@ -143,17 +149,23 @@ namespace rtengine { if(m_h2 < wavelet_decomp[lvl]->m_h2) m_h2 = wavelet_decomp[lvl]->m_h2; } - E *tmpLo = new E[m_w*m_h2]; E *tmpHi = new E[m_w*m_h2]; - - for (int lvl=lvltot-1; lvl>0; lvl--) { - wavelet_decomp[lvl]->reconstruct_level(tmpLo, tmpHi, wavelet_decomp[lvl-1]->wavcoeffs[0], wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); + + E *buffer[2]; + buffer[0] = coeff0; + buffer[1] = new E[(m_w/2+1)*(m_h/2+1)]; + int bufferindex = 0; + for (int lvl=lvltot; lvl>0; lvl--) { + wavelet_decomp[lvl]->reconstruct_level(tmpLo, tmpHi, buffer[bufferindex], buffer[bufferindex^1], wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); + bufferindex ^= 1; //skip /=2; } - wavelet_decomp[0]->reconstruct_level(tmpLo, tmpHi, dst, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); - + wavelet_decomp[0]->reconstruct_level(tmpLo, tmpHi, buffer[bufferindex], dst, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); + delete[] buffer[0]; + delete[] buffer[1]; + coeff0 = NULL; delete[] tmpLo; delete[] tmpHi; diff --git a/rtengine/cplx_wavelet_level.h b/rtengine/cplx_wavelet_level.h index 58603e804..874476c9a 100644 --- a/rtengine/cplx_wavelet_level.h +++ b/rtengine/cplx_wavelet_level.h @@ -72,7 +72,7 @@ namespace rtengine { size_t m_w2, m_h2; template - wavelet_level(E * src, int level, int subsamp, int padding, size_t w, size_t h, float *filterV, float *filterH, int len, int offset) + wavelet_level(E * src, E * dst, int level, int subsamp, int padding, size_t w, size_t h, float *filterV, float *filterH, int len, int offset) : m_w(w), m_h(h), m_w2(w), m_h2(h), m_pad(padding), wavcoeffs(NULL), lvl(level), skip(1<>level)&1) { if (subsamp) { @@ -86,7 +86,7 @@ namespace rtengine { m_pad= skip*padding; wavcoeffs = create((m_w2)*(m_h2)); - decompose_level(src, filterV, filterH, len, offset); + decompose_level(src, dst, filterV, filterH, len, offset); } @@ -126,18 +126,18 @@ namespace rtengine { } template - void decompose_level(E *src, float *filterV, float *filterH, int len, int offset); + void decompose_level(E *src, E *dst, float *filterV, float *filterH, int len, int offset); template - void reconstruct_level(E* tmpLo, E* tmpHi, E *dst, float *filterV, float *filterH, int taps, int offset); + void reconstruct_level(E* tmpLo, E* tmpHi, E *src, E *dst, float *filterV, float *filterH, int taps, int offset); }; template T ** wavelet_level::create(size_t n) { - T * data = new T[4*n]; + T * data = new T[3*n]; T ** subbands = new T*[4]; - for(size_t j = 0; j < 4; j++) { - subbands[j] = data + n * j; + for(size_t j = 1; j < 4; j++) { + subbands[j] = data + n * (j-1); } return subbands; } @@ -145,7 +145,7 @@ namespace rtengine { template void wavelet_level::destroy(T ** subbands) { if(subbands) { - delete[] subbands[0]; + delete[] subbands[1]; delete[] subbands; } } @@ -356,7 +356,7 @@ namespace rtengine { } } - template template void wavelet_level::decompose_level(E *src, float *filterV, float *filterH, int taps, int offset) { + template template void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) { T tmpLo[m_w] ALIGNED64; T tmpHi[m_w] ALIGNED64; @@ -364,27 +364,27 @@ namespace rtengine { if(subsamp_out) { for(int row=0;row template void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E *dst, float *filterV, float *filterH, int taps, int offset) { + template template void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset) { /* filter along rows and columns */ if (subsamp_out) { - SynthesisFilterSubsampHorizontal (wavcoeffs[0], wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w/*dstlen*/); + SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w/*dstlen*/); SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH+taps, taps, offset, m_w/*dstlen*/); SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterV, filterV+taps, taps, offset, m_w/*pitch*/, m_h/*dstlen*/); } else { - SynthesisFilterHaarHorizontal (wavcoeffs[0], wavcoeffs[1], tmpLo, m_w); + SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w); SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w); SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); }