Exemplo n.º 1
0
void CompCompressor::SelectQuantisers( PicArray& pic_data , SubbandList& bands ,
                                                 OneDArray<unsigned int>& est_counts )
{
    // Select all the quantizers
    for ( int b=bands.Length() ; b>=1 ; --b )
        est_counts[b] = SelectQuant( pic_data , bands , b );
}
Exemplo n.º 2
0
void CompDecompressor::SetupCodeBlocks( SubbandList& bands )
{
    int xregions;
    int yregions;

    for (int band_num = 1; band_num<=bands.Length() ; ++band_num)
    {
        if (m_decparams.SpatialPartition())
        {
            int level = m_decparams.TransformDepth() - (band_num-1)/3;
            const CodeBlocks &cb = m_decparams.GetCodeBlocks(level);
            xregions = cb.HorizontalCodeBlocks();
            yregions = cb.VerticalCodeBlocks();
        }
        else
        {
               xregions = 1;
               yregions = 1;
        }

        bands( band_num ).SetNumBlocks( yregions ,xregions );

    }// band_num
}
Exemplo n.º 3
0
void CompDecompressor::Decompress(ComponentByteIO* p_component_byteio,
                                  CoeffArray& coeff_data,
                                  SubbandList& bands)
{

    // Set up the code blocks
    SetupCodeBlocks( bands );

    for ( int b=bands.Length() ; b>=1 ; --b ){
        // Multiple quantiser are used only if
        // a. The global code_block_mode is QUANT_MULTIPLE
        //              and
        // b. More than one code block is present in the subband.
        bands(b).SetUsingMultiQuants( 
                           m_decparams.SpatialPartition() &&
                           m_decparams.GetCodeBlockMode() == QUANT_MULTIPLE &&
                           (bands(b).GetCodeBlocks().LengthX() > 1 ||
                           bands(b).GetCodeBlocks().LengthY() > 1)
                                );

        // Read the header data first
        SubbandByteIO subband_byteio(bands(b), *p_component_byteio);
        subband_byteio.Input();
        
        if ( !bands(b).Skipped() ){
            if (m_pparams.UsingAC()){
                // A pointer to the object(s) we'll be using for coding the bands
                BandCodec* bdecoder;
    
                if ( b>=bands.Length()-3){
                    if ( m_psort.IsIntra() && b==bands.Length() )
                        bdecoder=new IntraDCBandCodec(&subband_byteio, 
                                                       TOTAL_COEFF_CTXS ,bands);
                    else
                        bdecoder=new LFBandCodec(&subband_byteio ,
                                                 TOTAL_COEFF_CTXS, bands ,
                                                 b, m_psort.IsIntra());
                }
                else
                    bdecoder=new BandCodec( &subband_byteio , TOTAL_COEFF_CTXS ,
                                            bands , b, m_psort.IsIntra());

                bdecoder->Decompress(coeff_data , subband_byteio.GetBandDataLength());
                delete bdecoder;
            }
            else{
                // A pointer to the object(s) we'll be using for coding the bands
                BandVLC* bdecoder;
    
                   if ( m_psort.IsIntra() && b==bands.Length() )
                      bdecoder=new IntraDCBandVLC(&subband_byteio, bands);
                else
                    bdecoder=new BandVLC( &subband_byteio , bands ,
                                          b, m_psort.IsIntra());

                bdecoder->Decompress(coeff_data , subband_byteio.GetBandDataLength());
                delete bdecoder;
            }
        }
        else{
            SetToVal( coeff_data , bands(b) , 0 );
        }
    }
}
Exemplo n.º 4
0
int CompCompressor::SelectQuant(PicArray& pic_data,SubbandList& bands,const int band_num)
{

    Subband& node=bands(band_num);

    const int qf_start_idx = 4;

    if (band_num==bands.Length())
        AddSubAverage(pic_data,node.Xl(),node.Yl(),SUBTRACT);

    int min_idx;
    double bandmax=PicAbsMax(pic_data,node.Xp(),node.Yp(),node.Xl(),node.Yl());

    if (bandmax>=1)
        node.SetMax(int(floor(log(float(bandmax))/log(2.0))));
    else
        node.SetMax(0);
    int length=4*node.Max()+5;//this is the number of quantisers that are possible

    OneDArray<int> count0(length);
    int count1;    
    OneDArray<int> countPOS(length);
    OneDArray<int> countNEG(length);    
    OneDArray<double> error_total(length);    
    OneDArray<CostType> costs(length);
    int quant_val;    
    ValueType val,abs_val;
    int error;
    double p0,p1;    
    double sign_entropy;    

    int xp=node.Xp();
    int yp=node.Yp();
    int xl=node.Xl();
    int yl=node.Yl();
    double vol;

    if (bandmax < 1.0 )
    {
        //coefficients are zero so the subband can be skipped
        node.SetQf(0,-1);//indicates that the subband is skipped

        if ( band_num == bands.Length() )
            AddSubAverage(pic_data,node.Xl(),node.Yl(),ADD);
    
        return 0;        
    }
    else
    {
        for ( int q=0 ; q<costs.Length() ; q++)
        {
            error_total[q] = 0.0;            
            count0[q] = 0;
            countPOS[q] = 0;
            countNEG[q] = 0;            
        }

        //first, find to nearest integral number of bits using 1/4 of the data
        //////////////////////////////////////////////////////////////////////
        vol=double((yl/2)*(xl/2));//vol is only 1/4 of the coeffs
        count1=int(vol);
        for ( int j=yp+1 ; j<yp+yl ; j+=2 )
        {
            for ( int i=xp+((j-yp)%4)/2 ; i<xp+xl ; i+=2)
            {

                val = pic_data[j][i];
                quant_val = abs(val);
                abs_val = quant_val;

                for ( int q=qf_start_idx ; q<costs.Length() ; q+=4)
                {
                    quant_val >>= (q/4);                                

                    if (quant_val)
                    {
                        count0[q]+=quant_val;
                        quant_val <<= (q/4);                        
                        if (val>0)
                            countPOS[q]++;
                        else
                            countNEG[q]++;
                    }

                    error = abs_val-quant_val;

                    if ( quant_val != 0)                    
                        error -= m_offset[q];

                    error_total[q] +=  pow4( static_cast<double>(error) );
                }// q
            }// i
        }// j

         //do entropy calculation etc        
        for ( int q=qf_start_idx ; q<costs.Length() ; q+=4 )
        {
            costs[q].MSE = error_total[q]/( vol*node.Wt()*node.Wt() );
//
            costs[q].MSE = std::sqrt( costs[q].MSE );
//     
             //calculate probabilities and entropy
            p0 = double( count0[q] )/double( count0[q]+count1 );
            p1 = 1.0-p0;

            if ( p0 != 0.0 && p1 != 0.0)
                costs[q].ENTROPY =- (p0*log(p0)+p1*log(p1))/log(2.0);
            else
                costs[q].ENTROPY = 0.0;

            //we want the entropy *per symbol*, not per bit ...            
            costs[q].ENTROPY *= double(count0[q]+count1);
            costs[q].ENTROPY /= vol;

            //now add in the sign entropy
            if ( countPOS[q]+countNEG[q] != 0 )
            {
                p0 = float(countNEG[q])/float( countPOS[q]+countNEG[q] );
                p1 = 1.0-p0;
                if ( p0 != 0.0 && p1 != 0.0)
                    sign_entropy = -( (p0*log(p0)+p1*log(p1) ) / log(2.0));
                else
                    sign_entropy = 0.0;
            }
            else
                sign_entropy=0.0;    

              //we want the entropy *per symbol*, not per bit ...
            sign_entropy *= double( countNEG[q]+countPOS[q] );
            sign_entropy /= vol;    

            costs[q].ENTROPY += sign_entropy;

            //sort out correction factors
            costs[q].ENTROPY *= m_encparams.EntropyFactors().Factor(band_num,m_fsort,m_csort);
            costs[q].TOTAL = costs[q].MSE+m_lambda*costs[q].ENTROPY;

        }// q

        //find the qf with the lowest cost
        min_idx=qf_start_idx;
        for ( int q=qf_start_idx ; q<costs.Length() ; q+=4 ) 
        {
            if ( costs[q].TOTAL < costs[min_idx].TOTAL )
                min_idx=q;
        }

        //now repeat to get to 1/2 bit accuracy
        ///////////////////////////////////////
        for ( int q=std::max(0,min_idx-2) ; q<=std::min(costs.Last(),min_idx+2) ; q+=2 )
        {
            if ( q != min_idx )
            {
                error_total[q] = 0.0;            
                count0[q] = 0;
                countPOS[q] = 0;
                countNEG[q] = 0;            
            }
        }

        vol = double( (yl/2) * (xl/2) );
        count1 = int(vol);
        int top_idx = std::min(costs.Last(),min_idx+2);
        int bottom_idx = std::max(0,min_idx-2);

        for (int j=yp+1 ; j<yp+yl ; j+=2 )
        {
            for (int i=xp+1 ; i<xp+xl ; i+=2 )
            {
                val = pic_data[j][i];
                abs_val = abs(val);

                for ( int q=bottom_idx ; q<=top_idx ; q+=2 )
                {
                    if ( q != min_idx )
                    {
                        quant_val = int(abs_val);                    
                        quant_val *= m_qfinvlist[q];
                        quant_val >>= 17;

                        if ( quant_val )
                        {
                            count0[q] += quant_val;
                            quant_val *= m_qflist[q];                        

                            if (val>0.0)
                                countPOS[q]++;
                            else
                                countNEG[q]++;
                        }

                        error = abs_val-quant_val;

                        if ( quant_val != 0 )                    
                            error -= m_offset[q];

                        error_total[q] += pow4( static_cast<double>(error) );
                    }//end of if
                }//q
            }//J
        }//I

         //do entropy calculation        
        for ( int q=bottom_idx ; q<=top_idx ; q+=2 )
        {
            if ( q != min_idx )
            {
                costs[q].MSE = error_total[q] / (vol*node.Wt()*node.Wt());
//
                costs[q].MSE = std::sqrt( costs[q].MSE );
//     


                  //calculate probabilities and entropy
                p0 = double(count0[q]) / double(count0[q]+count1);
                p1 = 1.0-p0;

                if (p0 != 0.0 && p1 != 0.0)
                    costs[q].ENTROPY =- (p0*log(p0) + p1*log(p1)) / log(2.0);
                else
                    costs[q].ENTROPY = 0.0;
                //we want the entropy *per symbol*, not per bit ...            
                costs[q].ENTROPY *= count0[q]+count1;
                costs[q].ENTROPY /= vol;

                  //now add in the sign entropy
                if (countPOS[q]+countNEG[q] != 0)
                {
                    p0 = double( countNEG[q] )/double( countPOS[q] + countNEG[q] );
                    p1 = 1.0-p0;
                    if (p0 != 0.0 && p1 != 0.0)
                        sign_entropy =- ( (p0*log(p0)+p1*log(p1)) / log(2.0) );
                    else
                        sign_entropy = 0.0;
                }
                else
                    sign_entropy = 0.0;    

                  //we want the entropy *per symbol*, not per bit ...
                sign_entropy *= double(countNEG[q]+countPOS[q]);
                sign_entropy /= vol;    

                costs[q].ENTROPY += sign_entropy;
                //sort out correction factors
                costs[q].ENTROPY *= m_encparams.EntropyFactors().Factor(band_num,m_fsort,m_csort);
                costs[q].TOTAL = costs[q].MSE+m_lambda*costs[q].ENTROPY;
            }
        }//q

         //find the qf with the lowest cost
        for ( int q=bottom_idx ; q<=top_idx ; q+=2 )
        {
            if ( costs[q].TOTAL < costs[min_idx].TOTAL )
                min_idx = q;
        }

         //finally use 1/2 the values to get 1/4 bit accuracy
        ////////////////////////////////////////////////////        

        bottom_idx=std::max(0,min_idx-1);
        top_idx=std::min(costs.Length()-1,min_idx+1);

        for ( int q=bottom_idx ; q<=top_idx ; q++ )
        {
            error_total[q] = 0.0;            
            count0[q] = 0;
            countPOS[q] = 0;
            countNEG[q] = 0;            
        }

        vol = double( (yl/2) * xl );
        count1 = int( vol );        

        for (int j=yp ; j<yp+yl ; ++j )
        {                
            for (int i=xp+1 ; i<xp+xl ; i+=2)
            {                
                val = pic_data[j][i];
                abs_val = abs(val);

                for (int q=bottom_idx;q<=top_idx;q++)
                {
                    quant_val = int(abs_val);                    
                    quant_val *= m_qfinvlist[q];
                    quant_val >>= 17;

                    if (quant_val)
                    {
                        count0[q] += quant_val;
                        quant_val *= m_qflist[q];                        

                        if ( val > 0 )
                            countPOS[q]++;
                        else
                            countNEG[q]++;
                    }

                    error = abs_val - quant_val;

                    if ( quant_val != 0 )                    
                        error -= m_offset[q];

                    error_total[q] +=  pow4( static_cast<double>(error) );
                }//q
            }//i
        }//j

         //do entropy calculation        
        for ( int q=bottom_idx ; q<=top_idx ; q++ )
        {
            costs[q].MSE = error_total[q]/(vol*node.Wt()*node.Wt());
//
            costs[q].MSE = std::sqrt( costs[q].MSE );
//
             //calculate probabilities and entropy
            p0 = double( count0[q] )/ double( count0[q]+count1 );
            p1 = 1.0 - p0;

            if ( p0 != 0.0 && p1 != 0.0)
                costs[q].ENTROPY = -( p0*log(p0)+p1*log(p1) ) / log(2.0);
            else
                costs[q].ENTROPY = 0.0;

              //we want the entropy *per symbol*, not per bit ...            
            costs[q].ENTROPY *= double(count0[q]+count1);
            costs[q].ENTROPY /= vol;

             //now add in the sign entropy
            if ( countPOS[q] + countNEG[q] != 0 )
            {
                p0 = double( countNEG[q] )/double( countPOS[q]+countNEG[q] );
                p1 = 1.0-p0;
                if ( p0 != 0.0 && p1 != 0.0)
                    sign_entropy = -( (p0*log(p0)+p1*log(p1) ) / log(2.0));
                else
                    sign_entropy = 0.0;
            }
            else
                sign_entropy = 0.0;    

              //we want the entropy *per symbol*, not per bit ...
            sign_entropy *= double(countNEG[q]+countPOS[q]);
            sign_entropy /= vol;    

            costs[q].ENTROPY += sign_entropy;

            //sort out correction factors
            costs[q].ENTROPY *= m_encparams.EntropyFactors().Factor(band_num,m_fsort,m_csort);
            costs[q].TOTAL = costs[q].MSE+m_lambda*costs[q].ENTROPY;

        }//q

         //find the qf with the lowest cost
        for ( int q=bottom_idx ; q<=top_idx ; q++ )
        {
            if ( costs[q].TOTAL < costs[min_idx].TOTAL )
                min_idx=q;
        }

        if ( costs[min_idx].ENTROPY == 0.0 )//then can skip after all
            node.SetQf(0,-1);
        else
            node.SetQf(0,min_idx);

        if ( band_num == bands.Length())
            AddSubAverage(pic_data,node.Xl(),node.Yl(),ADD);

        return int(costs[min_idx].ENTROPY*double(xl*yl));
    }