/* * This file is part of RawTherapee. * * 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 . * * 2010 Ilya Popov * 2012 Emil Martinec */ #ifndef CPLX_WAVELET_DEC_H_INCLUDED #define CPLX_WAVELET_DEC_H_INCLUDED #include #include #include "cplx_wavelet_level.h" #include "cplx_wavelet_filter_coeffs.h" namespace rtengine { // %%%%%%%%%%%%%%%%%%%%%%%%%%% template void copy_out(A ** a, B * b, size_t datalen) { for (size_t j=0; j (0.25f*(a[0][j]+a[1][j]+a[2][j]+a[3][j])); } } // %%%%%%%%%%%%%%%%%%%%%%%%%%% class cplx_wavelet_decomposition { public: typedef float internal_type; private: static const int maxlevels = 8;//should be greater than any conceivable order of decimation int lvltot; size_t m_w, m_h;//dimensions size_t m_w1, m_h1; int first_lev_len, first_lev_offset; //multi_array2D first_lev_anal; //multi_array2D first_lev_synth; float *first_lev_anal; float *first_lev_synth; int wavfilt_len, wavfilt_offset; //multi_array2D wavfilt_anal; //multi_array2D wavfilt_synth; float *wavfilt_anal; float *wavfilt_synth; cplx_wavelet_level * dual_tree_coeffs[maxlevels][4];//m_c in old code public: template cplx_wavelet_decomposition(E * src, int width, int height, int maxlvl); ~cplx_wavelet_decomposition(); template void reconstruct(E * dst); }; // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*template cplx_wavelet_decomposition::cplx_wavelet_decomposition(E * src, int width, int height, int maxlvl) : lvltot(0), m_w(w), m_h(h), m_w1(0), m_h1(0) { m_w1 = w; m_h1 = h; m_c[0] = new cplx_wavelet_level(src, m_w1, m_h1, FSFarras); lvltot = 1; while(lvltot < maxlevels) { m_c[level] = new cplx_wavelet_level(m_c[lvltot-1]->data[0], m_c[lvltot-1]->width(), m_c[lvltot-1]->height(), Kingsbury); lvltot ++; } }*/ /*template void cplx_wavelet_decomposition::reconstruct(E * dst) { noop n; for(int level = lvltot - 1; level > 0; level--) { int alpha = 1024 + 10 * c[level]; m_c[level]->reconstruct(m_c[level-1]->lowfreq(), alpha, n); } int alpha = 1024 + 10 * c[0]; m_c[0]->reconstruct(dst, alpha, l); }*/ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% template cplx_wavelet_decomposition::cplx_wavelet_decomposition(E * src, int width, int height, int maxlvl) : lvltot(0), m_w(width), m_h(height), m_w1(0), m_h1(0) { m_w1 = width; m_h1 = height; //initialize wavelet filters first_lev_len = FSFarras_len; first_lev_offset = FSFarras_offset; //multi_array2D first_lev_anal(2,first_lev_len); //multi_array2D first_lev_synth(2,first_lev_len); float *first_level_anal = new float[4*first_lev_len]; float *first_level_synth = new float[4*first_lev_len]; for (int n=0; n<2; n++) { for (int m=0; m<2; m++) { for (int i=0; i wavfilt_anal(2,Kingsbury_len); //multi_array2D wavfilt_synth(2,Kingsbury_len); float *wavfilt_anal = new float[4*wavfilt_len]; float *wavfilt_synth = new float[4*wavfilt_len]; for (int n=0; n<2; n++) { for (int m=0; m<2; m++) { for (int i=0; i(src, first_lev_anal[n], first_lev_anal[m], first_lev_len, first_lev_offset); dual_tree_coeffs[0][2*n+m] = new cplx_wavelet_level(src, m_w, m_h, first_lev_anal+first_lev_len*2*n, \ first_lev_anal+first_lev_len*2*m, first_lev_len, first_lev_offset); lvltot=1; while(lvltot < maxlevels) { //dual_tree_coeffs[lvltot][2*n+m] = new cplx_wavelet_level(dual_tree_coeffs[lvltot-1][2*n+m]->lopass()/*lopass*/, \ wavfilt_anal[n], wavfilt_anal[m], wavfilt_len, wavfilt_offset); dual_tree_coeffs[lvltot][2*n+m] = new cplx_wavelet_level(dual_tree_coeffs[lvltot-1][2*n+m]->lopass()/*lopass*/, \ dual_tree_coeffs[lvltot-1][2*n+m]->width(), \ dual_tree_coeffs[lvltot-1][2*n+m]->height(), \ wavfilt_anal+wavfilt_len*2*n, wavfilt_anal+wavfilt_len*2*m, wavfilt_len, wavfilt_offset); lvltot++; } } } //rotate detail coefficients float root2 = sqrt(2); for (int lvl=0; lvlwidth(); int Hlvl = dual_tree_coeffs[lvl][0]->height(); for (int i=0; iwavcoeffs[m][i] + dual_tree_coeffs[lvl][3]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][3]->wavcoeffs[m][i] = (dual_tree_coeffs[lvl][0]->wavcoeffs[m][i] - dual_tree_coeffs[lvl][3]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][0]->wavcoeffs[m][i] = wavtmp; wavtmp = (dual_tree_coeffs[lvl][1]->wavcoeffs[m][i] + dual_tree_coeffs[lvl][2]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][2]->wavcoeffs[m][i] = (dual_tree_coeffs[lvl][1]->wavcoeffs[m][i] - dual_tree_coeffs[lvl][2]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][1]->wavcoeffs[m][i] = wavtmp; } } } } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ /* function y=reconstruct(w,J,Fsf,sf) */ template void cplx_wavelet_decomposition::reconstruct(E * dst) { // data structure is wavcoeffs[scale][2*n+m=2*(Re/Im)+dir][channel={lo,hi1,hi2,hi3}][pixel_array] //rotate detail coefficients float root2 = sqrt(2); for (int lvl=0; lvlwidth(); int Hlvl = dual_tree_coeffs[lvl][0]->height(); for (int i=0; iwavcoeffs[m][i] + dual_tree_coeffs[lvl][3]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][3]->wavcoeffs[m][i] = (dual_tree_coeffs[lvl][0]->wavcoeffs[m][i] - dual_tree_coeffs[lvl][3]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][0]->wavcoeffs[m][i] = wavtmp; wavtmp = (dual_tree_coeffs[lvl][1]->wavcoeffs[m][i] + dual_tree_coeffs[lvl][2]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][2]->wavcoeffs[m][i] = (dual_tree_coeffs[lvl][1]->wavcoeffs[m][i] - dual_tree_coeffs[lvl][2]->wavcoeffs[m][i])/root2; dual_tree_coeffs[lvl][1]->wavcoeffs[m][i] = wavtmp; } } } //y = ConstantArray[0, {vsizetmp, hsizetmp}]; array2D tmp(4,m_w*m_h); for (int n=0; n<2; n++) { for (int m=0; m<2; m++) { for (int lvl=lvltot-1; lvl>0; lvl--) { //m_c[level]->reconstruct(m_c[level-1]->lowfreq(), alpha, n); //dual_tree_coeffs[lvl][2*n+m]->reconstruct_level(dual_tree_coeffs[lvl-1][2*n+m]->wavcoeffs[0], wavfilt_synth[n], wavfilt_synth[m], wavfilt_len, wavfilt_offset); dual_tree_coeffs[lvl][2*n+m]->reconstruct_level(dual_tree_coeffs[lvl-1][2*n+m]->wavcoeffs[0], wavfilt_synth+wavfilt_len*2*n, \ wavfilt_synth+wavfilt_len*2*m, wavfilt_len, wavfilt_offset); } //dual_tree_coeffs[0][2*n+m]->reconstruct_level(tmp[2*n+m], first_lev_synth[n], first_lev_synth[m], first_lev_len, first_lev_offset); dual_tree_coeffs[0][2*n+m]->reconstruct_level(tmp[2*n+m], first_lev_synth+wavfilt_len*2*n, first_lev_synth+wavfilt_len*2*m, first_lev_len, first_lev_offset); } } copy_out(tmp,dst,m_w*m_h); } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% }; #endif