001: /*
002: * $RCSfile: SynWTFilterFloatLift9x7.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:34 $
005: * $State: Exp $
006: *
007: * Class: SynWTFilterFloatLift9x7
008: *
009: * Description: A synthetizing wavelet filter implementing the
010: * lifting 9x7 transform.
011: *
012: *
013: *
014: * COPYRIGHT:
015: *
016: * This software module was originally developed by Raphaël Grosbois and
017: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
018: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
019: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
020: * Centre France S.A) in the course of development of the JPEG2000
021: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
022: * software module is an implementation of a part of the JPEG 2000
023: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
024: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
025: * Partners) agree not to assert against ISO/IEC and users of the JPEG
026: * 2000 Standard (Users) any of their rights under the copyright, not
027: * including other intellectual property rights, for this software module
028: * with respect to the usage by ISO/IEC and Users of this software module
029: * or modifications thereof for use in hardware or software products
030: * claiming conformance to the JPEG 2000 Standard. Those intending to use
031: * this software module in hardware or software products are advised that
032: * their use may infringe existing patents. The original developers of
033: * this software module, JJ2000 Partners and ISO/IEC assume no liability
034: * for use of this software module or modifications thereof. No license
035: * or right to this software module is granted for non JPEG 2000 Standard
036: * conforming products. JJ2000 Partners have full right to use this
037: * software module for his/her own purpose, assign or donate this
038: * software module to any third party and to inhibit third parties from
039: * using this software module for non JPEG 2000 Standard conforming
040: * products. This copyright notice must be included in all copies or
041: * derivative works of this software module.
042: *
043: * Copyright (c) 1999/2000 JJ2000 Partners.
044: * */
045:
046: package jj2000.j2k.wavelet.synthesis;
047:
048: import jj2000.j2k.wavelet.*;
049: import jj2000.j2k.image.*;
050: import jj2000.j2k.*;
051:
052: /**
053: * This class inherits from the synthesis wavelet filter definition for int
054: * data. It implements the inverse wavelet transform specifically for the 9x7
055: * filter. The implementation is based on the lifting scheme.
056: *
057: * <P>See the SynWTFilter class for details such as normalization, how to
058: * split odd-length signals, etc. In particular, this method assumes that the
059: * low-pass coefficient is computed first.
060: *
061: * @see SynWTFilter
062: * @see SynWTFilterFloat
063: * */
064: public class SynWTFilterFloatLift9x7 extends SynWTFilterFloat {
065:
066: /** The value of the first lifting step coefficient */
067: public final static float ALPHA = -1.586134342f;
068:
069: /** The value of the second lifting step coefficient */
070: public final static float BETA = -0.05298011854f;
071:
072: /** The value of the third lifting step coefficient */
073: public final static float GAMMA = 0.8829110762f;
074:
075: /** The value of the fourth lifting step coefficient */
076: public final static float DELTA = 0.4435068522f;
077:
078: /** The value of the low-pass subband normalization factor */
079: public final static float KL = 0.8128930655f;
080:
081: /** The value of the high-pass subband normalization factor */
082: public final static float KH = 1.230174106f;
083:
084: /**
085: * An implementation of the synthetize_lpf() method that works on int
086: * data, for the inverse 9x7 wavelet transform using the lifting
087: * scheme. See the general description of the synthetize_lpf() method in
088: * the SynWTFilter class for more details.
089: *
090: * <P>The low-pass and high-pass subbands are normalized by respectively a
091: * factor of 1/KL and a factor of 1/KH
092: *
093: * <P>The coefficients of the first lifting step are [-DELTA 1 -DELTA].
094: *
095: * <P>The coefficients of the second lifting step are [-GAMMA 1 -GAMMA].
096: *
097: * <P>The coefficients of the third lifting step are [-BETA 1 -BETA].
098: *
099: * <P>The coefficients of the fourth lifting step are [-ALPHA 1 -ALPHA].
100: *
101: * @param lowSig This is the array that contains the low-pass input
102: * signal.
103: *
104: * @param lowOff This is the index in lowSig of the first sample to
105: * filter.
106: *
107: * @param lowLen This is the number of samples in the low-pass input
108: * signal to filter.
109: *
110: * @param lowStep This is the step, or interleave factor, of the low-pass
111: * input signal samples in the lowSig array.
112: *
113: * @param highSig This is the array that contains the high-pass input
114: * signal.
115: *
116: * @param highOff This is the index in highSig of the first sample to
117: * filter.
118: *
119: * @param highLen This is the number of samples in the high-pass input
120: * signal to filter.
121: *
122: * @param highStep This is the step, or interleave factor, of the
123: * high-pass input signal samples in the highSig array.
124: *
125: * @param outSig This is the array where the output signal is placed. It
126: * should be long enough to contain the output signal.
127: *
128: * @param outOff This is the index in outSig of the element where to put
129: * the first output sample.
130: *
131: * @param outStep This is the step, or interleave factor, of the output
132: * samples in the outSig array.
133: *
134: * @see SynWTFilter#synthetize_lpf
135: * */
136: public void synthetize_lpf(float[] lowSig, int lowOff, int lowLen,
137: int lowStep, float[] highSig, int highOff, int highLen,
138: int highStep, float[] outSig, int outOff, int outStep) {
139:
140: int i;
141: int outLen = lowLen + highLen; //Length of the output signal
142: int iStep = 2 * outStep; //Upsampling in outSig
143: int ik; //Indexing outSig
144: int lk; //Indexing lowSig
145: int hk; //Indexing highSig
146:
147: // Generate intermediate low frequency subband
148: float sample = 0;
149:
150: //Initialize counters
151: lk = lowOff;
152: hk = highOff;
153: ik = outOff;
154:
155: //Handle tail boundary effect. Use symmetric extension
156: if (outLen > 1) {
157: outSig[ik] = lowSig[lk] / KL - 2 * DELTA * highSig[hk] / KH;
158: } else {
159: outSig[ik] = lowSig[lk];
160: }
161:
162: lk += lowStep;
163: hk += highStep;
164: ik += iStep;
165:
166: //Apply lifting step to each "inner" sample
167: for (i = 2; i < outLen - 1; i += 2, ik += iStep, lk += lowStep, hk += highStep) {
168: outSig[ik] = lowSig[lk] / KL - DELTA
169: * (highSig[hk - highStep] + highSig[hk]) / KH;
170: }
171:
172: //Handle head boundary effect if input signal has odd length
173: if (outLen % 2 == 1) {
174: if (outLen > 2) {
175: outSig[ik] = lowSig[lk] / KL - 2 * DELTA
176: * highSig[hk - highStep] / KH;
177: }
178: }
179:
180: // Generate intermediate high frequency subband
181:
182: //Initialize counters
183: lk = lowOff;
184: hk = highOff;
185: ik = outOff + outStep;
186:
187: //Apply lifting step to each "inner" sample
188: for (i = 1; i < outLen - 1; i += 2, ik += iStep, hk += highStep, lk += lowStep) {
189: outSig[ik] = highSig[hk] / KH - GAMMA
190: * (outSig[ik - outStep] + outSig[ik + outStep]);
191: }
192:
193: //Handle head boundary effect if output signal has even length
194: if (outLen % 2 == 0) {
195: outSig[ik] = highSig[hk] / KH - 2 * GAMMA
196: * outSig[ik - outStep];
197: }
198:
199: // Generate even samples (inverse low-pass filter)
200:
201: //Initialize counters
202: ik = outOff;
203:
204: //Handle tail boundary effect
205: //If access the overlap then perform the lifting step.
206: if (outLen > 1) {
207: outSig[ik] -= 2 * BETA * outSig[ik + outStep];
208: }
209: ik += iStep;
210:
211: //Apply lifting step to each "inner" sample
212: for (i = 2; i < outLen - 1; i += 2, ik += iStep) {
213: outSig[ik] -= BETA
214: * (outSig[ik - outStep] + outSig[ik + outStep]);
215: }
216:
217: //Handle head boundary effect if input signal has odd length
218: if (outLen % 2 == 1 && outLen > 2) {
219: outSig[ik] -= 2 * BETA * outSig[ik - outStep];
220: }
221:
222: // Generate odd samples (inverse high pass-filter)
223:
224: //Initialize counters
225: ik = outOff + outStep;
226:
227: //Apply first lifting step to each "inner" sample
228: for (i = 1; i < outLen - 1; i += 2, ik += iStep) {
229: outSig[ik] -= ALPHA
230: * (outSig[ik - outStep] + outSig[ik + outStep]);
231: }
232:
233: //Handle head boundary effect if input signal has even length
234: if (outLen % 2 == 0) {
235: outSig[ik] -= 2 * ALPHA * outSig[ik - outStep];
236: }
237: }
238:
239: /**
240: * An implementation of the synthetize_hpf() method that works on int
241: * data, for the inverse 9x7 wavelet transform using the lifting
242: * scheme. See the general description of the synthetize_hpf() method in
243: * the SynWTFilter class for more details.
244: *
245: * <P>The low-pass and high-pass subbands are normalized by respectively
246: * a factor of 1/KL and a factor of 1/KH
247: *
248: * <P>The coefficients of the first lifting step are [-DELTA 1 -DELTA].
249: *
250: * <P>The coefficients of the second lifting step are [-GAMMA 1 -GAMMA].
251: *
252: * <P>The coefficients of the third lifting step are [-BETA 1 -BETA].
253: *
254: * <P>The coefficients of the fourth lifting step are [-ALPHA 1 -ALPHA].
255: *
256: * @param lowSig This is the array that contains the low-pass
257: * input signal.
258: *
259: * @param lowOff This is the index in lowSig of the first sample to
260: * filter.
261: *
262: * @param lowLen This is the number of samples in the low-pass input
263: * signal to filter.
264: *
265: * @param lowStep This is the step, or interleave factor, of the low-pass
266: * input signal samples in the lowSig array.
267: *
268: * @param highSig This is the array that contains the high-pass input
269: * signal.
270: *
271: * @param highOff This is the index in highSig of the first sample to
272: * filter.
273: *
274: * @param highLen This is the number of samples in the high-pass input
275: * signal to filter.
276: *
277: * @param highStep This is the step, or interleave factor, of the
278: * high-pass input signal samples in the highSig array.
279: *
280: * @param outSig This is the array where the output signal is placed. It
281: * should be long enough to contain the output signal.
282: *
283: * @param outOff This is the index in outSig of the element where to put
284: * the first output sample.
285: *
286: * @param outStep This is the step, or interleave factor, of the output
287: * samples in the outSig array.
288: *
289: * @see SynWTFilter#synthetize_hpf
290: * */
291: public void synthetize_hpf(float[] lowSig, int lowOff, int lowLen,
292: int lowStep, float[] highSig, int highOff, int highLen,
293: int highStep, float[] outSig, int outOff, int outStep) {
294:
295: int i;
296: int outLen = lowLen + highLen; //Length of the output signal
297: int iStep = 2 * outStep; //Upsampling in outSig
298: int ik; //Indexing outSig
299: int lk; //Indexing lowSig
300: int hk; //Indexing highSig
301:
302: // Initialize counters
303: lk = lowOff;
304: hk = highOff;
305:
306: if (outLen != 1) {
307: int outLen2 = outLen >> 1;
308: // "Inverse normalize" each sample
309: for (i = 0; i < outLen2; i++) {
310: lowSig[lk] /= KL;
311: highSig[hk] /= KH;
312: lk += lowStep;
313: hk += highStep;
314: }
315: // "Inverse normalise" last high pass coefficient
316: if (outLen % 2 == 1) {
317: highSig[hk] /= KH;
318: }
319: } else {
320: // Normalize for Nyquist gain
321: highSig[highOff] /= 2;
322: }
323:
324: // Generate intermediate low frequency subband
325:
326: //Initialize counters
327: lk = lowOff;
328: hk = highOff;
329: ik = outOff + outStep;
330:
331: //Apply lifting step to each "inner" sample
332: for (i = 1; i < outLen - 1; i += 2) {
333: outSig[ik] = lowSig[lk] - DELTA
334: * (highSig[hk] + highSig[hk + highStep]);
335: ik += iStep;
336: lk += lowStep;
337: hk += highStep;
338: }
339:
340: if (outLen % 2 == 0 && outLen > 1) {
341: //Use symmetric extension
342: outSig[ik] = lowSig[lk] - 2 * DELTA * highSig[hk];
343: }
344:
345: // Generate intermediate high frequency subband
346:
347: //Initialize counters
348: hk = highOff;
349: ik = outOff;
350:
351: if (outLen > 1) {
352: outSig[ik] = highSig[hk] - 2 * GAMMA * outSig[ik + outStep];
353: } else {
354: outSig[ik] = highSig[hk];
355: }
356:
357: ik += iStep;
358: hk += highStep;
359:
360: //Apply lifting step to each "inner" sample
361: for (i = 2; i < outLen - 1; i += 2) {
362: outSig[ik] = highSig[hk] - GAMMA
363: * (outSig[ik - outStep] + outSig[ik + outStep]);
364: ik += iStep;
365: hk += highStep;
366: }
367:
368: //Handle head boundary effect if output signal has even length
369: if (outLen % 2 == 1 && outLen > 1) {
370: //Use symmetric extension
371: outSig[ik] = highSig[hk] - 2 * GAMMA * outSig[ik - outStep];
372: }
373:
374: // Generate even samples (inverse low-pass filter)
375:
376: //Initialize counters
377: ik = outOff + outStep;
378:
379: //Apply lifting step to each "inner" sample
380: for (i = 1; i < outLen - 1; i += 2) {
381: outSig[ik] -= BETA
382: * (outSig[ik - outStep] + outSig[ik + outStep]);
383: ik += iStep;
384: }
385:
386: if (outLen % 2 == 0 && outLen > 1) {
387: // symmetric extension.
388: outSig[ik] -= 2 * BETA * outSig[ik - outStep];
389: }
390:
391: // Generate odd samples (inverse high pass-filter)
392:
393: //Initialize counters
394: ik = outOff;
395:
396: if (outLen > 1) {
397: // symmetric extension.
398: outSig[ik] -= 2 * ALPHA * outSig[ik + outStep];
399: }
400: ik += iStep;
401:
402: //Apply first lifting step to each "inner" sample
403: for (i = 2; i < outLen - 1; i += 2) {
404: outSig[ik] -= ALPHA
405: * (outSig[ik - outStep] + outSig[ik + outStep]);
406: ik += iStep;
407: }
408:
409: //Handle head boundary effect if input signal has even length
410: if ((outLen % 2 == 1) && (outLen > 1)) {
411: //Use symmetric extension
412: outSig[ik] -= 2 * ALPHA * outSig[ik - outStep];
413: }
414: }
415:
416: /**
417: * Returns the negative support of the low-pass analysis filter. That is
418: * the number of taps of the filter in the negative direction.
419: *
420: * @return 2
421: * */
422: public int getAnLowNegSupport() {
423: return 4;
424: }
425:
426: /**
427: * Returns the positive support of the low-pass analysis filter. That is
428: * the number of taps of the filter in the negative direction.
429: *
430: * @return The number of taps of the low-pass analysis filter in the
431: * positive direction
432: * */
433: public int getAnLowPosSupport() {
434: return 4;
435: }
436:
437: /**
438: * Returns the negative support of the high-pass analysis filter. That is
439: * the number of taps of the filter in the negative direction.
440: *
441: * @return The number of taps of the high-pass analysis filter in
442: * the negative direction
443: * */
444: public int getAnHighNegSupport() {
445: return 3;
446: }
447:
448: /**
449: * Returns the positive support of the high-pass analysis filter. That is
450: * the number of taps of the filter in the negative direction.
451: *
452: * @return The number of taps of the high-pass analysis filter in the
453: * positive direction
454: * */
455: public int getAnHighPosSupport() {
456: return 3;
457: }
458:
459: /**
460: * Returns the negative support of the low-pass synthesis filter. That is
461: * the number of taps of the filter in the negative direction.
462: *
463: * <P>A MORE PRECISE DEFINITION IS NEEDED
464: *
465: * @return The number of taps of the low-pass synthesis filter in the
466: * negative direction
467: * */
468: public int getSynLowNegSupport() {
469: return 3;
470: }
471:
472: /**
473: * Returns the positive support of the low-pass synthesis filter. That is
474: * the number of taps of the filter in the negative direction.
475: *
476: * <P>A MORE PRECISE DEFINITION IS NEEDED
477: *
478: * @return The number of taps of the low-pass synthesis filter in the
479: * positive direction
480: * */
481: public int getSynLowPosSupport() {
482: return 3;
483: }
484:
485: /**
486: * Returns the negative support of the high-pass synthesis filter. That is
487: * the number of taps of the filter in the negative direction.
488: *
489: * <P>A MORE PRECISE DEFINITION IS NEEDED
490: *
491: * @return The number of taps of the high-pass synthesis filter in the
492: * negative direction
493: * */
494: public int getSynHighNegSupport() {
495: return 4;
496: }
497:
498: /**
499: * Returns the positive support of the high-pass synthesis filter. That is
500: * the number of taps of the filter in the negative direction.
501: *
502: * <P>A MORE PRECISE DEFINITION IS NEEDED
503: *
504: * @return The number of taps of the high-pass synthesis filter in the
505: * positive direction
506: * */
507: public int getSynHighPosSupport() {
508: return 4;
509: }
510:
511: /**
512: * Returns the implementation type of this filter, as defined in this
513: * class, such as WT_FILTER_INT_LIFT, WT_FILTER_FLOAT_LIFT,
514: * WT_FILTER_FLOAT_CONVOL.
515: *
516: * @return WT_FILTER_INT_LIFT.
517: * */
518: public int getImplType() {
519: return WT_FILTER_FLOAT_LIFT;
520: }
521:
522: /**
523: * Returns the reversibility of the filter. A filter is considered
524: * reversible if it is suitable for lossless coding.
525: *
526: * @return true since the 9x7 is reversible, provided the appropriate
527: * rounding is performed.
528: * */
529: public boolean isReversible() {
530: return false;
531: }
532:
533: /**
534: * Returns true if the wavelet filter computes or uses the
535: * same "inner" subband coefficient as the full frame wavelet transform,
536: * and false otherwise. In particular, for block based transforms with
537: * reduced overlap, this method should return false. The term "inner"
538: * indicates that this applies only with respect to the coefficient that
539: * are not affected by image boundaries processings such as symmetric
540: * extension, since there is not reference method for this.
541: *
542: * <P>The result depends on the length of the allowed overlap when
543: * compared to the overlap required by the wavelet filter. It also
544: * depends on how overlap processing is implemented in the wavelet
545: * filter.
546: *
547: * @param tailOvrlp This is the number of samples in the input
548: * signal before the first sample to filter that can be used for
549: * overlap.
550: *
551: * @param headOvrlp This is the number of samples in the input
552: * signal after the last sample to filter that can be used for
553: * overlap.
554: *
555: * @param inLen This is the lenght of the input signal to filter.The
556: * required number of samples in the input signal after the last sample
557: * depends on the length of the input signal.
558: *
559: * @return true if both overlaps are greater than 2, and correct
560: * processing is applied in the analyze() method.
561: *
562: *
563: *
564: */
565: public boolean isSameAsFullWT(int tailOvrlp, int headOvrlp,
566: int inLen) {
567:
568: //If the input signal has even length.
569: if (inLen % 2 == 0) {
570: if (tailOvrlp >= 2 && headOvrlp >= 1)
571: return true;
572: else
573: return false;
574: }
575: //Else if the input signal has odd length.
576: else {
577: if (tailOvrlp >= 2 && headOvrlp >= 2)
578: return true;
579: else
580: return false;
581: }
582: }
583:
584: /**
585: * Returns a string of information about the synthesis wavelet filter
586: *
587: * @return wavelet filter type.
588: *
589: *
590: */
591: public String toString() {
592: return "w9x7 (lifting)";
593: }
594: }
|