Added wavelet equalizer module

This commit is contained in:
Ilia Popov
2010-06-30 23:28:45 +02:00
parent e37b23ae8b
commit e0c25b4db6
22 changed files with 1632 additions and 787 deletions

View File

@@ -11,7 +11,8 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc dcraw.cc iccstore.cc
loadinitial.cc procparams.cc rawimagesource.cc shmap.cc simpleprocess.cc refreshmap.cc
stdimagesource.cc myfile.cc iccjpeg.c hlmultipliers.cc improccoordinator.cc
processingjob.cc rtthumbnail.cc utils.cc labimage.cc
iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc)
iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc
wavelet_dec.cc ipequalizer.cc)
add_library (rtengine ${RTENGINESOURCEFILES})
#It may be nice to store library version too

View File

@@ -89,6 +89,7 @@ class ImProcFunctions {
void lab2rgb (LabImage* lab, Image8* image);
void resize (Image16* src, Image16* dst);
void deconvsharpening(LabImage* lab, unsigned short** buffer);
void waveletEqualizer(Image16 * image, int fw, int fh, const EqualizerParams & params);
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile);
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile);

40
rtengine/ipequalizer.cc Normal file
View File

@@ -0,0 +1,40 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* 2010 Ilya Popov <ilia_popov@rambler.ru>
*/
#include <rtengine.h>
#include <improcfun.h>
#include <wavelet_dec.h>
namespace rtengine {
void ImProcFunctions :: waveletEqualizer(Image16 * image, int fw, int fh, const EqualizerParams & params) {
wavelet_decomposition r(image->r, fw, fh);
r.reconstruct(image->r, params.c);
wavelet_decomposition g(image->g, fw, fh);
g.reconstruct(image->g, params.c);
wavelet_decomposition b(image->b, fw, fh);
b.reconstruct(image->b, params.c);
}
}

View File

@@ -21,7 +21,7 @@
#include <rtengine.h>
#define NUMOFEVENTS 84
#define NUMOFEVENTS 86
namespace rtengine {
@@ -109,7 +109,9 @@ enum ProcEvent {
EvResizeEnabled=80,
EvProfileChangeNotification=81,
EvSHHighQuality=82,
EvPerspCorr=83
EvPerspCorr=83,
EvEqualizer=84,
EvEqlEnabled=85
};
}
#endif

View File

