corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * CVS identifier:
3 *
4 * $Id: SubbandAn.java,v 1.30 2001/08/02 09:13:53 grosbois Exp $
5 *
6 * Class: SubbandAn
7 *
8 * Description: Element for a tree structure for a descripotion
9 * of subbands on the anslysis side.
10 *
11 *
12 *
13 * COPYRIGHT:
14 *
15 * This software module was originally developed by Raphaël Grosbois and
16 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
17 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
18 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
19 * Centre France S.A) in the course of development of the JPEG2000
20 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
21 * software module is an implementation of a part of the JPEG 2000
22 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
23 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
24 * Partners) agree not to assert against ISO/IEC and users of the JPEG
25 * 2000 Standard (Users) any of their rights under the copyright, not
26 * including other intellectual property rights, for this software module
27 * with respect to the usage by ISO/IEC and Users of this software module
28 * or modifications thereof for use in hardware or software products
29 * claiming conformance to the JPEG 2000 Standard. Those intending to use
30 * this software module in hardware or software products are advised that
31 * their use may infringe existing patents. The original developers of
32 * this software module, JJ2000 Partners and ISO/IEC assume no liability
33 * for use of this software module or modifications thereof. No license
34 * or right to this software module is granted for non JPEG 2000 Standard
35 * conforming products. JJ2000 Partners have full right to use this
36 * software module for his/her own purpose, assign or donate this
37 * software module to any third party and to inhibit third parties from
38 * using this software module for non JPEG 2000 Standard conforming
39 * products. This copyright notice must be included in all copies or
40 * derivative works of this software module.
41 *
42 * Copyright (c) 1999/2000 JJ2000 Partners.
43 * */
44 using System;
45 using CSJ2K.j2k.wavelet;
46 namespace CSJ2K.j2k.wavelet.analysis
47 {
48  
49 /// <summary> This class represents a subband in a bidirectional tree structure that
50 /// describes the subband decomposition for a wavelet transform, specifically
51 /// for the analysis side.
52 ///
53 /// <p>The element can be either a node or a leaf of the tree. If it is a node
54 /// then ther are 4 descendants (LL, HL, LH and HH). If it is a leaf there are
55 /// no descendants.</p>
56 ///
57 /// <p>The tree is bidirectional. Each element in the tree structure has a
58 /// "parent", which is the subband from which the element was obtained by
59 /// decomposition. The only exception is the root element which has no parent
60 /// (i.e.it's null), for obvious reasons.</p>
61 ///
62 /// </summary>
63 public class SubbandAn:Subband
64 {
65 /// <summary> Returns the parent of this subband. The parent of a subband is the
66 /// subband from which this one was obtained by decomposition. The root
67 /// element has no parent subband (null).
68 ///
69 /// </summary>
70 /// <returns> The parent subband, or null for the root one.
71 ///
72 /// </returns>
73 override public Subband Parent
74 {
75 get
76 {
77 return parentband;
78 }
79  
80 }
81 /// <summary> Returns the LL child subband of this subband.
82 ///
83 /// </summary>
84 /// <returns> The LL child subband, or null if there are no childs.
85 ///
86 /// </returns>
87 override public Subband LL
88 {
89 get
90 {
91 return subb_LL;
92 }
93  
94 }
95 /// <summary> Returns the HL (horizontal high-pass) child subband of this subband.
96 ///
97 /// </summary>
98 /// <returns> The HL child subband, or null if there are no childs.
99 ///
100 /// </returns>
101 override public Subband HL
102 {
103 get
104 {
105 return subb_HL;
106 }
107  
108 }
109 /// <summary> Returns the LH (vertical high-pass) child subband of this subband.
110 ///
111 /// </summary>
112 /// <returns> The LH child subband, or null if there are no childs.
113 ///
114 /// </returns>
115 override public Subband LH
116 {
117 get
118 {
119 return subb_LH;
120 }
121  
122 }
123 /// <summary> Returns the HH child subband of this subband.
124 ///
125 /// </summary>
126 /// <returns> The HH child subband, or null if there are no childs.
127 ///
128 /// </returns>
129 override public Subband HH
130 {
131 get
132 {
133 return subb_HH;
134 }
135  
136 }
137 /// <summary> This function returns the horizontal wavelet filter relevant to this
138 /// subband
139 ///
140 /// </summary>
141 /// <returns> The horizontal wavelet filter
142 ///
143 /// </returns>
144 override public WaveletFilter HorWFilter
145 {
146 get
147 {
148 return hFilter;
149 }
150  
151 }
152 /// <summary> This function returns the vertical wavelet filter relevant to this
153 /// subband
154 ///
155 /// </summary>
156 /// <returns> The vertical wavelet filter
157 ///
158 /// </returns>
159 override public WaveletFilter VerWFilter
160 {
161 get
162 {
163 return hFilter;
164 }
165  
166 }
167  
168 /// <summary>The reference to the parent of this subband. It is null for the root
169 /// element. It is null by default.
170 /// </summary>
171 public SubbandAn parentband = null;
172  
173 /// <summary>The reference to the LL subband resulting from the decomposition of
174 /// this subband. It is null by default.
175 /// </summary>
176 public SubbandAn subb_LL;
177  
178 /// <summary>The reference to the HL subband (horizontal high-pass) resulting from
179 /// the decomposition of this subband. It is null by default.
180 /// </summary>
181 public SubbandAn subb_HL;
182  
183 /// <summary>The reference to the LH subband (vertical high-pass) resulting from
184 /// the decomposition of this subband. It is null by default.
185 ///
186 /// </summary>
187 public SubbandAn subb_LH;
188  
189 /// <summary>The reference to the HH subband resulting from the decomposition of
190 /// this subband. It is null by default.
191 /// </summary>
192 public SubbandAn subb_HH;
193  
194 /// <summary>The horizontal analysis filter used to decompose this subband. This is
195 /// applicable to "node" elements only. The default value is null.
196 /// </summary>
197 public AnWTFilter hFilter;
198  
199 /// <summary>The vertical analysis filter used to decompose this subband. This is
200 /// applicable to "node" elements only. The default value is null.
201 /// </summary>
202 public AnWTFilter vFilter;
203  
204 /// <summary>The L2-norm of the synthesis basis waveform of this subband,
205 /// applicable to "leafs" only. By default it is -1 (i.e. not calculated
206 /// yet).
207 ///
208 /// </summary>
209 public float l2Norm = - 1.0f;
210  
211 /// <summary> The contribution to the MSE or WMSE error that would result in the
212 /// image if there was an error of exactly one quantization step size in
213 /// the sample of the subband. This value is expressed relative to a
214 /// nominal dynamic range in the image domain of exactly 1.0. This field
215 /// contains valid data only after quantization 9See Quantizer).
216 ///
217 /// </summary>
218 /// <seealso cref="jj2000.j2k.quantization.quantizer.Quantizer">
219 ///
220 /// </seealso>
221 public float stepWMSE;
222  
223 /// <summary> Creates a SubbandAn element with all the default values. The dimensions
224 /// are (0,0) and the upper left corner is (0,0).
225 ///
226 /// </summary>
227 public SubbandAn()
228 {
229 }
230  
231 /// <summary> Creates the top-level node and the entire subband tree, with the
232 /// top-level dimensions, the number of decompositions, and the
233 /// decomposition tree as specified.
234 ///
235 /// <p>This constructor just calls the same constructor of the super class,
236 /// and then calculates the L2-norm (or energy weight) of each leaf.</p>
237 ///
238 /// <p>This constructor does not initialize the value of the magBits or
239 /// stepWMSE member variables. This variables are normally initialized by
240 /// the quantizer (see Quantizer).</p>
241 ///
242 /// </summary>
243 /// <param name="w">The top-level width
244 ///
245 /// </param>
246 /// <param name="h">The top-level height
247 ///
248 /// </param>
249 /// <param name="ulcx">The horizontal coordinate of the upper-left corner with
250 /// respect to the canvas origin, in the component grid.
251 ///
252 /// </param>
253 /// <param name="ulcy">The vertical coordinate of the upper-left corner with
254 /// respect to the canvas origin, in the component grid.
255 ///
256 /// </param>
257 /// <param name="lvls">The number of levels (or LL decompositions) in the tree.
258 ///
259 /// </param>
260 /// <param name="hfilters">The horizontal wavelet analysis filters for each
261 /// resolution level, starting at resolution level 0.
262 ///
263 /// </param>
264 /// <param name="vfilters">The vertical wavelet analysis filters for each
265 /// resolution level, starting at resolution level 0.
266 ///
267 /// </param>
268 /// <seealso cref="Subband.Subband(int,int,int,int,int,">
269 /// WaveletFilter[],WaveletFilter[])
270 ///
271 /// </seealso>
272 /// <seealso cref="jj2000.j2k.quantization.quantizer.Quantizer">
273 ///
274 /// </seealso>
275 public SubbandAn(int w, int h, int ulcx, int ulcy, int lvls, WaveletFilter[] hfilters, WaveletFilter[] vfilters):base(w, h, ulcx, ulcy, lvls, hfilters, vfilters)
276 {
277 // Caculate the L2-norms
278 calcL2Norms();
279 }
280  
281 /// <summary> Splits the current subband in its four subbands. It changes the status
282 /// of this element (from a leaf to a node, and sets the filters), creates
283 /// the childs and initializes them. An IllegalArgumentException is thrown
284 /// if this subband is not a leaf.
285 ///
286 /// <p>It uses the initChilds() method to initialize the childs.</p>
287 ///
288 /// </summary>
289 /// <param name="hfilter">The horizontal wavelet filter used to decompose this
290 /// subband. It has to be a AnWTFilter object.
291 ///
292 /// </param>
293 /// <param name="vfilter">The vertical wavelet filter used to decompose this
294 /// subband. It has to be a AnWTFilter object.
295 ///
296 /// </param>
297 /// <returns> A reference to the LL leaf (subb_LL).
298 ///
299 /// </returns>
300 /// <seealso cref="Subband.initChilds">
301 ///
302 /// </seealso>
303 protected internal override Subband split(WaveletFilter hfilter, WaveletFilter vfilter)
304 {
305 // Test that this is a node
306 if (isNode)
307 {
308 throw new System.ArgumentException();
309 }
310  
311 // Modify this element into a node and set the filters
312 isNode = true;
313 this.hFilter = (AnWTFilter) hfilter;
314 this.vFilter = (AnWTFilter) vfilter;
315  
316 // Create childs
317 subb_LL = new SubbandAn();
318 subb_LH = new SubbandAn();
319 subb_HL = new SubbandAn();
320 subb_HH = new SubbandAn();
321  
322 // Assign parent
323 subb_LL.parentband = this;
324 subb_HL.parentband = this;
325 subb_LH.parentband = this;
326 subb_HH.parentband = this;
327  
328 // Initialize childs
329 initChilds();
330  
331 // Return reference to LL subband
332 return subb_LL;
333 }
334  
335 /// <summary> Calculates the basis waveform of the first leaf for which the L2-norm
336 /// has not been calculated yet. This method searches recursively for the
337 /// first leaf for which the value has not been calculated yet, and then
338 /// calculates the L2-norm on the return path.
339 ///
340 /// <p>The wfs argument should be a size 2 array of float arrays (i.e. 2D
341 /// array) and it must be of length 2 (or more). When returning, wfs[0]
342 /// will contain the line waveform, and wfs[1] will contain the column
343 /// waveform.</p>
344 ///
345 /// <p>This method can not be called on an element that ahs a non-negative
346 /// value in l2Norm, since that means that we are done.</p>
347 ///
348 /// </summary>
349 /// <param name="wfs">An size 2 array where the line and column waveforms will be
350 /// returned.
351 ///
352 /// </param>
353 private void calcBasisWaveForms(float[][] wfs)
354 {
355 if (l2Norm < 0)
356 {
357 // We are not finished with this element yet
358 if (isNode)
359 {
360 // We are on a node => search on childs
361 if (subb_LL.l2Norm < 0f)
362 {
363 subb_LL.calcBasisWaveForms(wfs);
364 wfs[0] = hFilter.getLPSynWaveForm(wfs[0], null);
365 wfs[1] = vFilter.getLPSynWaveForm(wfs[1], null);
366 }
367 else if (subb_HL.l2Norm < 0f)
368 {
369 subb_HL.calcBasisWaveForms(wfs);
370 wfs[0] = hFilter.getHPSynWaveForm(wfs[0], null);
371 wfs[1] = vFilter.getLPSynWaveForm(wfs[1], null);
372 }
373 else if (subb_LH.l2Norm < 0f)
374 {
375 subb_LH.calcBasisWaveForms(wfs);
376 wfs[0] = hFilter.getLPSynWaveForm(wfs[0], null);
377 wfs[1] = vFilter.getHPSynWaveForm(wfs[1], null);
378 }
379 else if (subb_HH.l2Norm < 0f)
380 {
381 subb_HH.calcBasisWaveForms(wfs);
382 wfs[0] = hFilter.getHPSynWaveForm(wfs[0], null);
383 wfs[1] = vFilter.getHPSynWaveForm(wfs[1], null);
384 }
385 else
386 {
387 // There is an error! If all childs have non-negative
388 // l2norm, then this node should have non-negative l2norm
389 throw new System.ApplicationException("You have found a bug in JJ2000!");
390 }
391 }
392 else
393 {
394 // This is a leaf, just use diracs (null is equivalent to
395 // dirac)
396 wfs[0] = new float[1];
397 wfs[0][0] = 1.0f;
398 wfs[1] = new float[1];
399 wfs[1][0] = 1.0f;
400 }
401 }
402 else
403 {
404 // This is an error! The calcBasisWaveForms() method is never
405 // called on an element with non-negative l2norm
406 throw new System.ApplicationException("You have found a bug in JJ2000!");
407 }
408 }
409  
410 /// <summary> Assigns the given L2-norm to the first leaf that does not have an
411 /// L2-norm value yet (i.e. l2norm is negative). The search is done
412 /// recursively and in the same order as that of the calcBasisWaveForms()
413 /// method, so that this method is used to assigne the l2norm of the
414 /// previously computed waveforms.
415 ///
416 /// <p>This method can not be called on an element that ahs a non-negative
417 /// value in l2Norm, since that means that we are done.</p>
418 ///
419 /// </summary>
420 /// <param name="l2n">The L2-norm to assign.
421 ///
422 /// </param>
423 private void assignL2Norm(float l2n)
424 {
425 if (l2Norm < 0)
426 {
427 // We are not finished with this element yet
428 if (isNode)
429 {
430 // We are on a node => search on childs
431 if (subb_LL.l2Norm < 0f)
432 {
433 subb_LL.assignL2Norm(l2n);
434 }
435 else if (subb_HL.l2Norm < 0f)
436 {
437 subb_HL.assignL2Norm(l2n);
438 }
439 else if (subb_LH.l2Norm < 0f)
440 {
441 subb_LH.assignL2Norm(l2n);
442 }
443 else if (subb_HH.l2Norm < 0f)
444 {
445 subb_HH.assignL2Norm(l2n);
446 // If child now is done, we are done
447 if (subb_HH.l2Norm >= 0f)
448 {
449 l2Norm = 0f; // We are on a node, any non-neg value OK
450 }
451 }
452 else
453 {
454 // There is an error! If all childs have non-negative
455 // l2norm, then this node should have non-negative l2norm
456 throw new System.ApplicationException("You have found a bug in JJ2000!");
457 }
458 }
459 else
460 {
461 // This is a leaf, assign the L2-norm
462 l2Norm = l2n;
463 }
464 }
465 else
466 {
467 // This is an error! The assignL2Norm() method is never called on
468 // an element with non-negative l2norm
469 throw new System.ApplicationException("You have found a bug in JJ2000!");
470 }
471 }
472  
473  
474 /// <summary> Calculates the L2-norm of the sythesis waveforms of every leaf in the
475 /// tree. This method should only be called on the root element.
476 ///
477 /// </summary>
478 private void calcL2Norms()
479 {
480 int i;
481 float[][] wfs = new float[2][];
482 double acc;
483 float l2n;
484  
485 // While we are not done on the root element, compute basis functions
486 // and assign L2-norm
487 while (l2Norm < 0f)
488 {
489 calcBasisWaveForms(wfs);
490 // Compute line L2-norm, which is the product of the line
491 // and column L2-norms
492 acc = 0.0;
493 for (i = wfs[0].Length - 1; i >= 0; i--)
494 {
495 acc += wfs[0][i] * wfs[0][i];
496 }
497 //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
498 l2n = (float) System.Math.Sqrt(acc);
499 // Compute column L2-norm
500 acc = 0.0;
501 for (i = wfs[1].Length - 1; i >= 0; i--)
502 {
503 acc += wfs[1][i] * wfs[1][i];
504 }
505 //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
506 l2n *= (float) System.Math.Sqrt(acc);
507 // Release waveforms
508 wfs[0] = null;
509 wfs[1] = null;
510 // Assign the value
511 assignL2Norm(l2n);
512 }
513 }
514 }
515 }