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

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: comp_compress.cpp,v 1.2 2005/01/30 05:11:41 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),
  24. *                 Scott R Ladd,
  25. *                 Anuradha Suraparaju,
  26. *                 Peter Meerwald
  27. *
  28. * Alternatively, the contents of this file may be used under the terms of
  29. * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
  30. * Public License Version 2.1 (the "LGPL"), in which case the provisions of
  31. * the GPL or the LGPL are applicable instead of those above. If you wish to
  32. * allow use of your version of this file only under the terms of the either
  33. * the GPL or LGPL and not to allow others to use your version of this file
  34. * under the MPL, indicate your decision by deleting the provisions above
  35. * and replace them with the notice and other provisions required by the GPL
  36. * or LGPL. If you do not delete the provisions above, a recipient may use
  37. * your version of this file under the terms of any one of the MPL, the GPL
  38. * or the LGPL.
  39. * ***** END LICENSE BLOCK ***** */
  40. //Compression of an individual component,
  41. //after motion compensation if appropriate
  42. //////////////////////////////////////////
  43. #include <libdirac_encoder/comp_compress.h>
  44. #include <libdirac_common/band_codec.h>
  45. #include <libdirac_common/golomb.h>
  46. using namespace dirac;
  47. #include <ctime>
  48. #include <vector>
  49. #include <iostream>
  50. using std::log;
  51. using std::floor;
  52. static inline double pow4 (double x)
  53. {
  54.     return x * x * x* x;
  55. }
  56. CompCompressor::CompCompressor( EncoderParams& encp,const FrameParams& fp)
  57. : m_encparams(encp),
  58.   m_fparams(fp),
  59.   m_fsort( m_fparams.FSort() ),
  60.   m_cformat( m_fparams.CFormat() ),
  61.   m_qflist(60),
  62.   m_qfinvlist(60),
  63.   m_offset(60)
  64. {}
  65. void CompCompressor::Compress(PicArray& pic_data)
  66. {
  67.     //need to transform, select quantisers for each band, and then compress each component in turn
  68.     m_csort=pic_data.CSort();
  69.     const int depth=4;
  70.     unsigned int num_band_bits;
  71.     // A pointer to an object  for coding the subband data
  72.     BandCodec* bcoder;
  73.     // A pointer to an object for outputting the subband data
  74.     UnitOutputManager* band_op;
  75.     const size_t CONTEXTS_REQUIRED = 24;
  76.     Subband node;
  77.     //set up Lagrangian params    
  78.     if (m_fsort == I_frame) 
  79.         m_lambda= m_encparams.ILambda();
  80.     else if (m_fsort == L1_frame) 
  81.         m_lambda= m_encparams.L1Lambda();
  82.     else 
  83.         m_lambda= m_encparams.L2Lambda();
  84.      if (m_csort == U_COMP) 
  85.          m_lambda*= m_encparams.UFactor();
  86.      if (m_csort == V_COMP) 
  87.          m_lambda*= m_encparams.VFactor();
  88.     WaveletTransform wtransform(depth);
  89.     wtransform.Transform( FORWARD , pic_data );
  90.     wtransform.SetBandWeights( m_encparams.CPD() , m_fparams.FSort() , m_fparams.CFormat(), m_csort);
  91.     SubbandList& bands=wtransform.BandList();
  92.     // Generate all the quantisation data
  93.     GenQuantList();
  94.     // Choose all the quantisers
  95.     OneDArray<unsigned int> estimated_bits( Range( 1 , bands.Length() ) );
  96.     SelectQuantisers( pic_data , bands , estimated_bits );  
  97.     // Loop over all the bands (from DC to HF) quantising and coding them
  98.     for (int b=bands.Length() ; b>=1 ; --b )
  99.     {
  100.         band_op = & m_encparams.BitsOut().FrameOutput().BandOutput( m_csort , b );
  101.         GolombCode( band_op->Header() , bands(b).Qf(0) );
  102.         if (bands(b).Qf(0) != -1)
  103.         {   // If not skipped ...
  104.             bands(b).SetQf( 0 , m_qflist[bands(b).Qf(0)] );
  105.              // Pick the right codec according to the frame type and subband
  106.             if (b >= bands.Length())
  107.             {
  108.                 if ( m_fsort == I_frame && b == bands.Length() )
  109.                     bcoder=new IntraDCBandCodec( &( band_op->Data() ) , CONTEXTS_REQUIRED , bands);
  110.                 else
  111.                     bcoder=new LFBandCodec( &( band_op->Data() ) ,CONTEXTS_REQUIRED, bands , b);
  112.             }
  113.             else
  114.                 bcoder=new BandCodec( &( band_op->Data() ) , CONTEXTS_REQUIRED , bands , b);
  115.             num_band_bits = bcoder->Compress(pic_data);
  116.              // Update the entropy correction factors
  117.             m_encparams.EntropyFactors().Update(b , m_fsort , m_csort , estimated_bits[b] , num_band_bits);
  118.             // Write the length of the data chunk into the header, and flush everything out to file
  119.             UnsignedGolombCode( band_op->Header() , num_band_bits);
  120.             delete bcoder;            
  121.         }
  122.         else
  123.         {   // ... skipped
  124.             if (b == bands.Length() && m_fsort == I_frame)
  125.                 SetToVal( pic_data , bands(b) , 2692 );
  126.             else
  127.                 SetToVal( pic_data , bands(b) , 0 );
  128.         }        
  129.     }//b
  130.     // Transform back into the picture domain
  131.     wtransform.Transform( BACKWARD , pic_data );
  132. }
  133. void CompCompressor::GenQuantList()
  134. {    //generates the list of quantisers and inverse quantisers
  135.     //there is some repetition in this list but at the moment this is easiest from the perspective of SelectQuant
  136.     //Need to remove this repetition later
  137.     m_qflist[0]=1;        m_qfinvlist[0]=131072;    m_offset[0]=0;
  138.     m_qflist[1]=1;        m_qfinvlist[1]=131072;    m_offset[1]=0;
  139.     m_qflist[2]=1;        m_qfinvlist[2]=131072;    m_offset[2]=0;
  140.     m_qflist[3]=1;        m_qfinvlist[3]=131072;    m_offset[3]=0;
  141.     m_qflist[4]=2;        m_qfinvlist[4]=65536;        m_offset[4]=1;
  142.     m_qflist[5]=2;        m_qfinvlist[5]=65536;        m_offset[5]=1;
  143.     m_qflist[6]=2;        m_qfinvlist[6]=65536;        m_offset[6]=1;
  144.     m_qflist[7]=3;        m_qfinvlist[7]=43690;        m_offset[7]=1;
  145.     m_qflist[8]=4;        m_qfinvlist[8]=32768;        m_offset[8]=2;
  146.     m_qflist[9]=4;        m_qfinvlist[9]=32768;        m_offset[9]=2;
  147.     m_qflist[10]=5;        m_qfinvlist[10]=26214;    m_offset[10]=2;
  148.     m_qflist[11]=6;        m_qfinvlist[11]=21845;    m_offset[11]=2;
  149.     m_qflist[12]=8;        m_qfinvlist[12]=16384;    m_offset[12]=3;
  150.     m_qflist[13]=9;        m_qfinvlist[13]=14563;    m_offset[13]=3;
  151.     m_qflist[14]=11;        m_qfinvlist[14]=11915;    m_offset[14]=4;
  152.     m_qflist[15]=13;        m_qfinvlist[15]=10082;    m_offset[15]=5;
  153.     m_qflist[16]=16;        m_qfinvlist[16]=8192;        m_offset[16]=6;
  154.     m_qflist[17]=19;        m_qfinvlist[17]=6898;        m_offset[17]=7;
  155.     m_qflist[18]=22;        m_qfinvlist[18]=5957;        m_offset[18]=8;
  156.     m_qflist[19]=26;        m_qfinvlist[19]=5041;        m_offset[19]=10;
  157.     m_qflist[20]=32;        m_qfinvlist[20]=4096;        m_offset[20]=12;
  158.     m_qflist[21]=38;        m_qfinvlist[21]=3449;        m_offset[21]=14;
  159.     m_qflist[22]=45;        m_qfinvlist[22]=2912;        m_offset[22]=17;
  160.     m_qflist[23]=53;        m_qfinvlist[23]=2473;        m_offset[23]=20;
  161.     m_qflist[24]=64;        m_qfinvlist[24]=2048;        m_offset[24]=24;
  162.     m_qflist[25]=76;        m_qfinvlist[25]=1724;        m_offset[25]=29;
  163.     m_qflist[26]=90;        m_qfinvlist[26]=1456;        m_offset[26]=34;
  164.     m_qflist[27]=107;        m_qfinvlist[27]=1224;        m_offset[27]=40;
  165.     m_qflist[28]=128;        m_qfinvlist[28]=1024;        m_offset[28]=48;
  166.     m_qflist[29]=152;        m_qfinvlist[29]=862;        m_offset[29]=57;
  167.     m_qflist[30]=181;        m_qfinvlist[30]=724;        m_offset[30]=68;
  168.     m_qflist[31]=215;        m_qfinvlist[31]=609;        m_offset[31]=81;
  169.     m_qflist[32]=256;        m_qfinvlist[32]=512;        m_offset[32]=96;
  170.     m_qflist[33]=304;        m_qfinvlist[33]=431;        m_offset[33]=114;
  171.     m_qflist[34]=362;        m_qfinvlist[34]=362;        m_offset[34]=136;
  172.     m_qflist[35]=430;        m_qfinvlist[35]=304;        m_offset[35]=161;
  173.     m_qflist[36]=512;        m_qfinvlist[36]=256;        m_offset[36]=192;
  174.     m_qflist[37]=608;        m_qfinvlist[37]=215;        m_offset[37]=228;
  175.     m_qflist[38]=724;        m_qfinvlist[38]=181;        m_offset[38]=272;
  176.     m_qflist[39]=861;        m_qfinvlist[39]=152;        m_offset[39]=323;
  177.     m_qflist[40]=1024;    m_qfinvlist[40]=128;        m_offset[40]=384;
  178.     m_qflist[41]=1217;    m_qfinvlist[41]=107;        m_offset[41]=456;
  179.     m_qflist[42]=1448;    m_qfinvlist[42]=90;        m_offset[42]=543;
  180.     m_qflist[43]=1722;    m_qfinvlist[43]=76;        m_offset[43]=646;
  181.     m_qflist[44]=2048;    m_qfinvlist[44]=64;        m_offset[44]=768;
  182.     m_qflist[45]=2435;    m_qfinvlist[45]=53;        m_offset[45]=913;
  183.     m_qflist[46]=2896;    m_qfinvlist[46]=45;        m_offset[46]=1086;
  184.     m_qflist[47]=3444;    m_qfinvlist[47]=38;        m_offset[47]=1292;
  185.     m_qflist[48]=4096;    m_qfinvlist[48]=32;        m_offset[48]=1536;
  186.     m_qflist[49]=4870;    m_qfinvlist[49]=26;        m_offset[49]=1826;
  187.     m_qflist[50]=5792;    m_qfinvlist[50]=22;        m_offset[50]=2172;
  188.     m_qflist[51]=6888;    m_qfinvlist[51]=19;        m_offset[51]=2583;
  189.     m_qflist[52]=8192;    m_qfinvlist[52]=16;        m_offset[52]=3072;
  190.     m_qflist[53]=9741;    m_qfinvlist[53]=13;        m_offset[53]=3653;
  191.     m_qflist[54]=11585;    m_qfinvlist[54]=11;        m_offset[54]=4344;
  192.     m_qflist[55]=13777;    m_qfinvlist[55]=9;        m_offset[55]=5166;
  193.     m_qflist[56]=16384;    m_qfinvlist[56]=8;        m_offset[56]=6144;
  194.     m_qflist[57]=19483;    m_qfinvlist[57]=6;        m_offset[57]=7306;
  195.     m_qflist[58]=23170;    m_qfinvlist[58]=5;        m_offset[58]=8689;
  196.     m_qflist[59]=27554;    m_qfinvlist[59]=4;        m_offset[59]=10333;    
  197. }
  198. void CompCompressor::SelectQuantisers( PicArray& pic_data , SubbandList& bands ,
  199.                                                  OneDArray<unsigned int>& est_counts )
  200. {
  201.     // Select all the quantizers
  202.     for ( int b=bands.Length() ; b>=1 ; --b )
  203.         est_counts[b] = SelectQuant( pic_data , bands , b );
  204. }
  205. int CompCompressor::SelectQuant(PicArray& pic_data,SubbandList& bands,const int band_num)
  206. {
  207.     Subband& node=bands(band_num);
  208.     const int qf_start_idx = 4;
  209.     if (band_num==bands.Length())
  210.         AddSubAverage(pic_data,node.Xl(),node.Yl(),SUBTRACT);
  211.     int min_idx;
  212.     double bandmax=PicAbsMax(pic_data,node.Xp(),node.Yp(),node.Xl(),node.Yl());
  213.     if (bandmax>=1)
  214.         node.SetMax(int(floor(log(float(bandmax))/log(2.0))));
  215.     else
  216.         node.SetMax(0);
  217.     int length=4*node.Max()+5;//this is the number of quantisers that are possible
  218.     OneDArray<int> count0(length);
  219.     int count1;    
  220.     OneDArray<int> countPOS(length);
  221.     OneDArray<int> countNEG(length);    
  222.     OneDArray<double> error_total(length);    
  223.     OneDArray<CostType> costs(length);
  224.     int quant_val;    
  225.     ValueType val,abs_val;
  226.     int error;
  227.     double p0,p1;    
  228.     double sign_entropy;    
  229.     int xp=node.Xp();
  230.     int yp=node.Yp();
  231.     int xl=node.Xl();
  232.     int yl=node.Yl();
  233.     double vol;
  234.     if (bandmax < 1.0 )
  235.     {
  236.         //coefficients are zero so the subband can be skipped
  237.         node.SetQf(0,-1);//indicates that the subband is skipped
  238.         if ( band_num == bands.Length() )
  239.             AddSubAverage(pic_data,node.Xl(),node.Yl(),ADD);
  240.     
  241.         return 0;        
  242.     }
  243.     else
  244.     {
  245.         for ( int q=0 ; q<costs.Length() ; q++)
  246.         {
  247.             error_total[q] = 0.0;            
  248.             count0[q] = 0;
  249.             countPOS[q] = 0;
  250.             countNEG[q] = 0;            
  251.         }
  252.         //first, find to nearest integral number of bits using 1/4 of the data
  253.         //////////////////////////////////////////////////////////////////////
  254.         vol=double((yl/2)*(xl/2));//vol is only 1/4 of the coeffs
  255.         count1=int(vol);
  256.         for ( int j=yp+1 ; j<yp+yl ; j+=2 )
  257.         {
  258.             for ( int i=xp+((j-yp)%4)/2 ; i<xp+xl ; i+=2)
  259.             {
  260.                 val = pic_data[j][i];
  261.                 quant_val = abs(val);
  262.                 abs_val = quant_val;
  263.                 for ( int q=qf_start_idx ; q<costs.Length() ; q+=4)
  264.                 {
  265.                     quant_val >>= (q/4);                                
  266.                     if (quant_val)
  267.                     {
  268.                         count0[q]+=quant_val;
  269.                         quant_val <<= (q/4);                        
  270.                         if (val>0)
  271.                             countPOS[q]++;
  272.                         else
  273.                             countNEG[q]++;
  274.                     }
  275.                     error = abs_val-quant_val;
  276.                     if ( quant_val != 0)                    
  277.                         error -= m_offset[q];
  278.                     error_total[q] +=  pow4( static_cast<double>(error) );
  279.                 }// q
  280.             }// i
  281.         }// j
  282.          //do entropy calculation etc        
  283.         for ( int q=qf_start_idx ; q<costs.Length() ; q+=4 )
  284.         {
  285.             costs[q].MSE = error_total[q]/( vol*node.Wt()*node.Wt() );
  286. //
  287.             costs[q].MSE = std::sqrt( costs[q].MSE );
  288. //     
  289.              //calculate probabilities and entropy
  290.             p0 = double( count0[q] )/double( count0[q]+count1 );
  291.             p1 = 1.0-p0;
  292.             if ( p0 != 0.0 && p1 != 0.0)
  293.                 costs[q].ENTROPY =- (p0*log(p0)+p1*log(p1))/log(2.0);
  294.             else
  295.                 costs[q].ENTROPY = 0.0;
  296.             //we want the entropy *per symbol*, not per bit ...            
  297.             costs[q].ENTROPY *= double(count0[q]+count1);
  298.             costs[q].ENTROPY /= vol;
  299.             //now add in the sign entropy
  300.             if ( countPOS[q]+countNEG[q] != 0 )
  301.             {
  302.                 p0 = float(countNEG[q])/float( countPOS[q]+countNEG[q] );
  303.                 p1 = 1.0-p0;
  304.                 if ( p0 != 0.0 && p1 != 0.0)
  305.                     sign_entropy = -( (p0*log(p0)+p1*log(p1) ) / log(2.0));
  306.                 else
  307.                     sign_entropy = 0.0;
  308.             }
  309.             else
  310.                 sign_entropy=0.0;    
  311.               //we want the entropy *per symbol*, not per bit ...
  312.             sign_entropy *= double( countNEG[q]+countPOS[q] );
  313.             sign_entropy /= vol;    
  314.             costs[q].ENTROPY += sign_entropy;
  315.             //sort out correction factors
  316.             costs[q].ENTROPY *= m_encparams.EntropyFactors().Factor(band_num,m_fsort,m_csort);
  317.             costs[q].TOTAL = costs[q].MSE+m_lambda*costs[q].ENTROPY;
  318.         }// q
  319.         //find the qf with the lowest cost
  320.         min_idx=qf_start_idx;
  321.         for ( int q=qf_start_idx ; q<costs.Length() ; q+=4 ) 
  322.         {
  323.             if ( costs[q].TOTAL < costs[min_idx].TOTAL )
  324.                 min_idx=q;
  325.         }
  326.         //now repeat to get to 1/2 bit accuracy
  327.         ///////////////////////////////////////
  328.         for ( int q=std::max(0,min_idx-2) ; q<=std::min(costs.Last(),min_idx+2) ; q+=2 )
  329.         {
  330.             if ( q != min_idx )
  331.             {
  332.                 error_total[q] = 0.0;            
  333.                 count0[q] = 0;
  334.                 countPOS[q] = 0;
  335.                 countNEG[q] = 0;            
  336.             }
  337.         }
  338.         vol = double( (yl/2) * (xl/2) );
  339.         count1 = int(vol);
  340.         int top_idx = std::min(costs.Last(),min_idx+2);
  341.         int bottom_idx = std::max(0,min_idx-2);
  342.         for (int j=yp+1 ; j<yp+yl ; j+=2 )
  343.         {
  344.             for (int i=xp+1 ; i<xp+xl ; i+=2 )
  345.             {
  346.                 val = pic_data[j][i];
  347.                 abs_val = abs(val);
  348.                 for ( int q=bottom_idx ; q<=top_idx ; q+=2 )
  349.                 {
  350.                     if ( q != min_idx )
  351.                     {
  352.                         quant_val = int(abs_val);                    
  353.                         quant_val *= m_qfinvlist[q];
  354.                         quant_val >>= 17;
  355.                         if ( quant_val )
  356.                         {
  357.                             count0[q] += quant_val;
  358.                             quant_val *= m_qflist[q];                        
  359.                             if (val>0.0)
  360.                                 countPOS[q]++;
  361.                             else
  362.                                 countNEG[q]++;
  363.                         }
  364.                         error = abs_val-quant_val;
  365.                         if ( quant_val != 0 )                    
  366.                             error -= m_offset[q];
  367.                         error_total[q] += pow4( static_cast<double>(error) );
  368.                     }//end of if
  369.                 }//q
  370.             }//J
  371.         }//I
  372.          //do entropy calculation        
  373.         for ( int q=bottom_idx ; q<=top_idx ; q+=2 )
  374.         {
  375.             if ( q != min_idx )
  376.             {
  377.                 costs[q].MSE = error_total[q] / (vol*node.Wt()*node.Wt());
  378. //
  379.                 costs[q].MSE = std::sqrt( costs[q].MSE );
  380. //     
  381.                   //calculate probabilities and entropy
  382.                 p0 = double(count0[q]) / double(count0[q]+count1);
  383.                 p1 = 1.0-p0;
  384.                 if (p0 != 0.0 && p1 != 0.0)
  385.                     costs[q].ENTROPY =- (p0*log(p0) + p1*log(p1)) / log(2.0);
  386.                 else
  387.                     costs[q].ENTROPY = 0.0;
  388.                 //we want the entropy *per symbol*, not per bit ...            
  389.                 costs[q].ENTROPY *= count0[q]+count1;
  390.                 costs[q].ENTROPY /= vol;
  391.                   //now add in the sign entropy
  392.                 if (countPOS[q]+countNEG[q] != 0)
  393.                 {
  394.                     p0 = double( countNEG[q] )/double( countPOS[q] + countNEG[q] );
  395.                     p1 = 1.0-p0;
  396.                     if (p0 != 0.0 && p1 != 0.0)
  397.                         sign_entropy =- ( (p0*log(p0)+p1*log(p1)) / log(2.0) );
  398.                     else
  399.                         sign_entropy = 0.0;
  400.                 }
  401.                 else
  402.                     sign_entropy = 0.0;    
  403.                   //we want the entropy *per symbol*, not per bit ...
  404.                 sign_entropy *= double(countNEG[q]+countPOS[q]);
  405.                 sign_entropy /= vol;    
  406.                 costs[q].ENTROPY += sign_entropy;
  407.                 //sort out correction factors
  408.                 costs[q].ENTROPY *= m_encparams.EntropyFactors().Factor(band_num,m_fsort,m_csort);
  409.                 costs[q].TOTAL = costs[q].MSE+m_lambda*costs[q].ENTROPY;
  410.             }
  411.         }//q
  412.          //find the qf with the lowest cost
  413.         for ( int q=bottom_idx ; q<=top_idx ; q+=2 )
  414.         {
  415.             if ( costs[q].TOTAL < costs[min_idx].TOTAL )
  416.                 min_idx = q;
  417.         }
  418.          //finally use 1/2 the values to get 1/4 bit accuracy
  419.         ////////////////////////////////////////////////////        
  420.         bottom_idx=std::max(0,min_idx-1);
  421.         top_idx=std::min(costs.Length()-1,min_idx+1);
  422.         for ( int q=bottom_idx ; q<=top_idx ; q++ )
  423.         {
  424.             error_total[q] = 0.0;            
  425.             count0[q] = 0;
  426.             countPOS[q] = 0;
  427.             countNEG[q] = 0;            
  428.         }
  429.         vol = double( (yl/2) * xl );
  430.         count1 = int( vol );        
  431.         for (int j=yp ; j<yp+yl ; ++j )
  432.         {                
  433.             for (int i=xp+1 ; i<xp+xl ; i+=2)
  434.             {                
  435.                 val = pic_data[j][i];
  436.                 abs_val = abs(val);
  437.                 for (int q=bottom_idx;q<=top_idx;q++)
  438.                 {
  439.                     quant_val = int(abs_val);                    
  440.                     quant_val *= m_qfinvlist[q];
  441.                     quant_val >>= 17;
  442.                     if (quant_val)
  443.                     {
  444.                         count0[q] += quant_val;
  445.                         quant_val *= m_qflist[q];                        
  446.                         if ( val > 0 )
  447.                             countPOS[q]++;
  448.                         else
  449.                             countNEG[q]++;
  450.                     }
  451.                     error = abs_val - quant_val;
  452.                     if ( quant_val != 0 )                    
  453.                         error -= m_offset[q];
  454.                     error_total[q] +=  pow4( static_cast<double>(error) );
  455.                 }//q
  456.             }//i
  457.         }//j
  458.          //do entropy calculation        
  459.         for ( int q=bottom_idx ; q<=top_idx ; q++ )
  460.         {
  461.             costs[q].MSE = error_total[q]/(vol*node.Wt()*node.Wt());
  462. //
  463.             costs[q].MSE = std::sqrt( costs[q].MSE );
  464. //
  465.              //calculate probabilities and entropy
  466.             p0 = double( count0[q] )/ double( count0[q]+count1 );
  467.             p1 = 1.0 - p0;
  468.             if ( p0 != 0.0 && p1 != 0.0)
  469.                 costs[q].ENTROPY = -( p0*log(p0)+p1*log(p1) ) / log(2.0);
  470.             else
  471.                 costs[q].ENTROPY = 0.0;
  472.               //we want the entropy *per symbol*, not per bit ...            
  473.             costs[q].ENTROPY *= double(count0[q]+count1);
  474.             costs[q].ENTROPY /= vol;
  475.              //now add in the sign entropy
  476.             if ( countPOS[q] + countNEG[q] != 0 )
  477.             {
  478.                 p0 = double( countNEG[q] )/double( countPOS[q]+countNEG[q] );
  479.                 p1 = 1.0-p0;
  480.                 if ( p0 != 0.0 && p1 != 0.0)
  481.                     sign_entropy = -( (p0*log(p0)+p1*log(p1) ) / log(2.0));
  482.                 else
  483.                     sign_entropy = 0.0;
  484.             }
  485.             else
  486.                 sign_entropy = 0.0;    
  487.               //we want the entropy *per symbol*, not per bit ...
  488.             sign_entropy *= double(countNEG[q]+countPOS[q]);
  489.             sign_entropy /= vol;    
  490.             costs[q].ENTROPY += sign_entropy;
  491.             //sort out correction factors
  492.             costs[q].ENTROPY *= m_encparams.EntropyFactors().Factor(band_num,m_fsort,m_csort);
  493.             costs[q].TOTAL = costs[q].MSE+m_lambda*costs[q].ENTROPY;
  494.         }//q
  495.          //find the qf with the lowest cost
  496.         for ( int q=bottom_idx ; q<=top_idx ; q++ )
  497.         {
  498.             if ( costs[q].TOTAL < costs[min_idx].TOTAL )
  499.                 min_idx=q;
  500.         }
  501.         if ( costs[min_idx].ENTROPY == 0.0 )//then can skip after all
  502.             node.SetQf(0,-1);
  503.         else
  504.             node.SetQf(0,min_idx);
  505.         if ( band_num == bands.Length())
  506.             AddSubAverage(pic_data,node.Xl(),node.Yl(),ADD);
  507.         return int(costs[min_idx].ENTROPY*double(xl*yl));
  508.     }
  509. }
  510. ValueType CompCompressor::PicAbsMax(const PicArray& pic_data) const
  511. {
  512.     //finds the maximum absolute value of the picture array
  513.     return PicAbsMax(pic_data,pic_data.FirstX() , pic_data.FirstY(),
  514.                      pic_data.LengthX(),pic_data.LengthY());
  515. }
  516. ValueType CompCompressor::PicAbsMax(const PicArray& pic_data,int xp, int yp ,int xl ,int yl) const
  517. {
  518.     int first_x=std::max(pic_data.FirstX(),xp);    
  519.     int first_y=std::max(pic_data.FirstY(),yp);    
  520.     int last_x=std::min(pic_data.LastX(),xp+xl-1);    
  521.     int last_y=std::min(pic_data.LastY(),yp+yl-1);        
  522.     ValueType val=0;
  523.     for (int j=first_y ; j<=last_y; ++j)
  524.     {
  525.         for (int i=first_x ; i<=last_x; ++i)
  526.         {    
  527.             val = std::max( val , pic_data[j][i] );    
  528.         }// i
  529.     }// j
  530.     return val;
  531. }
  532. void CompCompressor::SetToVal(PicArray& pic_data,const Subband& node,ValueType val){
  533.     for (int j=node.Yp() ; j<node.Yp() + node.Yl() ; ++j)
  534.     {    
  535.         for (int i=node.Xp(); i<node.Xp() + node.Xl() ; ++i)
  536.         {
  537.             pic_data[j][i] = val;
  538.         }// i
  539.     }// j
  540. }
  541. void CompCompressor::AddSubAverage(PicArray& pic_data,int xl,int yl,AddOrSub dirn){
  542.     ValueType last_val=2692;//corresponds to mid-grey in this DC band with these filters
  543.                             //NB this is hard-wired for a level 4 transform
  544.     ValueType last_val2;
  545.  
  546.     if ( dirn == SUBTRACT )
  547.     {
  548.         for ( int j=0 ; j<yl ; j++)
  549.             {
  550.             for ( int i=0 ; i<xl ; i++)
  551.                 {
  552.                 last_val2 = pic_data[j][i];        
  553.                 pic_data[j][i] -= last_val;
  554.                 last_val = last_val2;
  555.             }// i
  556.         }// j
  557.     }
  558.     else
  559.     {
  560.         for ( int j=0 ; j<yl ; j++)
  561.         {
  562.             for ( int i=0 ; i<xl; i++ )
  563.             {
  564.                 pic_data[j][i] += last_val;
  565.                 last_val = pic_data[j][i];
  566.             }// i
  567.         }// j
  568.     }
  569. }