Wavelet1DDlg.cpp
上传用户:whhgrj
上传日期:2013-03-18
资源大小:169k
文件大小:23k
源码类别:

波变换

开发平台:

Visual C++

  1. // Wavelet1DDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "Wavelet1D.h"
  5. #include "Wavelet1DDlg.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CAboutDlg dialog used for App About
  13. class CAboutDlg : public CDialog
  14. {
  15. public:
  16. CAboutDlg();
  17. // Dialog Data
  18. //{{AFX_DATA(CAboutDlg)
  19. enum { IDD = IDD_ABOUTBOX };
  20. //}}AFX_DATA
  21. // ClassWizard generated virtual function overrides
  22. //{{AFX_VIRTUAL(CAboutDlg)
  23. protected:
  24. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  25. //}}AFX_VIRTUAL
  26. // Implementation
  27. protected:
  28. //{{AFX_MSG(CAboutDlg)
  29. //}}AFX_MSG
  30. DECLARE_MESSAGE_MAP()
  31. };
  32. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  33. {
  34. //{{AFX_DATA_INIT(CAboutDlg)
  35. //}}AFX_DATA_INIT
  36. }
  37. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  38. {
  39. CDialog::DoDataExchange(pDX);
  40. //{{AFX_DATA_MAP(CAboutDlg)
  41. //}}AFX_DATA_MAP
  42. }
  43. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  44. //{{AFX_MSG_MAP(CAboutDlg)
  45. // No message handlers
  46. //}}AFX_MSG_MAP
  47. END_MESSAGE_MAP()
  48. /////////////////////////////////////////////////////////////////////////////
  49. // CWavelet1DDlg dialog
  50. // 参数初始化
  51. CWavelet1DDlg::CWavelet1DDlg(CWnd* pParent /*=NULL*/)
  52. : CDialog(CWavelet1DDlg::IDD, pParent)
  53. {
  54. //{{AFX_DATA_INIT(CWavelet1DDlg)
  55. // NOTE: the ClassWizard will add member initialization here
  56. m_bWavelet = FALSE;
  57. m_strBmpFile=_T("Sample.bmp");
  58. m_nDecomposeStage = 1;
  59. m_nDisplayStage   = 1;
  60.     m_nFilterLen      = 6;
  61. m_nBinGate        =100;
  62. Data = NULL;
  63. DotData = NULL;
  64. //}}AFX_DATA_INIT
  65. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  66. m_strFilterFile[0]="h1.dat";
  67. m_strFilterFile[1]="h2.dat";
  68. m_strFilterFile[2]="h3.dat";
  69. m_strFilterFile[3]="h4.dat";
  70. m_strFilterFile[4]="h5.dat";
  71. m_strFilterFile[5]="h6.dat";
  72. m_strFilterFile[6]="h7.dat";
  73. m_strFilterFile[7]="h8.dat";
  74. m_strFilterFile[8]="h9.dat";
  75. m_strFilterFile[9]="h10.dat";
  76. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  77. }
  78. void CWavelet1DDlg::DoDataExchange(CDataExchange* pDX)
  79. {
  80. CDialog::DoDataExchange(pDX);
  81. //{{AFX_DATA_MAP(CWavelet1DDlg)
  82. DDX_Control(pDX, IDC_COMBO_DISPLAYSTAGE, m_combDisplayStage);
  83. DDX_Control(pDX, IDC_COMBO_FILTERLEN, m_combFilterLen);
  84. DDX_Control(pDX, IDC_COMBO_STAGE, m_combDecomposeStage);
  85. DDX_Control(pDX, IDC_EDIT_BMPFILE, m_editBmpFile);
  86. //}}AFX_DATA_MAP
  87. }
  88. BEGIN_MESSAGE_MAP(CWavelet1DDlg, CDialog)
  89. //{{AFX_MSG_MAP(CWavelet1DDlg)
  90. ON_WM_SYSCOMMAND()
  91. ON_WM_PAINT()
  92. ON_WM_QUERYDRAGICON()
  93. ON_BN_CLICKED(IDC_BUTTON_BMPFILE, OnBtnBmpFile)
  94. ON_BN_CLICKED(IDC_BUTTON_WAVELET1D, OnBtnWavelet1D)
  95. ON_CBN_SELCHANGE(IDC_COMBO_DISPLAYSTAGE, OnSelchangeCombDisplayStage)
  96. ON_CBN_EDITCHANGE(IDC_COMBO_DISPLAYSTAGE, OnEditchangeCombDisplayStage)
  97. ON_CBN_EDITCHANGE(IDC_COMBO_DECOMPOSESTAGE, OnEditchangeCombDecomposeStage)
  98. ON_CBN_EDITCHANGE(IDC_COMBO_FILTERLEN, OnEditchangeCombFilterLen)
  99. //}}AFX_MSG_MAP
  100. END_MESSAGE_MAP()
  101. /////////////////////////////////////////////////////////////////////////////
  102. // CWavelet1DDlg message handlers
  103. BOOL CWavelet1DDlg::OnInitDialog()
  104. {
  105. CDialog::OnInitDialog();
  106. // Add "About..." menu item to system menu.
  107. // IDM_ABOUTBOX must be in the system command range.
  108. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  109. ASSERT(IDM_ABOUTBOX < 0xF000);
  110. CMenu* pSysMenu = GetSystemMenu(FALSE);
  111. if (pSysMenu != NULL)
  112. {
  113. CString strAboutMenu;
  114. strAboutMenu.LoadString(IDS_ABOUTBOX);
  115. if (!strAboutMenu.IsEmpty())
  116. {
  117. pSysMenu->AppendMenu(MF_SEPARATOR);
  118. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  119. }
  120. }
  121. // Set the icon for this dialog.  The framework does this automatically
  122. //  when the application's main window is not a dialog
  123. SetIcon(m_hIcon, TRUE); // Set big icon
  124. SetIcon(m_hIcon, FALSE); // Set small icon
  125. // TODO: Add extra initialization here
  126. // 初始化控件
  127. m_editBmpFile.SetWindowText(m_strBmpFile);
  128. CString strComb;
  129. int k=0;
  130. for(k=0;k<6;k++)
  131.     strComb.Format("%d",k+1);
  132.     m_combDecomposeStage.InsertString(k,strComb);
  133.         m_combDecomposeStage.SetItemData(k,k+1);
  134.         m_combDecomposeStage.SetCurSel(0);
  135. }
  136. strComb.Format("%d",1);
  137. m_combFilterLen.InsertString(0,strComb);
  138.     m_combFilterLen.SetItemData(0,2);
  139. for(k=1;k<10;k++)
  140.     strComb.Format("%d",2*(k+1));
  141.     m_combFilterLen.InsertString(k,strComb);
  142.         m_combFilterLen.SetItemData(k,2*(k+1));
  143.         m_combFilterLen.SetCurSel(2);
  144. }
  145. m_combDisplayStage.EnableWindow(FALSE);
  146. return TRUE;  // return TRUE  unless you set the focus to a control
  147. }
  148. void CWavelet1DDlg::OnSysCommand(UINT nID, LPARAM lParam)
  149. {
  150. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  151. {
  152. CAboutDlg dlgAbout;
  153. dlgAbout.DoModal();
  154. }
  155. else
  156. {
  157. CDialog::OnSysCommand(nID, lParam);
  158. }
  159. }
  160. // If you add a minimize button to your dialog, you will need the code below
  161. //  to draw the icon.  For MFC applications using the document/view model,
  162. //  this is automatically done for you by the framework.
  163. void CWavelet1DDlg::OnPaint() 
  164. {
  165. if (IsIconic())
  166. {
  167. CPaintDC dc(this); // device context for painting
  168. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  169. // Center icon in client rectangle
  170. int cxIcon = GetSystemMetrics(SM_CXICON);
  171. int cyIcon = GetSystemMetrics(SM_CYICON);
  172. CRect rect;
  173. GetClientRect(&rect);
  174. int x = (rect.Width() - cxIcon + 1) / 2;
  175. int y = (rect.Height() - cyIcon + 1) / 2;
  176. // Draw the icon
  177. dc.DrawIcon(x, y, m_hIcon);
  178. }
  179. else
  180. {
  181. CDialog::OnPaint();
  182.      if(m_bWavelet)
  183.    DrawWavelet1D();
  184. }
  185. }
  186. // The system calls this to obtain the cursor to display while the user drags
  187. //  the minimized window.
  188. HCURSOR CWavelet1DDlg::OnQueryDragIcon()
  189. {
  190. return (HCURSOR) m_hIcon;
  191. }
  192. void CWavelet1DDlg::OnSelchangeCombDisplayStage() 
  193. {
  194. m_nDisplayStage=m_combDisplayStage.GetItemData(m_combDisplayStage.GetCurSel());
  195. DrawWavelet1D();
  196. }
  197. void CWavelet1DDlg::OnEditchangeCombDisplayStage() 
  198. {
  199. m_combDisplayStage.SetCurSel(1);
  200. }
  201. void CWavelet1DDlg::OnEditchangeCombDecomposeStage() 
  202. {
  203. m_combDecomposeStage.SetCurSel(0);
  204. }
  205. void CWavelet1DDlg::OnEditchangeCombFilterLen() 
  206. {
  207.     m_combFilterLen.SetCurSel(2);
  208. }
  209. // 选择原始数据图像文件
  210. void CWavelet1DDlg::OnBtnBmpFile() 
  211. {
  212. CFileDialog BmpFileDlg(TRUE,"bmp","*.bmp");
  213. if(BmpFileDlg.DoModal()==IDOK)
  214. {
  215.    m_strBmpFile=BmpFileDlg.GetPathName();
  216.    m_editBmpFile.SetWindowText(m_strBmpFile);
  217.    m_bWavelet=FALSE;
  218. }
  219. }
  220. // 确定退出
  221. void CWavelet1DDlg::OnOK() 
  222. {
  223. // 若已进行过小波变换,则所用资源
  224. if(m_bWavelet)
  225. {
  226.    ReleaseMemory();
  227. }
  228. CDialog::OnOK();
  229. }
  230. // “一维小波变换”按钮消息处理函数
  231. // 功能:打开文件,分配内存,进行变换,绘制结果
  232. void CWavelet1DDlg::OnBtnWavelet1D() 
  233. {
  234. CFile BmpFile;
  235. CFileException fe;
  236. // 打开原始数据图像文件
  237. if(m_strBmpFile.IsEmpty())
  238. {
  239. AfxMessageBox (_T("请选择一个位图(*.bmp)文件!"),MB_ICONINFORMATION|MB_OK,NULL);
  240.     return;
  241. }
  242. if(!BmpFile.Open(m_strBmpFile,CFile::modeRead,&fe))
  243. {
  244. AfxMessageBox (_T("打开文件失败!"),MB_ICONINFORMATION|MB_OK,NULL);
  245.     return;
  246. }
  247. // 若已进行过小波变换,则释放上次变换所用资源
  248. if(m_bWavelet)
  249. {
  250.    ReleaseMemory();
  251. }
  252. // 读取原始数据图像文件
  253. TRY
  254. {
  255. DIB = ::ReadDIBFile(BmpFile);
  256. }
  257. CATCH (CFileException, eLoad)
  258. {
  259. BmpFile.Abort();  // 读取失败
  260. AfxMessageBox (_T("读取数据失败!"),MB_ICONINFORMATION|MB_OK,NULL);
  261. DIB = NULL;         // 设置DIB为空
  262. return ;
  263. }
  264. END_CATCH
  265. // 锁定DIB
  266. lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)GetHDIB());
  267. //打开待处理图像
  268. // 判断是否是8-bpp位图
  269. if (::DIBNumColors(lpDIB) > 256||m_nImageWidth>=400||m_nImageHeight>=300)
  270. {
  271. // 提示用户
  272. AfxMessageBox(_T("不是256色位图或者图像过大!") , MB_ICONINFORMATION | MB_OK,NULL);
  273. // 解除锁定
  274. ::GlobalUnlock((HGLOBAL) GetHDIB());
  275. return ;
  276. }
  277. // 得到原始数据图像的宽度和高度
  278. m_nImageWidth=::DIBWidth(lpDIB);
  279. m_nImageHeight=::DIBHeight(lpDIB);
  280. // 更改光标形状
  281. BeginWaitCursor();
  282. // 找到DIB图像象素起始位置
  283. lpDIBBits = ::FindDIBBits(lpDIB);
  284. // 得到小波变换所需的层次、滤波器长度等参数
  285. GetParam();
  286. // 获取滤波器参数
  287. if(!GetHn())
  288. return;
  289. // 给Data数组分配内存
  290. if(!GetMemory())
  291. return;
  292. // 将原始数据图像二值化并投影,将其存储到Data[0]中
  293. PrepareData();
  294. // 对Data[0]中数据进行小波变换
  295. Wavelet1D();
  296. // 绘制小波变换结果
  297. DrawWavelet1D();
  298.   // 解除锁定
  299. ::GlobalUnlock((HGLOBAL)GetHDIB());
  300. // 恢复光标
  301. EndWaitCursor();
  302.     // 设置已进行过小波变换标志
  303. m_bWavelet=TRUE;
  304. }
  305. // 得到小波变换所需的层次、滤波器长度等参数
  306. void CWavelet1DDlg::GetParam()
  307. {
  308. // 得到要进行小波变换的层次
  309. if(m_combDecomposeStage.GetCurSel()==CB_ERR)
  310.    m_nDecomposeStage=1;
  311. else
  312.        m_nDecomposeStage=m_combDecomposeStage.GetItemData(m_combDecomposeStage.GetCurSel());
  313. // 得到滤波器长度
  314. if(m_combFilterLen.GetCurSel()==CB_ERR)
  315.    m_nFilterLen=6;
  316. else
  317.    m_nFilterLen=m_combFilterLen.GetItemData(m_combFilterLen.GetCurSel());
  318.     // 显示第一层小波变换后的结果
  319.     m_nDisplayStage=1;
  320.     // 只有在进行小波变换后才能初始化显示变换结果层次的Comb控件
  321. CString strComb;
  322. m_combDisplayStage.EnableWindow(TRUE);
  323.     m_combDisplayStage.ResetContent();
  324. for(int k=0;k<=m_nDecomposeStage;k++)
  325. {
  326.     strComb.Format("%d",k);     
  327. m_combDisplayStage.InsertString(k,strComb);
  328.         m_combDisplayStage.SetItemData(k,k);
  329.         m_combDisplayStage.SetCurSel(1);
  330. }
  331. }
  332. // 将原始数据图像二值化并投影,将其存储到Data[0]中
  333. void CWavelet1DDlg::PrepareData()
  334. {
  335.     // 原始数据图像二值化及垂直、水平方向投影
  336. // DotData[i]存放投影后一维待变换数据
  337. // Data[0][i]同DotData[i],存放投影后一维待变换数据
  338. // Data[1][i]存放一层小波变换后数据,依此类推
  339. int temp;
  340.     int i,j;
  341.     for(i=0;i<m_nImageHeight+m_nImageWidth;i++)
  342.     *(DotData+i)=0;
  343.     for(i=0;i<m_nImageHeight;i++)
  344.    for(j=0;j<m_nImageWidth;j++)
  345.    {  
  346.            temp=*((unsigned char *)lpDIBBits+m_nImageWidth*i+j);
  347.    if(temp<=m_nBinGate)
  348.    {
  349.   (*(DotData+i))++;
  350.   (*(DotData+m_nImageHeight+j))++;
  351.   *((unsigned char *)lpDIBBits+m_nImageWidth*i+j)=0;
  352.    }
  353.    else
  354.    {
  355.    *((unsigned char *)lpDIBBits+m_nImageWidth*i+j)=255;
  356.    }
  357.    }
  358. // 将二值化后图像点阵投影数据读入Data数组
  359. for(i=0;i<m_nImageHeight+m_nImageWidth;i++)
  360. Data[0][i]=DotData[i];
  361. }
  362. // 一维小波变换
  363. void CWavelet1DDlg::Wavelet1D()
  364. {
  365.      int i,j;
  366.  for(i=1;i<=m_nDecomposeStage;i++)
  367.  {
  368.      // 复制数据
  369.  for(j=0;j<(m_nImageWidth+m_nImageHeight);j++)
  370.      Data[i][j]=Data[i-1][j];
  371.  // 第i层小波变换
  372.          if(!DecompStage(i,m_nFilterLen))
  373.  {
  374.  AfxMessageBox("变换失败!",MB_OK|MB_ICONINFORMATION);
  375.      break;
  376.  }
  377.  }
  378. }
  379. // 得到滤波器参数
  380. BOOL CWavelet1DDlg::GetHn()
  381. {
  382.      int i;
  383.  double temp1;
  384.  FILE *fp1;
  385.  if((fp1=fopen(m_strFilterFile[m_nFilterLen/2-1],"rb+"))==NULL)
  386.  {
  387.     AfxMessageBox("打开Hn数据文件失败!",MB_OK|MB_ICONINFORMATION);
  388. return FALSE;
  389.  }
  390.  for(i=0;i<30;i++)
  391.  h[i]=0;
  392.  for(i=0;i<m_nFilterLen;i++)
  393.  {
  394.     fread(&temp1,sizeof(double),1,fp1);
  395. h[i]=temp1;
  396.  }
  397.  fclose(fp1);
  398.      return TRUE;
  399. }
  400. // 分配小波变换所需内存
  401. BOOL CWavelet1DDlg::GetMemory()
  402. {
  403.     BOOL flag=TRUE;
  404.     Data=new double *[m_nImageHeight];
  405. for(int n=0;n<=m_nDecomposeStage;n++)
  406. {
  407. *(Data+n)=new double[sizeof(double)*m_nImageWidth];
  408.     if(*(Data+n)==NULL)
  409.    flag=FALSE;
  410. }
  411. DotData=new double[sizeof(double)*(m_nImageWidth+m_nImageHeight)];
  412. if(DotData==NULL)
  413. flag=FALSE;
  414.     return flag;
  415. }
  416. // 释放小波变换所用内存资源
  417. void CWavelet1DDlg::ReleaseMemory()
  418. {
  419.    for(int k=0;k<m_nDecomposeStage;k++)
  420.    if(*(Data+k))
  421.      delete *(Data+k);
  422.    if(Data)
  423.    {
  424.   delete []Data; 
  425.   Data=NULL;
  426.    }
  427.    if(DotData)
  428.    {
  429.   delete DotData;
  430.   DotData=NULL;
  431.    }
  432.    if(DIB)
  433.    { 
  434.   ::GlobalFree((HGLOBAL) DIB);
  435.   DIB=NULL;
  436.    } 
  437. }
  438. // 返回H算子周期化后得值
  439. double CWavelet1DDlg::HH(int i,int m)
  440. {
  441.      return h[i+m];
  442. }
  443. // 返回G算子周期化后的值
  444. double CWavelet1DDlg::GG(int i, int m)
  445. {
  446.      char flag;
  447.  if(i%2)
  448.  flag=-1;
  449.  else
  450.  flag=1;
  451.  return HH(-1*i+1,m)*flag;
  452. }
  453. // H算子周期化过程
  454. BOOL CWavelet1DDlg::HHH(int level,int size)
  455. {
  456.      int len,m,i;
  457.  double temp;
  458.  int sign;
  459.  len=size>>level;
  460.  m=m_nFilterLen/2;
  461.  if((ph=new double[sizeof(double)*len])==NULL)
  462.  {
  463.     AfxMessageBox("H算子内存分配失败!",MB_OK|MB_ICONINFORMATION);
  464. return FALSE;
  465.  }
  466.  for(sign=0;sign<len;sign++)
  467.  {
  468.      temp=0;
  469.  for(i=(-1*m+1);i<=m;i++)
  470.  {
  471.      if(((sign-i)%len)==0)
  472.      temp+=HH(i-1,m);
  473.  }
  474.  ph[sign]=temp;
  475.  }
  476.  return TRUE;
  477. }
  478. // G算子周期化过程
  479. BOOL CWavelet1DDlg::GGG(int level,int size)
  480. {
  481.      int len,m,i;
  482.  double temp;
  483.  int sign;
  484.  len=size>>level;
  485.  m=m_nFilterLen/2;
  486.  if((pg=new double[sizeof(double)*len])==NULL)
  487.  {
  488.     AfxMessageBox("G算子内存分配失败!",MB_OK|MB_ICONINFORMATION);
  489. return FALSE;
  490.  }
  491.  for(sign=0;sign<len;sign++)
  492.  {
  493.      temp=0;
  494.  for(i=(-1*m+3);i<=m+2;i++)
  495.  {
  496.      if(((sign-i)%len)==0)
  497.      temp+=GG(i-1,m);
  498.  }
  499.  pg[sign]=temp;
  500.  }
  501.  return TRUE;
  502. }
  503. // H算子作用于一维数据
  504. void CWavelet1DDlg::HOperatorOn(int filterlen, int start, int len,int level)
  505. {
  506.      int i,i2,m,k,len1;
  507.  double temp1;
  508.  m=m_nFilterLen/2;
  509.  len1=len>>1;
  510.  for(i=0;i<len1;i++)
  511.  {
  512.      i2=2*i;
  513.  Data[level][i+start]=0;
  514.  if(len>filterlen)
  515.  {
  516.     for(k=i2-len;k<=i2-len+m;k++)
  517. {
  518.     if((k>=0)&&(k<len))
  519. if((temp1=ph[(k-i2+len)%len])!=0)
  520. Data[level][i+start]+=temp1*Data[level-1][k+start];
  521. }
  522. for(k=i2-m+1;k<=i2+m;k++)
  523. {
  524.     if((k>=0)&&(k<len))
  525. if((temp1=ph[(k-i2+len)%len])!=0)
  526. Data[level][i+start]+=temp1*Data[level-1][k+start];
  527. }
  528. for(k=i2+len-m+1;k<=i2+len;k++)
  529. {
  530.     if((k>=0)&&(k<len))
  531. if((temp1=ph[(k-i2+len)%len])!=0)
  532. Data[level][i+start]+=temp1*Data[level-1][k+start];
  533. }
  534.  }
  535.  else
  536.  {
  537.     for(k=0;k<len;k++)
  538. {
  539.     if((temp1=ph[(k-i2+len)%len])!=0)
  540. Data[level][i+start]+=temp1*Data[level-1][k+start];
  541. }
  542.  }
  543.  }
  544. }
  545. // G算子作用于一维数据
  546. void CWavelet1DDlg::GOperatorOn(int filterlen, int start, int len,int level)
  547. {
  548.  int i,i2,m,k,len1;
  549.  double temp1;
  550.  m=m_nFilterLen/2;
  551.  len1=len>>1;
  552.  for(i=0;i<len1;i++)
  553.  {
  554.      i2=2*i;
  555.  Data[level][i+start+len1]=0;
  556.  if(len>filterlen)
  557.  {
  558.     for(k=i2-len;k<=i2-len+m+2;k++)
  559. {
  560.     if((k>=0)&&(k<len))
  561. if((temp1=pg[(k-i2+len)%len])!=0)
  562. Data[level][i+start+len1]+=temp1*Data[level-1][k+start];
  563. }
  564. for(k=i2-m+3;k<=i2+m+2;k++)
  565. {
  566.     if((k>=0)&&(k<len))
  567. if((temp1=pg[(k-i2+len)%len])!=0)
  568. Data[level][i+start+len1]+=temp1*Data[level-1][k+start];
  569. }
  570. for(k=i2+len-m+3;k<=i2+len;k++)
  571. {
  572.     if((k>=0)&&(k<len))
  573. if((temp1=pg[(k-i2+len)%len])!=0)
  574. Data[level][i+start+len1]+=temp1*Data[level-1][k+start];
  575. }
  576.  }
  577.  else
  578.  {
  579.     for(k=0;k<len;k++)
  580. {
  581.     if((temp1=pg[(k-i2+len)%len])!=0)
  582. Data[level][i+start+len1]+=temp1*Data[level-1][k+start];
  583. }
  584.  }
  585.  }
  586. }
  587. // 对一维数据进行level层小波变换
  588. BOOL CWavelet1DDlg::DecompStage(int level, int filterlen)
  589. {
  590.      int start,len;
  591.  len=(m_nImageWidth+m_nImageHeight)>>(level-1);
  592.  start=0;
  593.  if((!HHH(level-1,m_nImageWidth+m_nImageHeight))||(!GGG(level-1,m_nImageWidth+m_nImageHeight)))
  594.      return FALSE;
  595.  HOperatorOn(filterlen,start,len,level);
  596.  GOperatorOn(filterlen,start,len,level);
  597.  if(ph&&pg)
  598.  {
  599.     delete  ph;
  600. delete  pg;
  601. ph=NULL;
  602. pg=NULL;
  603.  }
  604.  return TRUE;     
  605. }
  606. // 绘制m_nDisplayStage指定层次的小波变换结果
  607. void CWavelet1DDlg::DrawWavelet1D()
  608. {
  609. // 创建绘图所需资源
  610. int Ox=0,Oy=0;
  611. int Ox1=0,Oy1=0,Ox2=0,Oy2=0;
  612. CString Text=_T("");
  613. CPen *OldPen,PenWhite,PenGreen,PenBlue,Pen;
  614. CPen* OldPen2;
  615. PenWhite.CreatePen(PS_SOLID,1,0x00FFFFFF);
  616. PenGreen.CreatePen(PS_SOLID,1,0x0000FF00);
  617. PenBlue.CreatePen(PS_SOLID,1,0x00FF0000);
  618. Pen.CreatePen(PS_SOLID,1,0x00FFFFFF);
  619. CDC* pDC=GetDC();
  620.     CRect RectClient,Workarea;
  621.     GetClientRect(RectClient);
  622. // 锁定DIB
  623. lpDIB = (LPSTR)::GlobalLock((HGLOBAL) GetHDIB());
  624.     // 在对话框右上部分绘制原始数据图像及二值化后点阵投影图像
  625. int temp;
  626.     int i,j;
  627. // 创建绘制区
  628. Workarea.left=RectClient.left+(RectClient.right-RectClient.left)/5*2;
  629.     Workarea.right=RectClient.right-10;
  630.     Workarea.top=RectClient.top+10;
  631. Workarea.bottom=RectClient.top+(RectClient.bottom-RectClient.top-10)/2+40;
  632.     pDC->Rectangle(Workarea);
  633.     pDC->SetBkColor(0x00FFFFFF);
  634.     // 绘制坐标轴
  635. Ox = Workarea.left+20;    Oy = Workarea.bottom-20;
  636. pDC->MoveTo(Ox,Oy);
  637. pDC->LineTo(Ox,Workarea.top+10);
  638. pDC->MoveTo(Ox,Oy);
  639. pDC->LineTo(Workarea.right-10,Oy);
  640.     // 绘制二值化后数据图像
  641.     Ox1= Ox+m_nImageWidth;           Oy1= Oy-m_nImageHeight;
  642. pDC->MoveTo(Ox1,Oy1);
  643. pDC->LineTo(Ox1,Oy1-m_nImageHeight);
  644. pDC->LineTo(Ox1+m_nImageWidth,Oy1-m_nImageHeight);
  645. pDC->LineTo(Ox1+m_nImageWidth,Oy1);
  646. pDC->LineTo(Ox1,Oy1);
  647. pDC->SetTextColor(0x000000FF);
  648. pDC->TextOut(Ox,Workarea.top+3,"原始数据图像二值化及投影图");
  649. OldPen=pDC->SelectObject(&PenBlue);
  650.     for(i=0;i<m_nImageHeight;i++)
  651.    for(j=0;j<m_nImageWidth;j++)
  652.    {  
  653.            temp=*((unsigned char *)lpDIBBits+m_nImageWidth*i+j);
  654.    if(temp<=m_nBinGate)
  655.    {
  656.   *((unsigned char *)lpDIBBits+m_nImageWidth*i+j)=0;   
  657.   pDC->MoveTo(Ox1+j,Oy1-i);
  658.   pDC->LineTo(Ox1+j,Oy1-i-2);
  659.   OldPen2=pDC->SelectObject(&PenWhite);
  660.   pDC->LineTo(Ox1+j,Oy1-i-1);
  661.   pDC->SelectObject(OldPen2);
  662.    }
  663.    else
  664.    {
  665.    *((unsigned char *)lpDIBBits+m_nImageWidth*i+j)=255;
  666.    }
  667.    }
  668. // 绘制垂直和水平方向的投影
  669.     for(i=0;i<m_nImageHeight;i++)
  670. {
  671.     temp=Data[0][i];
  672. pDC->MoveTo(Ox,Oy1-i);
  673. pDC->LineTo(Ox+temp,Oy1-i);
  674. }
  675. for(j=0;j<m_nImageWidth;j++)
  676. {
  677.     temp=Data[0][m_nImageHeight+j];
  678. pDC->MoveTo(Ox1+j,Oy);
  679. pDC->LineTo(Ox1+j,Oy-temp);
  680. }
  681.     pDC->SelectObject(OldPen);
  682. // 在对话框右下部分绘制小波变换后第m_nDisplayStage层数据图像
  683. int    DataLen=0;
  684. double XUnit=1,YUnit=1,tempX=0,tempY=0;
  685. int    temp1=0,temp2=0;
  686. double max=0,min=0,scale=0;
  687.     // 创建绘制区
  688. Workarea.left=RectClient.left+(RectClient.right-RectClient.left)/5*2;
  689.     Workarea.right=RectClient.right-10;
  690. Workarea.top=RectClient.top+10+(RectClient.bottom-RectClient.top-10)/2+40;
  691.     Workarea.bottom=RectClient.bottom-10; 
  692.     pDC->Rectangle(Workarea);
  693.     pDC->SetBkColor(0x00FFFFFF);
  694. // 绘制坐标轴
  695. Ox = Workarea.left+20;    Oy = Workarea.bottom-20;
  696. pDC->MoveTo(Ox,Oy);
  697. pDC->LineTo(Ox,Workarea.top+10);
  698. pDC->MoveTo(Ox,Oy);
  699. pDC->LineTo(Workarea.right-10,Oy);
  700. // 归一化小波变换后数据并绘制
  701. max=Data[m_nDisplayStage][0];
  702. min=Data[m_nDisplayStage][0];
  703. for(j=0;j<m_nImageWidth+m_nImageHeight;j++)
  704. {   
  705. if(max<Data[m_nDisplayStage][j])
  706.    max=Data[m_nDisplayStage][j];
  707. if(min>Data[m_nDisplayStage][j])
  708.        min=Data[m_nDisplayStage][j];
  709. }
  710. scale=max-min;
  711. XUnit=double(Workarea.right-Workarea.left-30)/double(m_nImageHeight+m_nImageWidth);
  712.     YUnit=double(Workarea.bottom-Workarea.top-30-10)/scale;
  713. if(min>0)
  714.    scale=0;
  715. else
  716.    scale=(0-min)*YUnit;
  717. pDC->MoveTo(Ox,Oy-scale);
  718. pDC->LineTo(Workarea.right-10,Oy-scale);
  719. pDC->SetTextColor(0x000000FF);
  720. pDC->TextOut(Ox-10,Oy-scale-6,"O");
  721. Text.Format("Max:%f  Min:%f",max,min);
  722. pDC->TextOut(Ox+10,Workarea.top+5,Text);
  723. pDC->SelectObject(&PenBlue);
  724. for(j=0;j<m_nImageWidth+m_nImageHeight-1;j++)
  725. {
  726.     tempX=j*XUnit;
  727. tempY=(Data[m_nDisplayStage][j]-min)*YUnit;
  728.         pDC->MoveTo(tempX+Ox,Oy-tempY);
  729. tempX=(j+1)*XUnit;
  730. tempY=(Data[m_nDisplayStage][j+1]-min)*YUnit;
  731. pDC->LineTo(tempX+Ox,Oy-tempY);
  732. }
  733.     pDC->SelectObject(OldPen);
  734. // 绘制说明文字如C0,D0等
  735. DataLen=m_nImageWidth+m_nImageHeight;
  736. for(j=0;j<=m_nDisplayStage;j++)
  737. {
  738.     temp1=temp2;
  739. temp2=DataLen>>(m_nDisplayStage-j);
  740. tempX=(temp2-1)*XUnit;
  741. tempY=(Data[m_nDisplayStage][temp2-1]-min)*YUnit;
  742. pDC->MoveTo(tempX+Ox,Oy-tempY);
  743.     pDC->LineTo(tempX+Ox,Oy);
  744. if(j==0)
  745. Text.Format("C%d",m_nDisplayStage);
  746. else
  747. Text.Format("D%d",m_nDisplayStage+1-j);
  748. tempX=((temp2-temp1-1)/2+temp1)*XUnit-5;
  749. pDC->SetTextColor(0x000000FF);
  750. pDC->TextOut(Ox+tempX,Oy+3,Text);
  751. }
  752. // 释放资源
  753. PenWhite.DeleteObject();
  754. PenGreen.DeleteObject();
  755. PenBlue.DeleteObject();
  756. Pen.DeleteObject();
  757.     // 解除锁定
  758. ::GlobalUnlock((HGLOBAL)GetHDIB());
  759. }
  760. // Hn系数文件产生函数,因为Hn文件只需产生一次,所以程序中并没有使用此函数。
  761. // 若要重新产生Hn文件,读者可以调用此函数。
  762. BOOL CWavelet1DDlg::GenerateHnFile()
  763. {
  764. double Hn[10][20] ={ {0,0},
  765. { 0.4829629131445341, 0.8365163037378077, 0.2241438680420134,
  766.                      -0.1294095225512603 },
  767. { 0.3326705529500825, 0.8068915093110924, 0.4598775021184914,
  768.  -0.1350110200102546,-0.0854412738820267, 0.0352262918857095 },
  769. { 0.2303778133088964, 0.7148465705529154, 0.6308807679398587,
  770.  -0.0279837694168599,-0.1870348117190931, 0.0308413818355607,
  771.   0.0328830116668852,-0.0105974017850890 },
  772. { 0.1601023979741929, 0.6038292697971895, 0.7243085284377726,
  773.   0.1384281459013203,-0.2422948870663823,-0.0322448695846381,
  774.   0.0775714938400459,-0.0062414902127983,-0.0125807519990820,
  775.   0.0033357252854738 },
  776. { 0.1115407433501095, 0.4946238903984533, 0.7511339080210959,
  777.   0.3152503517091982,-0.2262646939654400,-0.1297668675672625,
  778.   0.0975016055873225, 0.0275228655303053,-0.0315820393174862,
  779.   0.0005538422011614, 0.0047772575109455, 0.0010773010853085 },
  780. { 0.0778520540850037, 0.3965393194818912, 0.7291320908461957,
  781.   0.4697822874051889,-0.1439060039285212,-0.2240361549938412,
  782.   0.0713092192668272, 0.0806123091510774,-0.0380299369350104,
  783.  -0.0165745416306655, 0.0125509985560986, 0.0004295779729214,
  784.  -0.0018016407040473, 0.0003537137999745 },
  785. { 0.0544158422431072, 0.3128715909143166, 0.6756307362973195,
  786.   0.5852546836542159,-0.0158291052563823,-0.2840155429615824,
  787.   0.0004724845739124, 0.1287474266204893,-0.0173693010018090,
  788.  -0.0440882539307971, 0.0139810279174001, 0.0087160940474065,
  789.  -0.0048703529934520,-0.0003917403733770, 0.0006754494064506,
  790.  -0.0001174767841248 },
  791. { 0.0380779473638778, 0.2438346746125858, 0.6048231236900955,
  792.      0.6572880780512736, 0.1331973858249883,-0.2932737832791663,
  793.           -0.0968407832229492, 0.1485407493381256, 0.0307256814793385,
  794.  -0.0676328290613279, 0.0002509471148340, 0.0223616621236798,
  795.  -0.0047232047577518,-0.0042815036824635, 0.0018476468830563,
  796.   0.0002303857645232,-0.0002519631889427, 0.0000393473203163 },
  797. { 0.0266700579005473, 0.1881768000776347, 0.5272011889315757,
  798.   0.6884590394534363, 0.2811723436605715,-0.2498464243271598,
  799.  -0.1959462743772862, 0.1273693403357541, 0.0930573646035547,
  800.  -0.0713941471663501,-0.0294575368218399, 0.0332126740593612,
  801.   0.0036065535669870,-0.0107331754833007, 0.0013953517470688,
  802.   0.0019924052951925,-0.0006858566949564,-0.001164668551285,
  803.   0.0000935886703202,-0.0000132642028945 },
  804. };
  805. BOOL flag=TRUE;
  806. FILE *fp;
  807. int i,j;
  808. for(i=0;i<10;i++)
  809. {
  810.     if((fp=fopen(m_strFilterFile[i],"wb+"))==NULL)
  811. {
  812. AfxMessageBox("Hn算子文件生成失败!",MB_OK|MB_ICONINFORMATION);
  813.     flag=FALSE;
  814. break;
  815. }
  816.     for(j=0;j<2*(i+1);j++)
  817. fwrite(&Hn[i][j],sizeof(double),1,fp);
  818. fclose(fp);
  819. }
  820.     return flag;
  821. }