@@ -158,6 +158,12 @@ void ProcParams::setDefaults () {
icm.working = "sRGB";
icm.output = "sRGB";
equalizer.enabled = false;
for(int i = 0; i < 8; i ++)
{
equalizer.c[i] = 0;
}
exif.clear ();
iptc.clear ();
@@ -303,6 +309,15 @@ int ProcParams::save (Glib::ustring fname) const {
keyFile.set_boolean ("Color Management", "ApplyGammaBeforeInputProfile", icm.gammaOnInput);
keyFile.set_string ("Color Management", "WorkingProfile", icm.working);
keyFile.set_string ("Color Management", "OutputProfile", icm.output);
// save wavelet equalizer parameters
keyFile.set_boolean ("Equalizer", "Enabled", equalizer.enabled);
for(int i = 0; i < 8; i++)
{
std::stringstream ss;
ss << "C" << i;
keyFile.set_integer("Equalizer", ss.str(), equalizer.c[i]);
}
// save exif change list
for (int i=0; i<exif.size(); i++)
@@ -530,6 +545,17 @@ if (keyFile.has_group ("Color Management")) {
if (keyFile.has_key ("Color Management", "OutputProfile")) icm.output = keyFile.get_string ("Color Management", "OutputProfile");
}
// load wavelet equalizer parameters
if (keyFile.has_group ("Equalizer")) {
if (keyFile.has_key ("Equalizer", "Enabled")) equalizer.enabled = keyFile.get_boolean ("Equalizer", "Enabled");
for(int i = 0; i < 8; i ++)
{
std::stringstream ss;
ss << "C" << i;
if(keyFile.has_key ("Equalizer", ss.str())) equalizer.c[i] = keyFile.get_integer ("Equalizer", ss.str());
}
}
// load exif change settings
if (keyFile.has_group ("Exif")) {
std::vector<Glib::ustring> keys = keyFile.get_keys ("Exif");
@@ -562,6 +588,17 @@ if (keyFile.has_group ("IPTC")) {
}
}
bool operator==(const EqualizerParams & a, const EqualizerParams & b) {
if(a.enabled != b.enabled)
return false;
for(int i = 0; i < 8; i++) {
if(a.c[i] != b.c[i])
return false;
}
return true;
}
bool operator==(const ExifPair& a, const ExifPair& b) {
return a.field == b.field && a.value == b.value;
@@ -660,6 +697,7 @@ bool ProcParams::operator== (const ProcParams& other) {
&& icm.gammaOnInput == other.icm.gammaOnInput
&& icm.working == other.icm.working
&& icm.output == other.icm.output
&& equalizer == other.equalizer
&& exif==other.exif
&& iptc==other.iptc;
}

View File

@@ -204,16 +204,16 @@ class DistortionParams {
bool uselensfun;
double amount;
};
/**
* Parameters of the perspective correction
*/
class PerspectiveParams {
public:
int horizontal;
int vertical;
};
/**
* Parameters of the perspective correction
*/
class PerspectiveParams {
public:
int horizontal;
int vertical;
};
/**
* Parameters of the vignetting correction
@@ -302,6 +302,16 @@ class IPTCPair {
std::vector<Glib::ustring> values;
};
/**
* Wavelet equalizer params
*/
class EqualizerParams {
public:
bool enabled;
int c[8];
};
/**
* This class holds all the processing parameters applied on the images
*/
@@ -321,14 +331,15 @@ class ProcParams {
CoarseTransformParams coarse; ///< Coarse transformation (90, 180, 270 deg rotation, h/v flipping) parameters
CommonTransformParams commonTrans; ///< Common transformation parameters (autofill)
RotateParams rotate; ///< Rotation parameters
DistortionParams distortion; ///< Lens distortion correction parameters
PerspectiveParams perspective; ///< Perspective correction parameters
DistortionParams distortion; ///< Lens distortion correction parameters
PerspectiveParams perspective; ///< Perspective correction parameters
CACorrParams cacorrection; ///< Lens c/a correction parameters
VignettingParams vignetting; ///< Lens vignetting correction parameters
ChannelMixerParams chmixer; ///< Channel mixer parameters
HRecParams hlrecovery; ///< Highlight recovery parameters
ResizeParams resize; ///< Resize parameters
ColorManagementParams icm; ///< profiles/color spaces used during the image processing
EqualizerParams equalizer; ///< wavelet equalizer parameters
std::vector<ExifPair> exif; ///< List of modifications appplied on the exif tags of the input image
std::vector<IPTCPair> iptc; ///< The IPTC tags and values to be saved to the output image
int version; ///< Version of the file from which the parameters have been read

View File

@@ -19,89 +19,90 @@
#include <refreshmap.h>
int refreshmap[] = {
ALL, // EvPhotoLoaded,
ALL, // EvProfileLoaded,
ALL, // EvProfileChanged,
ALL, // EvHistoryBrowsed,
RGBCURVE, // EvBrightness,
RGBCURVE, // EvContrast,
RGBCURVE, // EvBlack,
RGBCURVE, // EvExpComp,
RGBCURVE, // EvHLCompr,
RGBCURVE, // EvSHCompr,
RGBCURVE, // EvToneCurve,
AUTOEXP, // EvAutoExp,
AUTOEXP, // EvClip,
LUMINANCECURVE, // EvLBrightness,
LUMINANCECURVE, // EvLContrast,
LUMINANCECURVE, // EvLBlack,
LUMINANCECURVE, // EvLHLCompr,
LUMINANCECURVE, // EvLSHCompr,
LUMINANCECURVE, // EvLCurve,
SHARPENING, // EvShrEnabled,
SHARPENING, // EvShrRadius,
SHARPENING, // EvShrAmount,
SHARPENING, // EvShrThresh,
SHARPENING, // EvShrEdgeOnly,
SHARPENING, // EvShrEdgeRadius,
SHARPENING, // EvShrEdgeTolerance,
SHARPENING, // EvShrHaloControl,
SHARPENING, // EvShrHaloAmount,
SHARPENING, // EvShrMethod,
SHARPENING, // EvShrDRadius,
SHARPENING, // EvShrDAmount,
SHARPENING, // EvShrDDamping,
SHARPENING, // EvShrDIterations,
COLORBOOST, // EvCBAvoidClip,
COLORBOOST, // EvCBSatLimiter,
COLORBOOST, // EvCBSatLimit,
COLORBOOST, // EvCBBoost,
WHITEBALANCE, // EvWBMethod,
WHITEBALANCE, // EvWBTemp,
WHITEBALANCE, // EvWBGreen,
COLORBOOST, // EvCShiftA,
COLORBOOST, // EvCShiftB,
LUMADENOISE, // EvLDNEnabled,
LUMADENOISE, // EvLDNRadius,
LUMADENOISE, // EvLDNEdgeTolerance,
COLORDENOISE, // EvCDNEnabled,
COLORDENOISE, // EvCDNRadius,
COLORDENOISE, // EvCDNEdgeTolerance,
COLORDENOISE, // EvCDNEdgeSensitive,
RETINEX, // EvSHEnabled,
RGBCURVE, // EvSHHighlights,
RGBCURVE, // EvSHShadows,
RGBCURVE, // EvSHHLTonalW,
RGBCURVE, // EvSHSHTonalW,
RGBCURVE, // EvSHLContrast,
RETINEX, // EvSHRadius,
ALL, // EvCTRotate,
ALL, // EvCTHFlip,
ALL, // EvCTVFlip,
TRANSFORM, // EvROTDegree,
TRANSFORM, // EvTransAutoFill,
TRANSFORM, // EvDISTAmount,
ALL, // EvBookmarkSelected,
CROP, // EvCrop,
TRANSFORM, // EvCACorr,
ALL, // EvHREnabled,
ALL, // EvHRAmount,
ALL, // EvHRMethod,
ALL, // EvWProfile,
ALL, // EvOProfile,
ALL, // EvIProfile,
TRANSFORM, // EvVignetting,
RGBCURVE, // EvChMixer,
ALL, // EvResizeScale,
ALL, // EvResizeMethod,
EXIF, // EvExif,
IPTC, // EvIPTC
ALL, // EvResizeSpec,
ALL, // EvResizeWidth
ALL, // EvResizeHeight
ALL, // EvResizeEnabled
ALL, // EvProfileChangeNotification
ALL, // EvPhotoLoaded,
ALL, // EvProfileLoaded,
ALL, // EvProfileChanged,
ALL, // EvHistoryBrowsed,
RGBCURVE, // EvBrightness,
RGBCURVE, // EvContrast,
RGBCURVE, // EvBlack,
RGBCURVE, // EvExpComp,
RGBCURVE, // EvHLCompr,
RGBCURVE, // EvSHCompr,
RGBCURVE, // EvToneCurve,
AUTOEXP, // EvAutoExp,
AUTOEXP, // EvClip,
LUMINANCECURVE, // EvLBrightness,
LUMINANCECURVE, // EvLContrast,
LUMINANCECURVE, // EvLBlack,
LUMINANCECURVE, // EvLHLCompr,
LUMINANCECURVE, // EvLSHCompr,
LUMINANCECURVE, // EvLCurve,
SHARPENING, // EvShrEnabled,
SHARPENING, // EvShrRadius,
SHARPENING, // EvShrAmount,
SHARPENING, // EvShrThresh,
SHARPENING, // EvShrEdgeOnly,
SHARPENING, // EvShrEdgeRadius,
SHARPENING, // EvShrEdgeTolerance,
SHARPENING, // EvShrHaloControl,
SHARPENING, // EvShrHaloAmount,
SHARPENING, // EvShrMethod,
SHARPENING, // EvShrDRadius,
SHARPENING, // EvShrDAmount,
SHARPENING, // EvShrDDamping,
SHARPENING, // EvShrDIterations,
COLORBOOST, // EvCBAvoidClip,
COLORBOOST, // EvCBSatLimiter,
COLORBOOST, // EvCBSatLimit,
COLORBOOST, // EvCBBoost,
WHITEBALANCE, // EvWBMethod,
WHITEBALANCE, // EvWBTemp,
WHITEBALANCE, // EvWBGreen,
COLORBOOST, // EvCShiftA,
COLORBOOST, // EvCShiftB,
LUMADENOISE, // EvLDNEnabled,
LUMADENOISE, // EvLDNRadius,
LUMADENOISE, // EvLDNEdgeTolerance,
COLORDENOISE, // EvCDNEnabled,
COLORDENOISE, // EvCDNRadius,
COLORDENOISE, // EvCDNEdgeTolerance,
COLORDENOISE, // EvCDNEdgeSensitive,
RETINEX, // EvSHEnabled,
RGBCURVE, // EvSHHighlights,
RGBCURVE, // EvSHShadows,
RGBCURVE, // EvSHHLTonalW,
RGBCURVE, // EvSHSHTonalW,
RGBCURVE, // EvSHLContrast,
RETINEX, // EvSHRadius,
ALL, // EvCTRotate,
ALL, // EvCTHFlip,
ALL, // EvCTVFlip,
TRANSFORM, // EvROTDegree,
TRANSFORM, // EvTransAutoFill,
TRANSFORM, // EvDISTAmount,
ALL, // EvBookmarkSelected,
CROP, // EvCrop,
TRANSFORM, // EvCACorr,
ALL, // EvHREnabled,
ALL, // EvHRAmount,
ALL, // EvHRMethod,
ALL, // EvWProfile,
ALL, // EvOProfile,
ALL, // EvIProfile,
TRANSFORM, // EvVignetting,
RGBCURVE, // EvChMixer,
ALL, // EvResizeScale,
ALL, // EvResizeMethod,
EXIF, // EvExif,
IPTC, // EvIPTC
ALL, // EvResizeSpec,
ALL, // EvResizeWidth
ALL, // EvResizeHeight
ALL, // EvResizeEnabled
ALL, // EvProfileChangeNotification
RETINEX, // EvShrHighQuality
TRANSFORM // EvPerspCorr
};
TRANSFORM, // EvPerspCorr
ALL // ????? EvEqualizer
};

View File

@@ -25,6 +25,8 @@
#include <processingjob.h>
#include <glibmm.h>
#include <iostream>
#undef THREAD_PRIORITY_NORMAL
namespace rtengine {
@@ -100,6 +102,10 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
delete baseImg;
baseImg = trImg;
}
if (params.equalizer.enabled) {
ipf.waveletEqualizer (baseImg, fw, fh, params.equalizer);
}
// update blurmap
int** buffer = new int*[fh];

170
rtengine/wavelet.h Normal file
View File

@@ -0,0 +1,170 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* 2010 Ilya Popov <ilia_popov@rambler.ru>
*/
#ifndef WAVELET_H_INCLUDED
#define WAVELET_H_INCLUDED
template<class T>
void dwt_haar(T * data, size_t pitch, T * buffer, size_t n)
{
size_t n2a = (n + 1) / 2;
size_t n2 = n/2;
for(size_t i = 0, j = 0; i < n2; i++, j += 2 * pitch)
{
T a = data[j];
T b = data[j + pitch];
buffer[i] = (a + b) / 2;
buffer[n2a + i] = (a - b);
}
if(n2 < n2a)
{
buffer[n2] = data[pitch * (n-1)];
}
for(size_t k = 0, q = 0; k < n; k++, q += pitch)
{
data[q] = buffer[k];
}
}
template<class T>
void idwt_haar(T * data, size_t pitch, T * buffer, size_t n, int alpha)
{
size_t n2a = (n + 1) / 2;
size_t n2 = n/2;
for(size_t i = 0, j = 0; i < n2; i++, j += 2)
{
T p = data[i * pitch];
T q = (alpha * data[(n2a + i)*pitch]) / 1024;
buffer[j] = p + q / 2;
buffer[j + 1] = p - q / 2;
}
if(n2 < n2a)
{
buffer[n-1] = data[pitch * n2];
}
for(size_t k = 0, q = 0; k < n; k++, q += pitch)
{
data[q] = buffer[k];
}
}
// buffer must be of length (n + 4)
template<class T>
void dwt_53(T * data, size_t pitch, T * buffer, size_t n)
{
size_t n2 = n/2;
size_t n2a = (n + 1) / 2;
T * tmp = buffer + 2;
// copy data
for(size_t i = 0, j = 0; i < n; i++, j += pitch)
{
tmp[i] = data[j];
}
// extend mirror-like
tmp[-1] = tmp[1];
tmp[-2] = tmp[2];
tmp[n] = tmp[n-2];
tmp[n+1] = tmp[n-3];
// calculate coefficients
for(int j = -1; j < (int)n + 1; j += 2)
{
tmp[j] = tmp[j] - (tmp[j-1] + tmp[j+1]) / 2;
}
for(int i = 0; i < (int)n; i += 2)
{
tmp[i] = tmp[i] + (tmp[i-1] + tmp[i+1] + 2) / 4;
}
// copy with reordering
for(size_t i = 0, j = 0; i < n; i+=2, j += pitch)
{
data[j] = tmp[i];
}
for(size_t i = 1, j = n2a*pitch; i < n; i+=2, j += pitch)
{
data[j] = tmp[i];
}
}
template<class T>
void idwt_53(T * data, size_t pitch, T * buffer, size_t n, int alpha)
{
size_t n2 = n/2;
size_t n2a = (n + 1) / 2;
T * tmp = buffer + 2;
// copy with reordering
for(size_t i = 0, j = 0; i < n; i+=2, j += pitch)
{
tmp[i] = data[j];
}
for(size_t i = 1, j = n2a*pitch; i < n; i+=2, j += pitch)
{
tmp[i] = (alpha * data[j]) / 1024;
}
// extend mirror-like
tmp[-1] = tmp[1];
tmp[-2] = tmp[2];
tmp[n] = tmp[n-2];
tmp[n+1] = tmp[n-3];
// calculate coefficients
for(int i = 0; i < (int)n + 1; i += 2)
{
tmp[i] = tmp[i] - (tmp[i-1] + tmp[i+1] + 2) / 4;
}
for(int j = 1; j < (int)n; j += 2)
{
tmp[j] = tmp[j] + (tmp[j-1] + tmp[j+1]) / 2;
}
// copy data
for(size_t i = 0, j = 0; i < n; i++, j += pitch)
{
data[j] = tmp[i];
}
}
#endif

62
rtengine/wavelet_dec.cc Normal file
View File

@@ -0,0 +1,62 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* 2010 Ilya Popov <ilia_popov@rambler.ru>
*/
#include "wavelet_dec.h"
namespace rtengine
{
wavelet_decomposition::wavelet_decomposition(unsigned short ** src, size_t w, size_t h)
: nlevels(0), m_w(w), m_h(h), m_w1(0), m_h1(0)
{
m_w1 = w;
m_h1 = h;
m_c[0] = new wavelet_level<internal_type>(src, m_w1, m_h1);
nlevels = 1;
while(nlevels < maxlevels)
{
m_c[nlevels] = new wavelet_level<internal_type>(m_c[nlevels - 1]->lowfreq(), m_c[nlevels-1]->lfw(), m_c[nlevels-1]->lfh());
nlevels ++;
}
}
wavelet_decomposition::~wavelet_decomposition()
{
for(int i = 0; i < nlevels; i++)
{
delete m_c[i];
}
}
void wavelet_decomposition::reconstruct(unsigned short ** dst, const int * c)
{
for(int level = nlevels - 1; level > 0; level--)
{
int alpha = 1024 + 10 * c[level];
m_c[level]->reconstruct(m_c[level-1]->lowfreq(), alpha);
}
int alpha = 1024 + 10 * c[0];
m_c[0]->reconstruct(dst, alpha, wavelet_level<internal_type>::CLIP);
}
};

53
rtengine/wavelet_dec.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* 2010 Ilya Popov <ilia_popov@rambler.ru>
*/
#ifndef WAVELET_DEC_H_INCLUDED
#define WAVELET_DEC_H_INCLUDED
#include <cstddef>
#include "wavelet_level.h"
namespace rtengine {
class wavelet_decomposition
{
typedef int internal_type;
static const int maxlevels = 8;
int nlevels;
size_t m_w, m_h;
size_t m_w1, m_h1;
wavelet_level<internal_type> * m_c[maxlevels];
public:
wavelet_decomposition(unsigned short ** src, size_t w, size_t h);
~wavelet_decomposition();
void reconstruct(unsigned short ** dst, const int * c);
};
//////////////////////////////////////////////////////////////////////////////
};
#endif

208
rtengine/wavelet_level.h Normal file
View File

@@ -0,0 +1,208 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*
* 2010 Ilya Popov <ilia_popov@rambler.ru>
*/
#ifndef WAVELET_LEVEL_H_INCLUDED
#define WAVELET_LEVEL_H_INCLUDED
#include <cstddef>
#include <algorithm>
#include "wavelet.h"
namespace rtengine
{
template<class T>
inline T clip(T x, T min_value, T max_value)
{
if(x < min_value)
return min_value;
if(x > max_value)
return max_value;
return x;
}
template <class A, class B>
void plane_copy(A ** a, B ** b, size_t w, size_t h)
{
for(size_t j = 0; j < h; j++)
for(size_t i = 0; i < w; i++)
b[j][i] = static_cast<B>(a[j][i]);
}
//////////////////////////////////////////////////////////////////////////////
template<class T>
class wavelet_level
{
// full size
size_t m_w, m_h;
// size of low frequency part
size_t m_w2, m_h2;
// distance between lines in the array of coeffs
size_t m_pitch;
// array of pointers to lines of coeffs
// actually is a single contiguous data array pointed by m_coeffs[0]
T ** m_coeffs;
// allocation and destruction of data storage
void create();
void destroy();
void dwt_2d(size_t w, size_t h);
void idwt_2d(size_t w, size_t h, int alpha);
public:
static const bool CLIP = true;
template<class E>
wavelet_level(E ** src, size_t w, size_t h)
: m_w(w), m_h(h), m_w2((w+1)/2), m_h2((h+1)/2), m_pitch(0), m_coeffs(NULL)
{
create();
decompose(src);
}
~wavelet_level()
{
destroy();
}
T ** lowfreq() const
{
return m_coeffs;
}
size_t lfw() const
{
return m_w2;
}
size_t lfh() const
{
return m_h2;
}
template<class E>
void decompose(E ** src);
template<class E>
void reconstruct(E ** dst, int alpha, bool do_clip = false);
};
//////////////////////////////////////////////////////////////////////////////
template<class T>
void wavelet_level<T>::dwt_2d(size_t w, size_t h)
{
T * buffer = new T[std::max(w, h) + 4];
for(size_t j = 0; j < h; j++)
{
//dwt_haar(m_coeffs[j], 1, buffer, w);
dwt_53(m_coeffs[j], 1, buffer, w);
}
for(size_t i = 0; i < w; i++)
{
//dwt_haar(&m_coeffs[0][i], m_pitch, buffer, h);
dwt_53(&m_coeffs[0][i], m_pitch, buffer, h);
}
delete buffer;
}
template<class T>
void wavelet_level<T>::idwt_2d(size_t w, size_t h, int alpha)
{
T * buffer = new T[std::max(w, h) + 4];
for(size_t j = 0; j < h; j++)
{
//idwt_haar(m_coeffs[j], 1, buffer, w, alpha);
idwt_53(m_coeffs[j], 1, buffer, w, alpha);
}
for(size_t i = 0; i < w; i++)
{
//idwt_haar(&m_coeffs[0][i], m_pitch, buffer, h, alpha);
idwt_53(&m_coeffs[0][i], m_pitch, buffer, h, alpha);
}
delete buffer;
}
template<class T>
void wavelet_level<T>::create()
{
// 16-byte alignment: no effect
//m_pitch = (((m_w*sizeof(T) + 15) / 16) * 16) / sizeof(T);
m_pitch = m_w;
T * data = new T[m_pitch * m_h];
m_coeffs = new T*[m_h];
for(size_t j = 0; j < m_h; j++)
{
m_coeffs[j] = data + m_pitch * j;
}
}
template<class T>
void wavelet_level<T>::destroy()
{
if(m_coeffs)
{
delete[] m_coeffs[0];
delete[] m_coeffs;
}
}
template<class T> template<class E>
void wavelet_level<T>::decompose(E ** src)
{
plane_copy(src, m_coeffs, m_w, m_h);
dwt_2d(m_w, m_h);
}
template<class T> template<class E>
void wavelet_level<T>::reconstruct(E ** dst, int alpha, bool do_clip)
{
idwt_2d(m_w, m_h, alpha);
if(do_clip)
{
for(size_t j = 0; j < m_h; j++)
for(size_t i = 0; i < m_w; i++)
m_coeffs[j][i] = clip(m_coeffs[j][i], 0, 65535);
}
plane_copy(m_coeffs, dst, m_w, m_h);
}
};
#endif