Dirac - A Video Codec

Created by the British Broadcasting Corporation.


band_codec_template.h
Go to the documentation of this file.
1
4
5using namespace dirac;
6
8template<typename EntropyCodec>
10 size_t number_of_contexts,
11 const SubbandList & band_list,
12 int band_num,
13 const bool is_intra):
14 EntropyCodec(subband_byteio,number_of_contexts),
15 m_is_intra(is_intra),
16 m_bnum(band_num),
17 m_node(band_list(band_num)),
18 m_last_qf_idx(m_node.QuantIndex())
19{
20 if (m_node.Parent()!=0)
21 m_pnode=band_list(m_node.Parent());
22}
23
24
25//encoding function
26template<typename EntropyCodec>
28{
29
30 const TwoDArray<CodeBlock>& block_list( m_node.GetCodeBlocks() );
31
32 // coeff blocks can be skipped only if SpatialPartitioning is
33 // enabled i.e. more than one code-block per subband
34 bool code_skip = (block_list.LengthX() > 1 || block_list.LengthY() > 1);
35 // Now loop over the blocks and code
36 for (int j=block_list.FirstY() ; j<=block_list.LastY() ; ++j)
37 {
38 CodeBlock *block = block_list[j];
39 for (int i=block_list.FirstX() ; i<=block_list.LastX() ; ++i)
40 {
41 if (code_skip)
42 EntropyCodec::EncodeSymbol(block[i].Skipped() , BLOCK_SKIP_CTX );
43 if ( !block[i].Skipped() )
44 CodeCoeffBlock( block[i] , in_data );
45 else
46 ClearBlock (block[i] , in_data);
47 }// i
48 }// j
49
50}
51
52template<typename EntropyCodec>
54{
55 //main coding function, using binarisation
56
57 const int xbeg = code_block.Xstart();
58 const int ybeg = code_block.Ystart();
59 const int xend = code_block.Xend();
60 const int yend = code_block.Yend();
61
62 const int qf_idx = code_block.QuantIndex();
63
64 bool has_parent = m_node.Parent() != 0;
65
66 if ( m_node.UsingMultiQuants() )
67 {
68 CodeQuantIndexOffset( qf_idx - m_last_qf_idx);
69 m_last_qf_idx = qf_idx;
70 }
72 m_qf = dirac_quantiser_lists.QuantFactor4( qf_idx );
73 if (m_is_intra)
74 m_offset = dirac_quantiser_lists.IntraQuantOffset4( qf_idx );
75 else
76 m_offset = dirac_quantiser_lists.InterQuantOffset4( qf_idx );
77
78 for ( int ypos=ybeg; ypos<yend ;++ypos)
79 {
80 m_pypos=(( ypos-m_node.Yp() )>>1)+m_pnode.Yp();
81 for ( int xpos=xbeg; xpos<xend ;++xpos)
82 {
83 m_pxpos=(( xpos-m_node.Xp() )>>1)+m_pnode.Xp();
84
85 m_nhood_nonzero = false;
86 if (ypos > m_node.Yp())
87 m_nhood_nonzero |= bool(in_data[ypos-1][xpos]);
88 if (xpos > m_node.Xp())
89 m_nhood_nonzero |= bool(in_data[ypos][xpos-1]);
90 if (ypos > m_node.Yp() && xpos > m_node.Xp())
91 m_nhood_nonzero |= bool(in_data[ypos-1][xpos-1]);
92
93 if (has_parent)
94 m_parent_notzero = static_cast<bool> ( in_data[m_pypos][m_pxpos] );
95 else
96 m_parent_notzero = false;
97
98 CodeCoeff( in_data , xpos , ypos );
100 }// xpos
101 }// ypos
102
105template<typename EntropyCodec>
106void GenericBandCodec<EntropyCodec>::CodeCoeff( CoeffArray& in_data, const int xpos, const int ypos)
107{
108 CodeVal( in_data , xpos , ypos , in_data[ypos][xpos] );
109}
111
112/*
113Coefficient magnitude value and differential quantiser index magnitude are
114coded using interleaved exp-Golomb coding for binarisation. In this scheme, a
115value N>=0 is coded by writing N+1 in binary form of a 1 followed by K other
116bits: 1bbbbbbb (adding 1 ensures there'll be a leading 1). These K bits ("info
117bits") are interleaved with K zeroes ("follow bits") each of which means
118"another bit coming", followed by a terminating 1:
119
120 0b0b0b ...0b1
121
122(Conventional exp-Golomb coding has the K zeroes at the beginning, followed
123by the 1 i.e 00...01bb .. b, but interleaving allows the decoder to run a
124single loop and avoid counting the number of zeroes, sparing a register.)
125
126All bits are arithmetically coded. The follow bits have separate contexts
127based on position, and have different contexts from the info bits.
128*/
129
130template<typename EntropyCodec>
132 const int xpos ,
133 const int ypos ,
134 const CoeffType val )
135{
136 unsigned int abs_val( std::abs(val) );
137 abs_val <<= 2;
138 abs_val /= m_qf;
139
140 const int N = abs_val+1;
141 int num_follow_zeroes=0;
142
143 while ( N >= (1<<num_follow_zeroes) )
144 ++num_follow_zeroes;
145 --num_follow_zeroes;
146
147 for ( int i=num_follow_zeroes-1, c=1; i>=0; --i, ++c )
148 {
149 EntropyCodec::EncodeSymbol( 0, ChooseFollowContext( c ) );
150 EntropyCodec::EncodeSymbol( N&(1<<i), ChooseInfoContext() );
151 }
152 EntropyCodec::EncodeSymbol( 1, ChooseFollowContext( num_follow_zeroes+1 ) );
153
154 in_data[ypos][xpos] = static_cast<CoeffType>( abs_val );
155
156 if ( abs_val )
157 {
158 // Must code sign bits and reconstruct
159 in_data[ypos][xpos] *= m_qf;
160 in_data[ypos][xpos] += m_offset+2;
161 in_data[ypos][xpos] >>= 2;
162
163 if ( val>0 )
164 {
165 EntropyCodec::EncodeSymbol( 0 , ChooseSignContext( in_data , xpos , ypos ) );
166 }
167 else
168 {
169 EntropyCodec::EncodeSymbol( 1 , ChooseSignContext( in_data , xpos , ypos ) );
170 in_data[ypos][xpos] = -in_data[ypos][xpos];
171 }
172 }
173}
174
175template<typename EntropyCodec>
177{
178
179 const int abs_val = std::abs( offset );
180
181 int N = abs_val+1;
182 int num_follow_zeroes=0;
183
184 while ( N>= (1<<num_follow_zeroes) )
185 ++num_follow_zeroes;
186 --num_follow_zeroes;
187
188 for ( int i=num_follow_zeroes-1, c=1; i>=0; --i, ++c )
189 {
190 EntropyCodec::EncodeSymbol( 0 , Q_OFFSET_FOLLOW_CTX );
191 EntropyCodec::EncodeSymbol( N&(1<<i), Q_OFFSET_INFO_CTX );
192 }
193 EntropyCodec::EncodeSymbol( 1 , Q_OFFSET_FOLLOW_CTX );
194
195 if ( abs_val )
197 if ( offset>0 )
198 EntropyCodec::EncodeSymbol( 0 , Q_OFFSET_SIGN_CTX );
199 else
200 EntropyCodec::EncodeSymbol( 1 , Q_OFFSET_SIGN_CTX );
201 }
202}
203
204template<typename EntropyCodec>
206{
207 const TwoDArray<CodeBlock>& block_list( m_node.GetCodeBlocks() );
208
209 // coeff blocks can be skipped only if SpatialPartitioning is
210 // enabled i.e. more than one code-block per subband
211 bool decode_skip= (block_list.LengthX() > 1 || block_list.LengthY() > 1);
212 // Now loop over the blocks and decode
213 for (int j=block_list.FirstY() ; j<=block_list.LastY() ; ++j)
214 {
215 CodeBlock *block = block_list[j];
216 for (int i=block_list.FirstX() ; i<=block_list.LastX() ; ++i)
217 {
218 if (decode_skip)
219 block[i].SetSkip( EntropyCodec::DecodeSymbol( BLOCK_SKIP_CTX ) );
220 if ( !block[i].Skipped() )
221 DecodeCoeffBlock( block[i] , out_data );
222 else
223 ClearBlock (block[i] , out_data);
224
225 }// i
226 }// j
227
228}
229
230template<typename EntropyCodec>
232{
233
234
235 const int xbeg = code_block.Xstart();
236 const int ybeg = code_block.Ystart();
237 const int xend = code_block.Xend();
238 const int yend = code_block.Yend();
239
240 int qf_idx = m_node.QuantIndex();
241
242 bool has_parent = m_node.Parent() != 0;
243
244 if ( m_node.UsingMultiQuants() )
245 {
246 qf_idx = m_last_qf_idx+DecodeQuantIndexOffset();
247 m_last_qf_idx = qf_idx;
248 }
249
250 if (qf_idx > (int)dirac_quantiser_lists.MaxQuantIndex())
251 {
252 std::ostringstream errstr;
253 errstr << "Quantiser index out of range [0.."
254 << (int)dirac_quantiser_lists.MaxQuantIndex() << "]";
257 errstr.str(),
259 }
260
261 m_qf = dirac_quantiser_lists.QuantFactor4( qf_idx );
262
263 if (m_is_intra)
264 m_offset = dirac_quantiser_lists.IntraQuantOffset4( qf_idx );
265 else
266 m_offset = dirac_quantiser_lists.InterQuantOffset4( qf_idx );
267
268 //Work
269
270 for ( int ypos=ybeg; ypos<yend ;++ypos)
271 {
272 m_pypos=(( ypos-m_node.Yp() )>>1)+m_pnode.Yp();
273 CoeffType *p_out_data = NULL;
274 if (has_parent)
275 p_out_data = out_data[m_pypos];
276 CoeffType *c_out_data_1 = NULL;
277 if (ypos!=m_node.Yp())
278 c_out_data_1 = out_data[ypos-1];
279 CoeffType *c_out_data_2 = out_data[ypos];
280 for ( int xpos=xbeg; xpos<xend ;++xpos)
281 {
282 m_pxpos=(( xpos-m_node.Xp() )>>1)+m_pnode.Xp();
283
284 m_nhood_nonzero = false;
285 /* c_out_data_1 is the line above the current
286 * c_out_data_2 is the current line */
287 if (ypos > m_node.Yp())
288 m_nhood_nonzero |= bool(c_out_data_1[xpos]);
289 if (xpos > m_node.Xp())
290 m_nhood_nonzero |= bool(c_out_data_2[xpos-1]);
291 if (ypos > m_node.Yp() && xpos > m_node.Xp())
292 m_nhood_nonzero |= bool(c_out_data_1[xpos-1]);
293
294 if (has_parent)
295 m_parent_notzero = ( p_out_data[m_pxpos] != 0 );
296 else
297 m_parent_notzero = false;
298
299 DecodeCoeff( out_data , xpos , ypos );
300
301 }// xpos
302 }// ypos
303}
304
305template<typename EntropyCodec>
306void GenericBandCodec<EntropyCodec>::DecodeCoeff( CoeffArray& in_data, const int xpos, const int ypos)
307{
308 DecodeVal( in_data , xpos , ypos );
309}
310
311
312/*
313Coefficient magnitude value and differential quantiser index value is coded
314using interleaved exp-Golomb coding for binarisation. In this scheme, a value
315N>=0 is coded by writing N+1 in binary form of a 1 followed by K other bits:
3161bbbbbbb (adding 1 ensures there'll be a leading 1). These K bits ("info bits")
317are interleaved with K zeroes ("follow bits") each of which means "another bit
318coming", followed by a terminating 1:
319
320 0b0b0b ...0b1
321
322(Conventional exp-Golomb coding has the K zeroes at the beginning, followed
323by the 1 i.e 00...01bb .. b, but interleaving allows the decoder to run a
324single loop and avoid counting the number of zeroes, sparing a register.)
325
326All bits are arithmetically coded. The follow bits have separate contexts
327based on position, and have different contexts from the info bits.
328*/
329template<typename EntropyCodec>
330inline void GenericBandCodec<EntropyCodec>::DecodeVal( CoeffArray& out_data , const int xpos , const int ypos )
331{
332
333 CoeffType& out_pixel = out_data[ypos][xpos];
334
335 out_pixel = 1;
336 int bit_count=1;
337
338 while ( !EntropyCodec::DecodeSymbol( ChooseFollowContext( bit_count ) ) )
339 {
340 out_pixel <<= 1;
341 out_pixel |= EntropyCodec::DecodeSymbol( ChooseInfoContext() );
342 bit_count++;
343 };
344 --out_pixel;
345
346 if ( out_pixel )
347 {
348 out_pixel *= m_qf;
349 out_pixel += m_offset+2;
350 out_pixel >>= 2;
351
352 if ( EntropyCodec::DecodeSymbol( ChooseSignContext(out_data, xpos, ypos)) )
353 out_pixel = -out_pixel;
354 }
355}
356
357template<typename EntropyCodec>
358inline int GenericBandCodec<EntropyCodec>::ChooseFollowContext( const int bin_number ) const
359{
360 //condition on neighbouring values and parent values
361
362 if (!m_parent_notzero)
363 {
364 switch ( bin_number )
365 {
366 case 1 :
367 if(m_nhood_nonzero == false)
368 return Z_FBIN1z_CTX;
369
370 return Z_FBIN1nz_CTX;
371
372 case 2 :
373 return Z_FBIN2_CTX;
374 case 3 :
375 return Z_FBIN3_CTX;
376 case 4 :
377 return Z_FBIN4_CTX;
378 case 5 :
379 return Z_FBIN5_CTX;
380 default :
381 return Z_FBIN6plus_CTX;
382 }
383 }
384 else
385 {
386 switch ( bin_number )
387 {
388 case 1 :
389 if(m_nhood_nonzero == false)
390 return NZ_FBIN1z_CTX;
391
392 return NZ_FBIN1nz_CTX;
393
394 case 2 :
395 return NZ_FBIN2_CTX;
396 case 3 :
397 return NZ_FBIN3_CTX;
398 case 4 :
399 return NZ_FBIN4_CTX;
400 case 5 :
401 return NZ_FBIN5_CTX;
402 default :
403 return NZ_FBIN6plus_CTX;
404 }
405
406 }
407
408 /* not reachable, but dumb compilers can't spot that */
409 return 0;
410}
411
412template<typename EntropyCodec>
414{
415 return INFO_CTX;
416}
417
418template<typename EntropyCodec>
419inline int GenericBandCodec<EntropyCodec>::ChooseSignContext( const CoeffArray& data , const int xpos , const int ypos ) const
420{
421 if ( m_node.Yp()==0 && m_node.Xp()!=0 )
422 {
423 //we're in a vertically oriented subband
424 if (ypos == 0)
425 return SIGN0_CTX;
426 else
427 {
428 if (data[ypos-1][xpos]>0)
429 return SIGN_POS_CTX;
430 else if (data[ypos-1][xpos]<0)
431 return SIGN_NEG_CTX;
432 else
433 return SIGN0_CTX;
434 }
435 }
436 else if ( m_node.Xp()==0 && m_node.Yp()!=0 )
437 {
438 //we're in a horizontally oriented subband
439 if (xpos == 0)
440 return SIGN0_CTX;
441 else
442 {
443 if ( data[ypos][xpos-1] > 0 )
444 return SIGN_POS_CTX;
445 else if ( data[ypos][xpos-1] < 0 )
446 return SIGN_NEG_CTX;
447 else
448 return SIGN0_CTX;
449 }
450 }
451 else
452 return SIGN0_CTX;
453}
454
455template<typename EntropyCodec>
457{
458 int offset = 1;
459
460 while ( !EntropyCodec::DecodeSymbol( Q_OFFSET_FOLLOW_CTX ) )
461 {
462 offset <<= 1;
463 offset |= EntropyCodec::DecodeSymbol( Q_OFFSET_INFO_CTX );
464 }
465 --offset;
466
467 if ( offset )
468 {
469 if ( EntropyCodec::DecodeSymbol( Q_OFFSET_SIGN_CTX ) )
470 offset = -offset;
471 }
472 return offset;
473}
474
475template<typename EntropyCodec>
476void GenericBandCodec<EntropyCodec>::SetToVal( const CodeBlock& code_block , CoeffArray& pic_data , const CoeffType val)
477{
478 for (int j=code_block.Ystart() ; j<code_block.Yend() ; j++)
479 {
480 for (int i=code_block.Xstart() ; i<code_block.Xend() ; i++)
481 {
482 pic_data[j][i] = val;
483 }// i
484 }// j
485}
486
487template<typename EntropyCodec>
489{
490 for (int j=code_block.Ystart() ; j<code_block.Yend() ; j++)
491 {
492 CoeffType *pic = &coeff_data[j][code_block.Xstart()];
493 memset (pic, 0, (code_block.Xend()-code_block.Xstart())*sizeof(CoeffType));
494 }// j
495
496}
497
498/* Decode a single coefficient using error-feedback DC quantization */
499template<typename EntropyCodec>
501{
503 /* do prediction for this block */
504 for ( int ypos=code_block.Ystart() ; ypos<code_block.Yend() ; ++ypos)
505 {
506 for ( int xpos=code_block.Xstart() ; xpos<code_block.Xend() ; ++xpos)
507 {
508 out_data[ypos][xpos] += GetPrediction( out_data , xpos , ypos );
509 }
510 }
511}
512
513/* after coding a skipped DC codeblock, reconstruct in_data by predicting the values
514 * and not adding any error term (they were all skipped). This is required to correctly
515 * predict the values in the next codeblock */
516
517template<typename EntropyCodec>
519{
520 for (int ypos=code_block.Ystart() ; ypos<code_block.Yend() ; ++ypos)
521 {
522 for (int xpos=code_block.Xstart() ; xpos<code_block.Xend() ; ++xpos)
523 {
524 /* NB, it is correct to overwrite the old value */
525 coeff_data[ypos][xpos] = GetPrediction( coeff_data , xpos , ypos );
526 } // i
527 } // j
528}
529
530template<typename EntropyCodec>
531CoeffType GenericIntraDCBandCodec<EntropyCodec>::GetPrediction( const CoeffArray& data , const int xpos , const int ypos ) const
532{
533 /* NB, 4.5.3 integer division
534 * numbers are rounded down towards -ve infinity, differing from
535 * C's convention that rounds towards 0
536 */
537 if (ypos!=0)
538 {
539 if (xpos!=0)
540 {
541 int sum = data[ypos][xpos-1] + data[ypos-1][xpos-1] + data[ypos-1][xpos] + 3/2;
542 if (sum<0)
543 return (sum-2)/3;
544 else
545 return sum/3;
546 }
547 else
548 return data[ypos - 1][0];
549 }
550 else
551 {
552 if(xpos!=0)
553 return data[0][xpos - 1];
554 else
555 return 0;
556 }
557}
#define DIRAC_THROW_EXCEPTION(arg1, arg2, arg3)
Construct an exception from 3 arguments, log it, and throw it.
Definition: dirac_exception.h:196
Definition of class SequenceHeaderByteIO.
Definition: accessunit_byteio.h:52
int CoeffType
Type of wavelet coefficient data (should be larger than ValueType)
Definition: common.h:74
@ SEVERITY_PICTURE_ERROR
Definition: dirac_exception.h:78
@ NZ_FBIN2_CTX
Definition: common.h:113
@ Z_FBIN4_CTX
Definition: common.h:107
@ INFO_CTX
Definition: common.h:120
@ NZ_FBIN5_CTX
Definition: common.h:116
@ SIGN_POS_CTX
Definition: common.h:99
@ Z_FBIN2_CTX
Definition: common.h:105
@ Z_FBIN1nz_CTX
Definition: common.h:104
@ NZ_FBIN6plus_CTX
Definition: common.h:117
@ Q_OFFSET_SIGN_CTX
Definition: common.h:125
@ NZ_FBIN1nz_CTX
Definition: common.h:112
@ NZ_FBIN3_CTX
Definition: common.h:114
@ NZ_FBIN4_CTX
Definition: common.h:115
@ NZ_FBIN1z_CTX
Definition: common.h:111
@ SIGN0_CTX
Definition: common.h:98
@ SIGN_NEG_CTX
Definition: common.h:100
@ Z_FBIN1z_CTX
Definition: common.h:103
@ Z_FBIN5_CTX
Definition: common.h:108
@ Q_OFFSET_FOLLOW_CTX
Definition: common.h:123
@ BLOCK_SKIP_CTX
Definition: common.h:122
@ Z_FBIN3_CTX
Definition: common.h:106
@ Q_OFFSET_INFO_CTX
Definition: common.h:124
@ Z_FBIN6plus_CTX
Definition: common.h:109
@ ERR_UNSUPPORTED_STREAM_DATA
Definition: dirac_exception.h:59
Subband Dirac-bytestream input/output.
Definition: subband_byteio.h:57
A template class for two-dimensional arrays.
Definition: arrays.h:285
int LengthX() const
Returns the width.
Definition: arrays.h:362
int LastX() const
Returns the index of the last element of a row.
Definition: arrays.h:374
int LastY() const
Returns the index of the first element of a column.
Definition: arrays.h:377
int FirstX() const
Returns the index of the first element of a row.
Definition: arrays.h:368
int LengthY() const
Returns the height.
Definition: arrays.h:365
int FirstY() const
Returns the index of the first element of a column.
Definition: arrays.h:371
A template class for coding and decoding wavelet subband data.
Definition: band_codec.h:59
virtual void DecodeCoeffBlock(const CodeBlock &code_block, CoeffArray &out_data)
Definition: band_codec_template.h:231
virtual void CodeCoeff(CoeffArray &in_data, const int xpos, const int ypos)
Definition: band_codec_template.h:106
int ChooseSignContext(const CoeffArray &data, const int xpos, const int ypos) const
A function for choosing the context for sign bits.
Definition: band_codec_template.h:419
const Subband m_node
the subband being coded
Definition: band_codec.h:133
void CodeQuantIndexOffset(const int offset)
Encode the offset for a code block quantiser.
Definition: band_codec_template.h:176
int DecodeQuantIndexOffset()
Decode the offset for a code block quantiser.
Definition: band_codec_template.h:456
int ChooseInfoContext() const
A function for choosing the context for "information bits".
Definition: band_codec_template.h:413
void DecodeVal(CoeffArray &out_data, const int xpos, const int ypos)
Decode an individual quantised value and perform inverse-quantisation.
Definition: band_codec_template.h:330
virtual void CodeCoeffBlock(const CodeBlock &code_block, CoeffArray &in_data)
Definition: band_codec_template.h:53
Subband m_pnode
the parent subband
Definition: band_codec.h:148
virtual void ClearBlock(const CodeBlock &code_block, CoeffArray &coeff_data)
Set all block values to 0.
Definition: band_codec_template.h:488
virtual void DoWorkCode(CoeffArray &in_data)
Definition: band_codec_template.h:27
void SetToVal(const CodeBlock &code_block, CoeffArray &coeff_data, const CoeffType val)
Set a code block area to a given value.
Definition: band_codec_template.h:476
virtual void DecodeCoeff(CoeffArray &in_data, const int xpos, const int ypos)
Definition: band_codec_template.h:306
int ChooseFollowContext(const int bin_number) const
A function for choosing the context for "follow bits".
Definition: band_codec_template.h:358
void CodeVal(CoeffArray &in_data, const int xpos, const int ypos, const CoeffType val)
Code an individual quantised value and perform inverse-quantisation.
Definition: band_codec_template.h:131
virtual void DoWorkDecode(CoeffArray &out_data)
Definition: band_codec_template.h:205
void ClearBlock(const CodeBlock &code_block, CoeffArray &coeff_data)
When coding a skipped block, propegate the predicted values for future non skipped blocks.
Definition: band_codec_template.h:518
CoeffType GetPrediction(const CoeffArray &data, const int xpos, const int ypos) const
Prediction of a DC value from its previously coded neighbours.
Definition: band_codec_template.h:531
void DecodeCoeffBlock(const CodeBlock &code_block, CoeffArray &out_data)
Decode codeblock of coefficients and perform DC prediction.
Definition: band_codec_template.h:500
Class for encapsulating metadata concerning a block of coefficients in a subband.
Definition: wavelet_utils.h:60
int Xstart() const
Returns the horizontal start of the block.
Definition: wavelet_utils.h:82
void SetSkip(bool skip)
Sets whether the code block is skipped or not.
Definition: wavelet_utils.h:109
int Ystart() const
Returns the vertical start of the block.
Definition: wavelet_utils.h:85
int QuantIndex() const
Returns the quantisation index associated to the code block.
Definition: wavelet_utils.h:100
int Xend() const
Returns one past the last coefficient coord, horizontally.
Definition: wavelet_utils.h:88
int Yend() const
Returns one past the last coefficient coord, vertically.
Definition: wavelet_utils.h:91
int Parent() const
Return the index of the parent subband.
Definition: wavelet_utils.h:205
A class encapulating all the subbands produced by a transform.
Definition: wavelet_utils.h:280
A class for wavelet coefficient data.
Definition: wavelet_utils.h:623

© 2004 British Broadcasting Corporation. Dirac code licensed under the Mozilla Public License (MPL) Version 1.1.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.