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 ); }
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 }
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 ); } } }
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)); }