DWT.h
#if !defined(AFX_DWT_H__C2E4CEAE_A0CC_4C62_85A0_41C34344E2E0__INCLUDED_)
#define AFX_DWT_H__C2E4CEAE_A0CC_4C62_85A0_41C34344E2E0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Dib.h"
const float hCoef[10][20] =
{
{ .707106781187f, .707106781187f},
{ .482962913145f, .836516303738f, .224143868042f, -.129409522551f },
{ .332670552950f, .806891509311f, .459877502118f, -.135011020010f, -.085441273882f, .035226291882f },
{ .230377813309f, .714846570553f, .630880767930f, -.027983769417f,
-.187034811719f, .030841381836f, .032883011667f, -.010597401785f },
{ .160102397974f, .603829269797f, .724308528438f, .138428145901f, -.242294887066f,
-.032244869585f, .077571493840f, -.006241490213f, -.012580751999f, .003335725285f },
{ .111540743350f, .494623890398f, .751133908021f, .315250351709f, -.226264693965f,
-.129766867567f, .097501605587f, .027522865530f, -.031582039318f, .000553842201f,
.004777257511f, -.001077301085f },
{ .077852054085f, .396539319482f, .729132090846f, .469782287405f, -.143906003929f,
-.224036184994f, .071309219267f, .080612609151f, -.038029936935f, -.016574541631f,
.012550998556f, .000429577973f, -.001801640704f, .000353713800f },
{ .054415842243f, .312871590914f, .675630736297f, .585354683654f, -.015829105256f,
-.284015542962f, .000472484574f, .128747426620f, -.017369301002f, -.044088253931f,
.013981027917f, .008746094047f, -.004870352993f, -.000391740373f, .000675449406f,
-.000117476784f },
{ .038077947364f, .243834674613f, .604823123690f, .657288078051f, .133197385825f,
-.293273783279f, -.096840783223f, .148540749338f, .030725681479f, -.067632829061f,
.000250947115f, .022361662124f, -.004723204758f, -.004281503682f, .001847646883f,
.000230385764f, -.000251963189f, .000039347320f },
{ .026670057901f, .188176800078f, .527201188932f, .688459039454f, .281172343661f,
-.249846424327f, -.195946274377f, .127369340336f, .093057364604f, -.071394147166f,
-.029457536822f, .033212674059f, .003606553567f, -.010733175483f, .001395351747f,
.001992405295f, -.000685856695f, -.000116466855f, .000093588670f, -.000013264203f }
};
class CDWT
{
public:
void SetPara(int Supp, BOOL bOptimize);
BOOL CanDWT(int Inv);
BOOL DibDWTStep ( int Inv );
CDWT();
virtual ~CDWT();
int InitDWT ( CDib* pDib );
private:
CDib *m_pDib;
int m_iHeight, m_iWidth;
int m_iMaxWLevel, m_iMaxHLevel, m_iMaxLevel;
int m_iSupp, m_iByte;
BOOL m_bOptimize;
public:
int m_iCurDepth;
float *m_pfBuf;
protected:
BOOL DWTStep_1D (float *pfBuf, int CurLevel, int Inv=0, int Step=1);
BOOL DWTStep_2D(int Inv, int Step);
inline int Log2 (int n);
inline char FloatToChar(float f);
inline BYTE FloatToByte(float f);
};
#endif // !defined(AFX_DWT_H__C2E4CEAE_A0CC_4C62_85A0_41C34344E2E0__INCLUDED_)
DWT.cpp
// DWT.cpp: implementation of the CDWT class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DWT.h"
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDWT::CDWT()
{
m_pDib = NULL;
m_pfBuf = NULL;
m_iMaxLevel = 0;
m_iCurDepth = 0;
m_iSupp = 1;
m_iByte = 1;
m_bOptimize = FALSE;
}
CDWT::~CDWT()
{
if ( m_pfBuf )
delete m_pfBuf;
}
CDWT::InitDWT ( CDib *pDib )
{
m_pDib = pDib;
if ( m_pfBuf )
delete m_pfBuf;
m_iWidth = m_pDib->Width();
m_iHeight = m_pDib->Height();
m_iMaxWLevel = Log2(m_iWidth);
m_iMaxHLevel = Log2(m_iHeight);
if ( ( m_iWidth != 1<<m_iMaxWLevel ) || (m_iHeight != 1<<m_iMaxHLevel) )
return FALSE;
m_iMaxLevel = __min(m_iMaxWLevel, m_iMaxHLevel);
m_iByte = m_pDib->GetBitCount()/8;
return TRUE;
}
BOOL CDWT::DibDWTStep(int Inv)
{
int i, j, k;
int BPL = m_pDib->GetLineSize();
BYTE *pBits;
float *pfBuf;
if ( !m_pfBuf )
{
m_pfBuf = new float[m_iWidth*m_iHeight*m_iByte];
if ( !m_pfBuf )
return FALSE;
pfBuf = m_pfBuf;
for ( k = 0; k < m_iByte; k++ )
{
pBits = m_pDib->GetBmBitsPtr()+m_iHeight*BPL;
for ( j = 0; j < m_iHeight; j++ )
{
pBits -= BPL;
for ( i = 0; i < m_iWidth; i++ )
pfBuf[i] = pBits[i*m_iByte+k];
pfBuf+=m_iWidth;
}
}
}
if (!DWTStep_2D(Inv, 1))
return FALSE;
if (Inv)
m_iCurDepth--;
else
m_iCurDepth++;
int lfw = m_iWidth>>m_iCurDepth, lfh = m_iHeight>>m_iCurDepth;
pfBuf = m_pfBuf;
for ( k = 0; k < m_iByte; k++ )
{
pBits = m_pDib->GetBmBitsPtr()+m_iHeight*BPL;
for ( j = 0; j < m_iHeight; j++ )
{
pBits -= BPL;
for ( i = 0; i < m_iWidth; i++ )
{
if ( ( j < lfh ) && ( i < lfw ) )
pBits[i*m_iByte+k] = FloatToByte(pfBuf[i]);
else
pBits[i*m_iByte+k] = (m_bOptimize)?BYTE(FloatToChar(pfBuf[i]) ^ 0x80):
BYTE(FloatToChar(pfBuf[i]));
}
pfBuf+=m_iWidth;
}
}
return TRUE;
}
BOOL CDWT::DWTStep_2D(int Inv, int Step)
{
int Width = 1<<m_iMaxWLevel;
int Height = 1<<m_iMaxHLevel;
int CurWLevel = m_iMaxWLevel-m_iCurDepth;
int CurHLevel = m_iMaxHLevel-m_iCurDepth;
int CurW = 1<<CurWLevel;
int CurH = 1<<CurHLevel;
if (!Inv)
{
for ( int k = 0; k < m_iByte; k++ )
for ( int i = 0; i < CurH; i++ )
if (!DWTStep_1D(m_pfBuf+k*Width*Height+(int)i*Width, CurWLevel, Inv, Step))
return FALSE;
for ( k = 0; k < m_iByte; k++ )
for ( int i = 0; i < CurW; i++ )
if (!DWTStep_1D(m_pfBuf+k*Width*Height+i, CurHLevel, Inv, Width))
return FALSE;
}
else
{
CurW <<= 1;
CurH <<= 1;
for ( int k = 0; k < m_iByte; k++ )
for ( int i = 0; i < CurW; i++ )
if (!DWTStep_1D(m_pfBuf+k*Width*Height+i, CurHLevel, Inv, Width))
return FALSE;
for ( k = 0; k < m_iByte; k++ )
for ( int i = 0; i < CurH; i++ )
if (!DWTStep_1D(m_pfBuf+k*Width*Height+(int)i*Width, CurWLevel, Inv, Step))
return FALSE;
}
return TRUE;
}
BYTE CDWT::FloatToByte(float f)
{
return (f<=0)?((BYTE)0):((f>=255)?(BYTE)255:(BYTE)(f+0.5));
}
char CDWT::FloatToChar(float f)
{
if (f>=0)
return (f>=127.0)?(char)127:(char)(f+0.5);
else
return (f<=-128)?(char)-128:-(char)(-f+0.5);
}
int CDWT::Log2(int n)
{
int result = 0;
while (n >>= 1) result++;
return result;
}
BOOL CDWT::DWTStep_1D(float *pfBuf, int CurLevel, int Inv, int Step)
//pfBufΪҪ´¦ÀíµÄÊý¾ÝÇø£¬CurLevelΪÒѾ­×öÁ˼¸´ÎµÄһάС²¨
//Inv±íʾÊÇÕý±ä»»»¹ÊÇÄæ±ä»»Step±íʾpfBufÖÐÿ¸öÊý¾ÝµÄ¼ä¸ô
{
float s = (float) sqrt(2);
//sΪ¸ùºÅÏÂ2
float* h = (float*) hCoef[m_iSupp-1];
//hCoefΪÀëɢС²¨ÏµÊý
ASSERT(CurLevel>=0);
//ÒѾ­×öÁ˼¸´ÎС²¨£¬²»ÄÜΪ¸ºÖµ
int CurN = 1<<CurLevel;
// CurN = 2µÄCurLevel´Î·½£¬ÎªÒ»¸ö¶þ½øÖÆ1000000000 (Èô¸ÉλΪÁãµÄ¶þ½øÖÆÊý)
int iMask1 = CurN - 1, iMask2 = CurN/2 - 1;
// iMask1 Ϊһ¸ö 111111111 (±ÈÉÏÃæµÄ¶þ½øÖÆÊýÉÙһλµÄȫһÊý)
// iMask2 Ϊһ¸ö 11111111 (ÔÙ±ÈÉÏÃæµÄÊýÉÙһλµÄȫһÊý)
if (Inv) CurN <<= 1;
if (m_iSupp<1 || m_iSupp>10 || CurN<2*m_iSupp) return FALSE;
float *ptemp = new float[CurN];
//CurN ´ú±í
// Õý±ä»» ±ÈÈçÏÖÊÇ512ÏóËØ£¬ÔòΪ512ÏóËØ
// Äæ±ä»» ±ÈÈçÏÖÊÇ256ÏóËØ£¬ÔòΪ512ÏóËØ
if (!ptemp) return FALSE;
float s1, s2;
int Index1, Index2;
//pfBufµÄϱê
//ÏÂÃæ·Ö±ðÒÔ¶Ô1) 512¡Á512µÄͼÏóÒÔ¼ä¸ôΪ1×÷µÚÒ»´ÎС²¨±ä»» width=512
// 2) 256¡Á256µÄͼÏóÒÔ¼ä¸ôΪ3×÷µÚÒ»´ÎС²¨±ä»» width=512
if (!Inv)
{ // DWT
Index1 = 0, Index2 = 2*m_iSupp-1;
// 1) index1=0, index2=1
// 2) index1=0, index2=5
for ( int i = 0; i < CurN/2; i++ )
// 1)CurN=512, CurN/2=256
// i´Ó0µ½255
// ptemp[512]
// 2)CurN=256, CurN/2=128
// i´Ó0µ½127
// ptemp[256]
{
s1 = s2 = 0;
float t = -1;
for ( int j = 0; j < 2*m_iSupp; j++, t = -t )
{// 1) j´Ó0µ½1, t½»Ìæ+1,-1
// 2) j´Ó0µ½5, t½»Ìæ+1,-1
s1 += h[j]*pfBuf[(Index1 & iMask1) * Step];
// 1) s1=h[0]*pfBuf[0] + h[1]*pfBuf[512]
// 2) s2=h[0]*pfBuf[512¡Á0] + h[1]*pfBuf[512¡Á1] +
// h[2]*pfBuf[512¡Á2] + h[3]*pfBuf[512¡Á3] +
// h[4]*pfBuf[512¡Á4] + h[5]*pfBuf[512¡Á5]
s2 += t*h[j]*pfBuf[(Index2 & iMask1) * Step];
// 1) s1=h[0]*pfBuf[512] - h[1]*pfBuf[0]
// 2) s2=h[0]*pfBuf[512¡Á5] - h[1]*pfBuf[512¡Á4] +
// h[2]*pfBuf[512¡Á3] - h[3]*pfBuf[512¡Á2] +
// h[4]*pfBuf[512¡Á1] - h[5]*pfBuf[512¡Á0]
Index1++, Index2--;
}
ptemp[i] = s1/s;
ptemp[i+CurN/2] = s2/s;
// 1)
// ptemp[0] / ptemp[256]
// ptemp[1] / ptemp[257]
// ptemp[2] / ptemp[258]
// ......
// ptemp[255] /ptemp[511]
// 2)
// ptemp[0] / ptemp[128]
// ptemp[1] / ptemp[129]
// ptemp[2] / ptemp[130]
// ......
// ptemp[127] / ptemp[255]
Index1 -= 2*m_iSupp;
Index2 +=2*m_iSupp;
Index1 += 2;
Index2 += 2;
}
}
else
{
Index1 = CurN/2;
Index2 = CurN/2-m_iSupp+1;
for ( int i = 0; i < CurN/2; i++ )
{
s1 = s2 = 0;
int Index3 = 0;
for ( int j = 0; j < m_iSupp; j++ )
{
s1 += h[Index3]*pfBuf[(Index1 & CurN/2-1) * Step]
+h[Index3+1]*pfBuf[((Index2 & CurN/2-1) + CurN/2) * Step];
s2 += h[Index3+1]*pfBuf[(Index1 & CurN/2-1) * Step]
-h[Index3]*pfBuf[((Index2 & CurN/2-1) + CurN/2) * Step];
Index3 += 2;
Index1--;
Index2++;
}
ptemp[2*i] = s1*s;
ptemp[2*i+1] = s2*s;
Index1 += m_iSupp;
Index2 -= m_iSupp;
Index1++;
Index2++;
}
}
for ( int i = 0; i < CurN; i++ )
pfBuf[i*Step] = ptemp[i];
//½«±ä»»Ö®ºóµÄÊý×éÌæ»»Ô­À´µÄÊý×é
delete[] ptemp;
return TRUE;
}
BOOL CDWT::CanDWT(int Inv)
{
if ( Inv )
return ( m_iCurDepth > 0 );
else
return ( m_iCurDepth < m_iMaxLevel );
}
void CDWT::SetPara(int Supp, BOOL bOptimize)
{
m_iSupp = Supp;
m_bOptimize = bOptimize;
}