corrade-vassal – Blame information for rev 1
?pathlinks?
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 | } |