wavelet_utils.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:19k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: wavelet_utils.cpp,v 1.3 2005/01/30 05:11:40 gabest Exp $ $Name:  $
  4. *
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License
  8. * Version 1.1 (the "License");  you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  14. * the specific language governing rights and limitations under the License.
  15. *
  16. * The Original Code is BBC Research and Development code.
  17. *
  18. * The Initial Developer of the Original Code is the British Broadcasting
  19. * Corporation.
  20. * Portions created by the Initial Developer are Copyright (C) 2004.
  21. * All Rights Reserved.
  22. *
  23. * Contributor(s): Thomas Davies (Original Author), Scott R Ladd
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
  27. * Public License Version 2.1 (the "LGPL"), in which case the provisions of
  28. * the GPL or the LGPL are applicable instead of those above. If you wish to
  29. * allow use of your version of this file only under the terms of the either
  30. * the GPL or LGPL and not to allow others to use your version of this file
  31. * under the MPL, indicate your decision by deleting the provisions above
  32. * and replace them with the notice and other provisions required by the GPL
  33. * or LGPL. If you do not delete the provisions above, a recipient may use
  34. * your version of this file under the terms of any one of the MPL, the GPL
  35. * or the LGPL.
  36. * ***** END LICENSE BLOCK ***** */
  37. #include <libdirac_common/wavelet_utils.h>
  38. #include <libdirac_common/common.h>
  39. using namespace dirac;
  40. #include <cstdlib>
  41. // Default constructor
  42. Subband::Subband()
  43. {
  44.     // this space intentionally left blank
  45. }
  46. // Constructor
  47. Subband::Subband(int xpos,int ypos, int xlen, int ylen):
  48.     xps(xpos),
  49.     yps(ypos),
  50.     xln(xlen),
  51.     yln(ylen),
  52.     wgt(1),
  53.     qfac(8)
  54. {
  55.     // this space intentionally left blank
  56. }
  57. // Constructor
  58. Subband::Subband(int xpos,int ypos, int xlen, int ylen, int d)
  59.   : xps(xpos),
  60.     yps(ypos),
  61.     xln(xlen), 
  62.     yln(ylen),
  63.     wgt(1),
  64.     dpth(d),
  65.     qfac(8)
  66. {
  67.     // this space intentionally left blank
  68. }
  69. //! Destructor
  70. Subband::~Subband()
  71. {
  72.     // this space intentionally left blank
  73. }
  74. //subband list methods
  75. void SubbandList::Init(const int depth,const int xlen,const int ylen)
  76. {
  77.     int xl=xlen; 
  78.     int yl=ylen; 
  79.     
  80.     Clear(); 
  81.     Subband* tmp;
  82.      
  83.     for (int level = 1; level <= depth; ++level)
  84.     {
  85.         xl/=2; 
  86.         yl/=2; 
  87.         
  88.         tmp=new Subband(xl , 0 , xl , yl , level); 
  89.         AddBand( *tmp ); 
  90.         delete tmp; 
  91.         
  92.         tmp=new Subband( 0 , yl , xl , yl , level); 
  93.         AddBand( *tmp ); 
  94.         delete tmp; 
  95.         
  96.         tmp=new Subband( xl , yl , xl , yl , level); 
  97.         AddBand( *tmp ); 
  98.         delete tmp; 
  99.         
  100.         if (level == depth)
  101.         {
  102.             tmp=new Subband( 0 , 0 , xl , yl , level); 
  103.             AddBand( *tmp ); 
  104.             delete tmp; 
  105.         }        
  106.     }
  107.     //now set the parent-child relationships
  108.     int len = bands.size(); 
  109.     (*this)(len).SetParent(0);         
  110.     (*this)(len).AddChild(len-3); 
  111.     (*this)(len-3).SetParent(len); 
  112.     (*this)(len).AddChild(len-2); 
  113.     (*this)(len-2).SetParent(len); 
  114.     (*this)(len).AddChild(len-1); 
  115.     (*this)(len-1).SetParent(len); 
  116.     for (int level = 1; level < depth; ++level)
  117.     {
  118.          //do parent-child relationship for other bands
  119.         (*this)(3*level + 1).AddChild( 3*(level-1) + 1); 
  120.         (*this)(3*(level-1) + 1).SetParent(3*level + 1); 
  121.         (*this)(3*level + 2).AddChild(3*(level-1) + 2); 
  122.         (*this)(3*(level-1) + 2).SetParent(3*level + 2); 
  123.         (*this)(3*level + 3).AddChild(3*(level-1) + 3); 
  124.         (*this)(3*(level-1) + 3).SetParent(3*level + 3); 
  125.     }// level
  126. }
  127. //wavelet transform methods
  128. ///////////////////////////
  129. //public methods
  130. WaveletTransform::WaveletTransform(int d, WltFilter f)
  131.   : depth(d),
  132.     filt_sort(f)
  133. {
  134.     // this space intentionally left blank
  135. }
  136. //! Destructor
  137. WaveletTransform::~WaveletTransform()
  138. {
  139.     // this space intentionally left blank
  140. }
  141. void WaveletTransform::Transform(const Direction d, PicArray& pic_data)
  142. {
  143.     int xl,yl; 
  144.     if (d == FORWARD)
  145.     {
  146.         //do work
  147.         xl=pic_data.LengthX(); 
  148.         yl=pic_data.LengthY(); 
  149.         
  150.         for (int l = 1; l <= depth; ++l)
  151.         {
  152.             VHSplit(0,0,xl,yl,pic_data); 
  153.             xl /= 2; 
  154.             yl /= 2; 
  155.         }
  156.         band_list.Init( depth , pic_data.LengthX() , pic_data.LengthY() ); 
  157.     }
  158.     else
  159.     {
  160.         //do work
  161.         xl = pic_data.LengthX()/(1<<(depth-1)); 
  162.         yl = pic_data.LengthY()/(1<<(depth-1)); 
  163.         
  164.         for (int l = 1; l <= depth; ++l)
  165.         {
  166.             VHSynth(0,0,xl,yl,pic_data); 
  167.             xl *= 2; 
  168.             yl *= 2; 
  169.         }
  170.         
  171.         //band list now inaccurate, so clear        
  172.         band_list.Clear();     
  173.     }
  174. }
  175. //private functions
  176. ///////////////////
  177. void WaveletTransform::VHSplit(const int xp, const int yp, const int xl, const int yl, PicArray& pic_data)
  178. {
  179.     //version based on integer-like types
  180.     //using edge-extension rather than reflection
  181.     OneDArray<ValueType *> tmp_data(yl); 
  182.     const int xl2 = xl/2; 
  183.     const int yl2 = yl/2; 
  184.     const int xend=xp+xl;
  185.     const int yend=yp+yl;
  186.     ValueType* line_data; 
  187.     // Positional variables
  188.     int i,j,k,r,s; 
  189.   
  190.     // Objects to do lifting stages 
  191.     // (in revese order and type from synthesis)
  192.     const PredictStep< 6497 > predictA;
  193.     const PredictStep< 217 > predictB;
  194.     const UpdateStep< 3616 > updateA;
  195.     const UpdateStep< 1817 > updateB;
  196.      //first do horizontal 
  197.     for (j = yp;  j < yend; ++j)
  198.     {
  199.         // First lifting stage
  200.         line_data = pic_data[j];                 
  201.         predictA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] );
  202.         predictB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] );
  203.         for (i = xp+2, k = xp+3; i < xend-2; i+=2, k+=2)
  204.         {
  205.             predictA.Filter( line_data[k] , line_data[i+2] , line_data[i] );
  206.             predictB.Filter( line_data[i] , line_data[k-2] , line_data[k] );
  207.         }// i
  208.         
  209.         predictA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] );
  210.         predictB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] );
  211.          //second lifting stage 
  212.         
  213.         updateA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] );
  214.         updateB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] );
  215.         for (i = xp+2, k = xp+3;  i < xend-2; i+=2 , k+=2)
  216.         { 
  217.             updateA.Filter( line_data[k] , line_data[i+2] , line_data[i] );
  218.             updateB.Filter( line_data[i] , line_data[k-2] , line_data[k] );
  219.         }// i
  220.         updateA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] );
  221.         updateB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] );
  222.     }// j
  223.     // next do vertical
  224.     // First lifting stage
  225.     // top edge - j=xp
  226.     for ( i = xp ; i<xend ; ++ i)
  227.     {
  228.         predictA.Filter( pic_data[yp+1][i] , pic_data[yp+2][i] , pic_data[yp][i] );
  229.         predictB.Filter( pic_data[yp][i] , pic_data[yp+1][i] , pic_data[yp+1][i] );
  230.     }// i
  231.     // middle bit
  232.     for ( j = yp+2, k = yp+3 ; j<yend-2 ; j+=2 , k+=2)
  233.     {
  234.         for ( i = xp ; i<xend ; ++ i)
  235.         {
  236.             predictA.Filter( pic_data[k][i] , pic_data[j+2][i] , pic_data[j][i] );
  237.             predictB.Filter( pic_data[j][i] , pic_data[k-2][i] , pic_data[k][i] );
  238.         }// i
  239.     }// j
  240.     // bottom edge
  241.     for ( i = xp ; i<xend ; ++ i)
  242.     {
  243.         predictA.Filter( pic_data[yend-1][i] , pic_data[yend-2][i] , pic_data[yend-2][i] );
  244.         predictB.Filter( pic_data[yend-2][i] , pic_data[yend-3][i] , pic_data[yend-1][i] );
  245.     }// i
  246.     // Second lifting stage
  247.     // top edge - j=xp
  248.     for ( i = xp ; i<xend ; ++ i)
  249.     {
  250.         updateA.Filter( pic_data[yp+1][i] , pic_data[yp+2][i] , pic_data[yp][i] );
  251.         updateB.Filter( pic_data[yp][i] , pic_data[yp+1][i] , pic_data[yp+1][i] );
  252.     }// i
  253.     // middle bit
  254.     for ( j = yp+2, k = yp+3 ; j<yend-2 ; j+=2 , k+=2)
  255.     {
  256.         for ( i = xp ; i<xend ; ++ i)
  257.         {
  258.             updateA.Filter( pic_data[k][i] , pic_data[j+2][i] , pic_data[j][i] );
  259.             updateB.Filter( pic_data[j][i] , pic_data[k-2][i] , pic_data[k][i] );
  260.         }// i
  261.     }// j
  262.     // bottom edge
  263.     for ( i = xp ; i<xend ; ++ i)
  264.     {
  265.         updateA.Filter( pic_data[yend-1][i] , pic_data[yend-2][i] , pic_data[yend-2][i] );
  266.         updateB.Filter( pic_data[yend-2][i] , pic_data[yend-3][i] , pic_data[yend-1][i] );
  267.     }// i
  268.     // Lastly, have to reorder so that subbands are no longer interleaved
  269.     ValueType** temp_data = new ValueType*[yl];
  270.     for ( j = 0 ; j< yl ; ++ j)
  271.         temp_data[j] = new ValueType[xl];
  272.     // Make a temporary copy of the subband
  273.     for ( j = yp; j<yend ; j++ )
  274.         memcpy( temp_data[j-yp] , pic_data[j]+xp , xl * sizeof( ValueType ) );
  275.     // Re-order to de-interleave
  276.     for ( j = yp, s=0; j<yp+yl2 ; j++, s+=2)
  277.     {
  278.         for ( i = xp , r=0 ; i<xp+xl2 ; i++ , r += 2)
  279.             pic_data[j][i] = temp_data[s][r];
  280.         for ( i = xp+xl2, r=1; i<xend ; i++ , r += 2)
  281.             pic_data[j][i] = temp_data[s][r];
  282.     }// j 
  283.     for ( j = yp+yl2, s=1 ; j<yend ; j++ , s += 2)
  284.     {
  285.         for ( i = xp , r=0 ; i<xp+xl2 ; i++ , r += 2)
  286.             pic_data[j][i] = temp_data[s][r];
  287.         for ( i = xp+xl2, r=1; i<xend ; i++ , r += 2)
  288.             pic_data[j][i] = temp_data[s][r];
  289.     }// j 
  290.     for ( j = 0 ; j< yl ; ++ j)
  291.         delete[] temp_data[j];
  292.     delete[] temp_data;
  293. }
  294. void WaveletTransform::VHSynth(const int xp, const int yp, const int xl, const int yl, PicArray& pic_data)
  295. {
  296.     int i,j,k,r,s;
  297.     const int xend( xp+xl );
  298.     const int yend( yp+yl );
  299.     const int xl2( xl/2 );
  300.     const int yl2( yl/2 );
  301.     const PredictStep< 1817 > predictB;
  302.     const PredictStep< 3616 > predictA;
  303.     const UpdateStep< 217 > updateB;
  304.     const UpdateStep< 6497 > updateA;
  305.     ValueType* line_data;
  306.     // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place
  307.     ValueType** temp_data = new ValueType*[yl];
  308.     for ( j = 0 ; j< yl ; ++ j)
  309.         temp_data[j] = new ValueType[xl];
  310.     // Make a temporary copy of the subband
  311.     for ( j = yp; j<yend ; j++ )
  312.         memcpy( temp_data[j-yp] , pic_data[j]+xp , xl * sizeof( ValueType ) );
  313.     // Re-order to interleave
  314.     for ( j = 0, s=yp; j<yl2 ; j++, s+=2)
  315.     {
  316.         for ( i = 0 , r=xp ; i<xl2 ; i++ , r += 2)
  317.             pic_data[s][r] = temp_data[j][i];
  318.         for ( i = xl2, r=xp+1; i<xl ; i++ , r += 2)
  319.             pic_data[s][r] = temp_data[j][i];
  320.     }// j 
  321.     for ( j = yl2, s=yp+1 ; j<yl ; j++ , s += 2)
  322.     {
  323.         for ( i = 0 , r=xp ; i<xl2 ; i++ , r += 2)
  324.             pic_data[s][r] = temp_data[j][i];
  325.         for ( i = xl2, r=xp+1; i<xl ; i++ , r += 2)
  326.             pic_data[s][r] = temp_data[j][i];
  327.     }// j 
  328.     for ( j = 0 ; j< yl ; ++ j)
  329.         delete[] temp_data[j];
  330.     delete[] temp_data;
  331.     // Next, do the vertical synthesis
  332.     // First lifting stage
  333.     // Begin with the bottom edge
  334.     for ( i = xend-1 ; i>=xp ; --i)
  335.     {
  336.         predictB.Filter( pic_data[yend-2][i] , pic_data[yend-3][i] , pic_data[yend-1][i] );
  337.         predictA.Filter( pic_data[yend-1][i] , pic_data[yend-2][i] , pic_data[yend-2][i] );
  338.     }// i
  339.     // Next, do the middle bit
  340.     for ( j = yend-4, k = yend-3 ; j>yp ; j-=2 , k-=2)
  341.     {
  342.         for ( i = xend-1 ; i>=xp ; --i)
  343.         {
  344.             predictB.Filter( pic_data[j][i] , pic_data[k-2][i] , pic_data[k][i] );
  345.             predictA.Filter( pic_data[k][i] , pic_data[j+2][i] , pic_data[j][i] );
  346.         }// i
  347.     }// j
  348.     // Then do the top edge
  349.     for ( i = xend-1 ; i>=xp ; --i)
  350.     {
  351.         predictB.Filter( pic_data[yp][i] , pic_data[yp+1][i] , pic_data[yp+1][i] );
  352.         predictA.Filter( pic_data[yp+1][i] , pic_data[yp+2][i] , pic_data[yp][i] );
  353.     }// i
  354.     // Second lifting stage
  355.     // Begin with the bottom edge
  356.     for ( i = xend-1 ; i>=xp ; --i)
  357.     {
  358.         updateB.Filter( pic_data[yend-2][i] , pic_data[yend-3][i] , pic_data[yend-1][i] );
  359.         updateA.Filter( pic_data[yend-1][i] , pic_data[yend-2][i] , pic_data[yend-2][i] );
  360.     }// i
  361.     // Next, do the middle bit
  362.     for ( j = yend-4, k = yend-3 ; j>yp ; j-=2 , k-=2)
  363.     {
  364.         for ( i = xend-1 ; i>=xp ; --i)
  365.         {
  366.             updateB.Filter( pic_data[j][i] , pic_data[k-2][i] , pic_data[k][i] );
  367.             updateA.Filter( pic_data[k][i] , pic_data[j+2][i] , pic_data[j][i] );
  368.         }// i
  369.     }// j
  370.     // Then do the top edge
  371.     for ( i = xend-1 ; i>=xp ; --i)
  372.     {
  373.         updateB.Filter( pic_data[yp][i] , pic_data[yp+1][i] , pic_data[yp+1][i] );
  374.         updateA.Filter( pic_data[yp+1][i] , pic_data[yp+2][i] , pic_data[yp][i] );
  375.     }// i
  376.     // Next do the horizontal synthesis
  377.     for (j = yend-1;  j >= yp ; --j)
  378.     {
  379.         // First lifting stage 
  380.         line_data = pic_data[j];
  381.         predictB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] ); 
  382.         predictA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] );
  383.         for (i = xend-4, k = xend-3;  i > xp; i-=2 , k-=2)
  384.         { 
  385.             predictB.Filter( line_data[i] , line_data[k-2] , line_data[k] );
  386.             predictA.Filter( line_data[k] , line_data[i+2] , line_data[i] );
  387.         }// i
  388.         predictB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] );
  389.         predictA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] );
  390.         // Second lifting stage
  391.         updateB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] );
  392.         updateA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] );
  393.         for (i = xend-4, k = xend-3;  i > xp; i-=2 , k-=2)
  394.         {
  395.             updateB.Filter( line_data[i] , line_data[k-2] , line_data[k] );
  396.             updateA.Filter( line_data[k] , line_data[i+2] , line_data[i] );
  397.         }// i
  398.         updateB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] );
  399.         updateA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] );
  400.     }
  401. }
  402. //perceptual weighting stuff
  403. ////////////////////////////
  404. // Returns a perceptual noise weighting based on extending CCIR 959 values
  405. // assuming a two-d isotropic response. Also has a fudge factor of 20% for chroma
  406. float WaveletTransform::PerceptualWeight( float xf , float yf , CompSort cs )
  407. {
  408.     double freq_sqd( xf*xf + yf*yf );
  409.     if ( cs != Y_COMP )
  410.         freq_sqd *= 1.2;
  411.     return 0.255 * std::pow( 1.0 + 0.2561*freq_sqd , 0.75) ;
  412. }
  413. void WaveletTransform::SetBandWeights (const float cpd, 
  414.                                        const FrameSort& fsort,
  415.                                        const ChromaFormat& cformat,
  416.                                        const CompSort csort)
  417. {
  418.     //NB - only designed for progressive to date    
  419.     int xlen, ylen, xl, yl, xp, yp, depth;
  420.     float xfreq, yfreq;
  421.     float temp;
  422.     // Compensate for chroma subsampling
  423.     float chroma_xfac(1.0);
  424.     float chroma_yfac(1.0);
  425.     if( csort != Y_COMP)
  426.     {
  427.         if( cformat == format422)
  428.         {
  429.             chroma_xfac = 2.0;
  430.             chroma_yfac = 1.0;
  431.         }
  432.         else if( cformat == format411 )
  433.         {
  434.             chroma_xfac = 4.0;
  435.             chroma_yfac = 1.0;
  436.         }
  437.         else if( cformat == format420 )
  438.         {
  439.             chroma_xfac = 2.0;
  440.             chroma_yfac = 2.0;
  441.         }
  442.     }
  443.     xlen = 2 * band_list(1).Xl();
  444.     ylen = 2 * band_list(1).Yl();
  445.     if (cpd != 0.0)
  446.     {
  447.         for( int i = 1; i<=band_list.Length() ; i++ )
  448.         {
  449.             xp = band_list(i).Xp();
  450.             yp = band_list(i).Yp();
  451.             xl = band_list(i).Xl();
  452.             yl = band_list(i).Yl();
  453.             xfreq = cpd * ( float(xp) + (float(xl)/2.0) ) / float(xlen);
  454.             yfreq = cpd * ( float(yp) + (float(yl)/2.0) ) / float(ylen);
  455.             if ( fsort != I_frame )
  456.             {
  457.                 xfreq /= 8.0;
  458.                 yfreq /= 8.0;
  459.             }
  460.             temp = PerceptualWeight( xfreq/chroma_xfac , yfreq/chroma_yfac , csort );
  461.             band_list(i).SetWt(temp);
  462.         }// i
  463.         // Give more welly to DC in a completely unscientific manner ...
  464.         // (should really relate this to the frame rate)
  465.         band_list( band_list.Length() ).SetWt(band_list(13).Wt()/6.0);
  466.         // Make sure dc is always the lowest weight
  467.         float min_weight=band_list(band_list.Length()).Wt();
  468.         for( int b=1 ; b<=band_list.Length()-1 ; b++ )
  469.             min_weight = ((min_weight>band_list(b).Wt()) ? band_list(b).Wt() : min_weight);
  470.         band_list( band_list.Length() ).SetWt( min_weight );
  471.         // Now normalize weights so that white noise is always weighted the same
  472.         // Overall factor to ensure that white noise ends up with the same RMS, whatever the weight
  473.         double overall_factor=0.0;
  474.         //fraction of the total number of samples belonging to each subband
  475.         double subband_fraction;    
  476.         for( int i=1 ; i<=band_list.Length() ; i++ )
  477.         {
  478.             subband_fraction = 1.0/((double) band_list(i).Scale() * band_list(i).Scale());
  479.             overall_factor += subband_fraction/( band_list(i).Wt() * band_list(i).Wt() );
  480.         }
  481.         overall_factor = std::sqrt( overall_factor );
  482.         //go through and normalise
  483.         for( int i=band_list.Length() ; i>0 ; i-- )
  484.             band_list(i).SetWt( band_list(i).Wt() * overall_factor );
  485.     }
  486.     else
  487.     {//cpd=0 so set all weights to 1
  488.         for( int i=1 ; i<=band_list.Length() ; i++ )
  489.            band_list(i).SetWt( 1.0 );        
  490.     }
  491.     //Finally, adjust to compensate for the absence of scaling in the transform
  492.     //Factor used to compensate:
  493.     const double alpha(1.149658203);    
  494.     for ( int i=1 ; i<=band_list.Length() ; ++i )
  495.     {
  496.         depth=band_list(i).Depth();
  497.         if ( band_list(i).Xp() == 0 && band_list(i).Yp() == 0)
  498.             temp=std::pow(alpha,2*depth);
  499.         else if ( band_list(i).Xp() != 0 && band_list(i).Yp() != 0)
  500.             temp=std::pow(alpha,2*(depth-2));
  501.         else
  502.             temp=std::pow(alpha,2*(depth-1));
  503.         band_list(i).SetWt(band_list(i).Wt()/temp);
  504.     }// i        
  505. }