1 /* ***** BEGIN LICENSE BLOCK ***** 2 * 3 * $Id: wavelet_utils.h,v 1.32 2008/10/20 04:21:02 asuraparaju Exp $ $Name: Dirac_1_0_2 $ 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 * 27 * Alternatively, the contents of this file may be used under the terms of 28 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser 29 * Public License Version 2.1 (the "LGPL"), in which case the provisions of 30 * the GPL or the LGPL are applicable instead of those above. If you wish to 31 * allow use of your version of this file only under the terms of the either 32 * the GPL or LGPL and not to allow others to use your version of this file 33 * under the MPL, indicate your decision by deleting the provisions above 34 * and replace them with the notice and other provisions required by the GPL 35 * or LGPL. If you do not delete the provisions above, a recipient may use 36 * your version of this file under the terms of any one of the MPL, the GPL 37 * or the LGPL. 38 * ***** END LICENSE BLOCK ***** */ 39 40 #ifndef _WAVELET_UTILS_H_ 41 #define _WAVELET_UTILS_H_ 42 43 #include <libdirac_common/arrays.h> 44 #include <libdirac_common/common.h> 45 #include <vector> 46 #include <cmath> 47 #include <iostream> 48 49 //utilities for subband and wavelet transforms 50 //Includes fast transform using lifting 51 52 namespace dirac 53 { 54 55 class PicArray; 56 class Subband; 57 58 //! Class for encapsulating metadata concerning a block of coefficients in a subband 59 class CodeBlock 60 { 61 62 friend class Subband; 63 64 public: 65 //! Constructor 66 /* 67 Default constructor - sets all dimensions to zero 68 */ 69 CodeBlock(); 70 71 //! Constructor 72 /* 73 Initialise the code block 74 \param xstart the x-coord of the first coefficient in the block 75 \param xend one past the last coefficient, horizontally 76 \param ystart the y-coord of the first coefficient in the block 77 \param yend one past the last coefficient, vertically 78 */ 79 CodeBlock( const int xstart , const int ystart , const int xend , const int yend); 80 81 //! Returns the horizontal start of the block Xstart()82 int Xstart() const { return m_xstart; } 83 84 //! Returns the vertical start of the block Ystart()85 int Ystart() const { return m_ystart; } 86 87 //! Returns one past the last coefficient coord, horizontally Xend()88 int Xend() const { return m_xend; } 89 90 //! Returns one past the last coefficient coord, vertically Yend()91 int Yend() const { return m_yend; } 92 93 //! Returns the width of the code block Xl()94 int Xl() const { return m_xl; } 95 96 //! Returns the height of the code block Yl()97 int Yl() const { return m_yl; } 98 99 //! Returns the quantisation index associated to the code block QuantIndex()100 int QuantIndex() const{ return m_quantindex; } 101 102 //! Returns true if the code-block is skipped, false if not Skipped()103 bool Skipped() const { return m_skipped; } 104 105 //! Sets the quantisation index SetQuantIndex(const int quantindex)106 void SetQuantIndex( const int quantindex ){ m_quantindex = quantindex; } 107 108 //! Sets whether the code block is skipped or not SetSkip(bool skip)109 void SetSkip( bool skip ){ m_skipped = skip; } 110 111 private: 112 113 //! Initialise the code block 114 /* 115 Initialise the code block 116 \param xstart the x-coord of the first coefficient in the block 117 \param xend one past the last coefficient, horizontally 118 \param ystart the y-coord of the first coefficient in the block 119 \param yend one past the last coefficient, vertically 120 */ 121 void Init( const int xstart , const int ystart , const int xend , const int yend ); 122 123 private: 124 125 int m_xstart; 126 int m_ystart; 127 int m_xend; 128 int m_yend; 129 int m_xl; 130 int m_yl; 131 132 int m_quantindex; 133 134 bool m_skipped; 135 }; 136 137 138 //! Class encapsulating all the metadata relating to a wavelet subband 139 class Subband 140 { 141 public: 142 143 //! Default constructor 144 Subband(); 145 146 //! Constructor 147 /*! 148 The constructor parameters are 149 \param xpos the xposition of the subband when packed into a 150 big array with all the others 151 \param ypos the xposition of the subband 152 \param xlen the width of the subband 153 \param ylen the height of the subband 154 */ 155 Subband(int xpos, int ypos, int xlen, int ylen); 156 157 //! Constructor 158 /*! 159 The constructor parameters are 160 \param xpos the xposition of the subband when packed into a 161 big array with all the others 162 \param ypos the xposition of the subband 163 \param xlen the width of the subband 164 \param ylen the height of the subband 165 \param d the depth of the subband in the wavelet transform 166 */ 167 Subband(int xpos, int ypos, int xlen, int ylen, int d); 168 169 //! Destructor 170 ~Subband(); 171 172 //Default (shallow) copy constructor and operator= used 173 174 //! Return the width of the subband Xl()175 int Xl() const {return m_xl;} 176 177 //! Return the horizontal position of the subband Xp()178 int Xp() const {return m_xp;} 179 180 //! Return the height of the subband Yl()181 int Yl() const {return m_yl;} 182 183 //! Return the vertical position of the subband Yp()184 int Yp() const {return m_yp;} 185 186 //! Return the index of the maximum bit of the largest coefficient Max()187 int Max() const {return m_max_bit;} 188 189 //! Return the subband perceptual weight Wt()190 double Wt() const {return m_wt;} 191 192 //! Return the depth of the subband in the transform Depth()193 int Depth() const {return m_depth;} 194 195 //! Return the scale of the subband, viewed as a subsampled version of the picture Scale()196 int Scale() const {return ( 1<<m_depth );} 197 198 //! Return a quantisation index QuantIndex()199 int QuantIndex() const {return m_qindex;} 200 201 //! Return a flag indicating whether we have separate quantisers for each code block UsingMultiQuants()202 bool UsingMultiQuants() const {return m_multi_quants; } 203 204 //! Return the index of the parent subband Parent()205 int Parent() const {return m_parent;} 206 207 //! Return the indices of any child subbands Children()208 const std::vector<int>& Children() const {return m_children;} 209 210 //! Return the index of a specific child band Child(const int n)211 int Child(const int n) const {return m_children[n];} 212 213 //! Return the code blocks GetCodeBlocks()214 TwoDArray<CodeBlock>& GetCodeBlocks(){ return m_code_block_array; } 215 216 //! Return the code blocks GetCodeBlocks()217 const TwoDArray<CodeBlock>& GetCodeBlocks() const { return m_code_block_array; } 218 219 //! Returns true if subband is skipped, false if not Skipped()220 bool Skipped() const { return m_skipped; } 221 222 //! Set the perceptual weight 223 void SetWt( const float w ); 224 225 //! Set the parent index SetParent(const int p)226 void SetParent( const int p ){ m_parent=p; } 227 228 //! Set the subband depth SetDepth(const int d)229 void SetDepth( const int d ){ m_depth=d;} 230 231 //! Set the index of the maximum bit of the largest coefficient SetMax(const int m)232 void SetMax( const int m ){ m_max_bit=m; }; 233 234 //! Set the number of (spatial) quantisers in the subband. Creates code block structure 235 void SetNumBlocks( const int ynum , const int xnum ); 236 237 //! Set the quantisation index SetQuantIndex(const int idx)238 void SetQuantIndex( const int idx){ m_qindex = idx; } 239 240 //! Set the number of (spatial) quantisers in the subband. Creates code block structure SetUsingMultiQuants(const bool multi)241 void SetUsingMultiQuants( const bool multi){ m_multi_quants = multi; } 242 243 //! Set whether the subband is skipped or not SetSkip(const bool skip)244 void SetSkip(const bool skip ){ m_skipped = skip; } 245 246 private: 247 // subband bounds 248 int m_xp , m_yp , m_xl , m_yl; 249 250 // perceptual weight for quantisation 251 double m_wt; 252 253 // depth in the transform 254 int m_depth; 255 256 // quantiser index 257 int m_qindex; 258 259 // position of parent in a subband list 260 int m_parent; 261 262 // positions of children in the subband list 263 std::vector<int> m_children; 264 265 // position of the MSB of the largest absolute value 266 int m_max_bit; 267 268 // The code blocks 269 TwoDArray<CodeBlock> m_code_block_array; 270 271 // A flag indicating whether we're using one qf for each code block 272 bool m_multi_quants; 273 274 // Whether the subband is skipped or not 275 bool m_skipped; 276 }; 277 278 //! A class encapulating all the subbands produced by a transform 279 class SubbandList 280 { 281 public: 282 //! Constructor SubbandList()283 SubbandList(){} 284 285 //! Destructor ~SubbandList()286 ~SubbandList(){} 287 288 //Default (shallow) copy constructor and operator= used 289 //! Initialise the list 290 void Init(const int depth,const int xlen,const int ylen); 291 292 //! Return the length of the subband list Length()293 int Length() const {return bands.size();} 294 295 //! Return the subband at position n (1<=n<=length) operator()296 Subband& operator()(const int n){return bands[n-1];} 297 298 //! Return the subband at position n (1<=n<=length) operator()299 const Subband& operator()(const int n) const {return bands[n-1];} 300 301 //! Add a band to the list AddBand(const Subband & b)302 void AddBand(const Subband& b){bands.push_back(b);} 303 304 //! Remove all the bands from the list Clear()305 void Clear(){bands.clear();} 306 307 private: 308 309 //! Given x and y spatial frequencies in cycles per degree, returns a weighting value 310 float PerceptualWeight( const float xf , const float yf , const CompSort cs); 311 312 private: 313 std::vector<Subband> bands; 314 }; 315 316 class CoeffArray; 317 //! A virtual parent class to do vertical and horizontal splitting with wavelet filters 318 class VHFilter 319 { 320 321 public: 322 VHFilter()323 VHFilter(){} 324 ~VHFilter()325 virtual ~VHFilter(){} 326 327 //! Split a subband into 4 328 virtual void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data)=0; 329 330 //! Create a single band from 4 quadrant bands 331 virtual void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data)=0; 332 333 //! Return the value of the additional bitshift 334 virtual int GetShift() const =0; 335 336 protected: 337 338 //! Interleave data from separate subbands into even and odd positions for in-place calculation - called by Synth 339 inline void Interleave( const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data ); 340 341 342 //! De-interleave data even and odd positions into separate subbands - called by Split 343 inline void DeInterleave( const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data ); 344 345 //! Shift all vals in Row by 'shift' bits to the left to increase accuracy by 'shift' bits. Used in Analysis stage of filter 346 void ShiftRowLeft(CoeffType *row, int length, int shift); 347 348 //! Shift all vals in Row by 'shift' bits to the right to counter the shift in the Analysis stage. This function is used in the Synthesis stage 349 void ShiftRowRight(CoeffType *row, int length, int shift); 350 }; 351 352 //! Class to do Daubechies (9,7) filtering operations 353 class VHFilterDAUB9_7 : public VHFilter 354 { 355 356 public: 357 358 //! Split a subband into 4 359 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 360 361 //! Create a single band from 4 quadrant bands 362 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 363 364 //! Return the value of the additional bitshift GetShift()365 int GetShift() const {return 1;} 366 367 368 }; 369 370 //! Class to do (5,3) wavelet filtering operations 371 class VHFilterLEGALL5_3 : public VHFilter 372 { 373 374 public: 375 376 //! Split a subband into 4 377 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 378 379 //! Create a single band from 4 quadrant bands 380 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 381 382 //! Return the value of the additional bitshift GetShift()383 int GetShift() const {return 1;} 384 385 386 #ifdef HAVE_MMX 387 inline void HorizSynth (int xp, int xl, int ystart, int yend, CoeffArray &coeff_data); 388 #endif 389 390 }; 391 392 //! A short filter that's actually close to Daubechies (9,7) but with just two lifting steps 393 class VHFilterDD9_7 : public VHFilter 394 { 395 396 public: 397 398 //! Split a subband into 4 399 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 400 401 //! Create a single band from 4 quadrant bands 402 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 403 404 //! Return the value of the additional bitshift GetShift()405 int GetShift() const {return 1;} 406 }; 407 408 409 //! An extension of DD9_7, with a better low-pass filter but more computation 410 class VHFilterDD13_7 : public VHFilter 411 { 412 413 public: 414 415 //! Split a subband into 4 416 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 417 418 //! Create a single band from 4 quadrant bands 419 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 420 421 //! Return the value of the additional bitshift GetShift()422 int GetShift() const {return 1;} 423 424 }; 425 426 //! Class to do Haar wavelet filtering operations 427 class VHFilterHAAR0 : public VHFilter 428 { 429 430 public: 431 432 //! Split a subband into 4 433 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 434 435 //! Create a single band from 4 quadrant bands 436 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 437 438 //! Return the value of the additional bitshift GetShift()439 int GetShift() const {return 0;} 440 441 442 }; 443 444 //! Class to do Haar wavelet filtering operations with a single shift per level 445 class VHFilterHAAR1 : public VHFilter 446 { 447 448 public: 449 450 //! Split a subband into 4 451 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 452 453 //! Create a single band from 4 quadrant bands 454 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 455 456 //! Return the value of the additional bitshift GetShift()457 int GetShift() const {return 1;} 458 459 }; 460 461 462 //! Class to do Haar wavelet filtering operations with a double shift per level 463 class VHFilterHAAR2 : public VHFilter 464 { 465 466 public: 467 468 //! Split a subband into 4 469 void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 470 471 //! Create a single band from 4 quadrant bands 472 void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); 473 474 //! Return a correction factor to compensate for non-unity power gain of low-pass filter GetLowFactor()475 double GetLowFactor() const { return 1.414213562;} 476 477 //! Return a correction factor to compensate for non-unity power gain of high-pass filter GetHighFactor()478 double GetHighFactor() const { return 0.707106781;} 479 480 //! Return the value of the additional bitshift GetShift()481 int GetShift() const {return 2;} 482 483 }; 484 485 486 487 // Lifting steps used in the filters 488 489 //! Class to do two-tap prediction lifting step 490 template<int shift> 491 class PredictStepShift 492 { 493 494 public: 495 496 //! Constructor PredictStepShift()497 PredictStepShift(){} 498 499 // Assume default copy constructor, assignment= and destructor // 500 501 //! Do the filtering 502 /* 503 Do the filtering. 504 \param in_val the value being predicted 505 \param val1 the first value being used for prediction 506 \param val2 the second value being used for prediction 507 */ Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)508 inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const 509 { 510 in_val -= (( val1 + val2 + (1<<(shift-1)) ) >>shift ); 511 } 512 513 }; 514 515 //! Class to do two-tap updating lifting step 516 template<int shift> 517 class UpdateStepShift 518 { 519 520 public: 521 //! Constructor UpdateStepShift()522 UpdateStepShift(){} 523 524 //! Do the filtering 525 /* 526 Do the filtering. 527 \param in_val the value being updated 528 \param val1 the first value being used for updating 529 \param val2 the second value being used for updating 530 */ Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)531 inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const 532 { 533 in_val += ( ( val1 + val2 + (1<<(shift-1)) ) >>shift ); 534 } 535 536 }; 537 538 //! Class to do symmetric four-tap prediction lifting step 539 template <int shift , int tap1, int tap2> 540 class PredictStepFourTap 541 { 542 public: 543 544 //! Constructor PredictStepFourTap()545 PredictStepFourTap(){} 546 547 // Assume default copy constructor, assignment= and destructor // 548 549 //! Do the filtering Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2,const CoeffType & val3,const CoeffType & val4)550 inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2 , 551 const CoeffType& val3, const CoeffType& val4 ) const 552 { 553 in_val -= ( tap1*( val1 + val2 ) + tap2*( val3 + val4 ) + (1<<(shift-1)))>>shift; 554 } 555 }; 556 557 //! Class to do symmetric four-tap update lifting step 558 template <int shift , int tap1 , int tap2> 559 class UpdateStepFourTap 560 { 561 562 public: 563 //! Constructor UpdateStepFourTap()564 UpdateStepFourTap(){} 565 566 //! Do the filtering Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2,const CoeffType & val3,const CoeffType & val4)567 inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2 , 568 const CoeffType& val3, const CoeffType& val4 ) const 569 { 570 in_val += ( tap1*( val1 + val2 ) + tap2*( val3 + val4 ) + (1<<(shift-1)) )>>shift; 571 } 572 }; 573 574 //! Class to do two-tap prediction lifting step for Daubechies (9,7) 575 template <int gain> class PredictStep97 576 { 577 public: 578 579 //! Constructor PredictStep97()580 PredictStep97(){} 581 582 // Assume default copy constructor, assignment= and destructor // 583 584 //! Do the filtering 585 /* 586 Do the filtering. 587 \param in_val the value being predicted 588 \param val1 the first value being used for prediction 589 \param val2 the second value being used for prediction 590 */ Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)591 inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const 592 { 593 in_val -= static_cast< CoeffType >( (gain * static_cast< int >( val1 + val2 )) >>12 ); 594 } 595 }; 596 597 //! Class to do two-tap update lifting step for Daubechies (9,7) 598 template <int gain> class UpdateStep97 599 { 600 601 public: 602 //! Constructor UpdateStep97()603 UpdateStep97(){} 604 605 //! Do the filtering 606 /* 607 Do the filtering. 608 \param in_val the value being updated 609 \param val1 the first value being used for updating 610 \param val2 the second value being used for updating 611 */ Filter(CoeffType & in_val,const CoeffType & val1,const CoeffType & val2)612 inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const 613 { 614 in_val += static_cast< CoeffType >( (gain * static_cast< int >( val1 + val2 )) >>12 ); 615 } 616 }; 617 618 //! A class for wavelet coefficient data. 619 /*! 620 A class for encapsulating coefficient data, derived from TwoDArray.. 621 */ 622 class CoeffArray: public TwoDArray<CoeffType> 623 { 624 public: 625 //! Default constructor 626 /*! 627 Default constructor creates an empty array. 628 */ CoeffArray()629 CoeffArray(): TwoDArray<CoeffType>(){} 630 631 //! Constructor. 632 /*! 633 Contructor creates a two-D array, with specified size and colour 634 format. 635 */ 636 CoeffArray(int height, int width, CompSort cs=Y_COMP): 637 TwoDArray<CoeffType>(height, width), m_csort(cs){} 638 639 //copy constructor and assignment= derived by inheritance 640 641 //! Destructor ~CoeffArray()642 ~CoeffArray(){} 643 644 //! Return which component is stored CSort()645 const CompSort& CSort() const {return m_csort;} 646 647 //! Set the type of component being stored SetCSort(const CompSort cs)648 void SetCSort(const CompSort cs){ m_csort = cs; } 649 650 //! Returns the set of subbands BandList()651 SubbandList& BandList(){return m_band_list;} 652 653 //! Returns the set of subbands BandList()654 const SubbandList& BandList() const {return m_band_list;} 655 656 //! Sets the subband weights 657 /*! 658 Sets perceptual weights for the subbands. Takes into account both perceptual factors 659 (weight noise less at higher spatial frequencies) and the scaling needed for the 660 wavelet transform. 661 */ 662 void SetBandWeights (const EncoderParams& encparams, 663 const PictureParams& pparams, 664 const CompSort csort, 665 const float cpd_scale_factor); 666 667 private: 668 669 CompSort m_csort; 670 671 // The subband list to be used for conventional transform apps 672 SubbandList m_band_list; 673 674 private: 675 676 //! Given x and y spatial frequencies in cycles per degree, returns a weighting value 677 float PerceptualWeight(float xf,float yf,CompSort cs); 678 679 }; 680 681 //! A class to do wavelet transforms 682 /*! 683 A class to do forward and backward wavelet transforms by iteratively splitting or merging the 684 lowest frequency band. 685 */ 686 class WaveletTransform 687 { 688 public: 689 //! Constructor 690 WaveletTransform(int d = 4, WltFilter f = DAUB9_7); 691 692 //! Destructor 693 virtual ~WaveletTransform(); 694 695 //! Transforms the data to and from the wavelet domain 696 /*! 697 Transforms the data to and from the wavelet domain. 698 \param d the direction of the transform 699 \param pic_data the data to be transformed 700 \param coeff_data array that holds the transform coefficient data 701 */ 702 void Transform(const Direction d, PicArray& pic_data, CoeffArray& coeff_data); 703 704 private: 705 706 707 private: 708 709 // Private variables 710 711 //! Depth of the transform 712 int m_depth; 713 714 //! The (vertical and horizontal) wavelet filter set to be used 715 WltFilter m_filt_sort; 716 717 //! A class to do the vertical and horizontal filtering required 718 VHFilter* m_vhfilter; 719 720 private: 721 // Private functions 722 //! Private, bodyless copy constructor: class should not be copied 723 WaveletTransform(const WaveletTransform& cpy); 724 725 //! Private, bodyless copy operator=: class should not be assigned 726 WaveletTransform& operator=(const WaveletTransform& rhs); 727 728 }; 729 }// end namespace dirac 730 731 #endif 732