001/*
002 * $RCSfile: AnWTFilterFloatLift9x7.java,v $
003 * $Revision: 1.1 $
004 * $Date: 2005/02/11 05:02:29 $
005 * $State: Exp $
006 *
007 * Class:                   AnWTFilterFloatLift9x7
008 *
009 * Description:             An analyzing 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 * */
045package jj2000.j2k.wavelet.analysis;
046
047import jj2000.j2k.wavelet.FilterTypes;
048
049/**
050 * This class inherits from the analysis wavelet filter definition
051 * for int data. It implements the forward wavelet transform
052 * specifically for the 9x7 filter. The implementation is based on
053 * the lifting scheme.
054 *
055 * <P>See the AnWTFilter class for details such as
056 * normalization, how to split odd-length signals, etc. In particular,
057 * this method assumes that the low-pass coefficient is computed first.
058 *
059 * @see AnWTFilter
060 * @see AnWTFilterFloat
061 * */
062public class AnWTFilterFloatLift9x7 extends AnWTFilterFloat {
063
064    /** The low-pass synthesis filter of the 9x7 wavelet transform */
065    private final static float LPSynthesisFilter[] =
066    { -0.091272f, -0.057544f, 0.591272f, 1.115087f,
067      0.591272f, -0.057544f, -0.091272f};
068
069    /** The high-pass synthesis filter of the 9x7 wavelet transform */
070    private final static float HPSynthesisFilter[] =
071        { 0.026749f, 0.016864f, -0.078223f, -0.266864f,
072          0.602949f,
073          -0.266864f, -0.078223f, 0.016864f, 0.026749f };
074
075    /** The value of the first lifting step coefficient */
076    public final static float ALPHA = -1.586134342f;
077
078    /** The value of the second lifting step coefficient */
079    public final static float BETA = -0.05298011854f;
080
081    /** The value of the third lifting step coefficient */
082    public final static float GAMMA = 0.8829110762f;
083
084    /** The value of the fourth lifting step coefficient */
085    public final static float DELTA = 0.443568522f;
086
087    /** The value of the low-pass subband normalization factor */
088    public final static float KL = 0.8128930655f;//1.149604398f;
089
090    /** The value of the high-pass subband normalization factor */
091    public final static float KH = 1.230174106f;//0.8698644523f;
092
093    /**
094     * An implementation of the analyze_lpf() method that works on int
095     * data, for the forward 9x7 wavelet transform using the
096     * lifting scheme. See the general description of the analyze_lpf()
097     * method in the AnWTFilter class for more details.
098     *
099     * <P>The coefficients of the first lifting step are [ALPHA 1 ALPHA].
100     *
101     * <P>The coefficients of the second lifting step are [BETA 1 BETA].
102     *
103     * <P>The coefficients of the third lifting step are [GAMMA 1 GAMMA].
104     *
105     * <P>The coefficients of the fourth lifting step are [DELTA 1 DELTA].
106     *
107     * <P>The low-pass and high-pass subbands are normalized by respectively
108     * a factor of KL and a factor of KH
109     *
110     * @param inSig This is the array that contains the input
111     * signal.
112     *
113     * @param inOff This is the index in inSig of the first sample to
114     * filter.
115     *
116     * @param inLen This is the number of samples in the input signal
117     * to filter.
118     *
119     * @param inStep This is the step, or interleave factor, of the
120     * input signal samples in the inSig array.
121     *
122     * @param lowSig This is the array where the low-pass output
123     * signal is placed.
124     *
125     * @param lowOff This is the index in lowSig of the element where
126     * to put the first low-pass output sample.
127     *
128     * @param lowStep This is the step, or interleave factor, of the
129     * low-pass output samples in the lowSig array.
130     *
131     * @param highSig This is the array where the high-pass output
132     * signal is placed.
133     *
134     * @param highOff This is the index in highSig of the element where
135     * to put the first high-pass output sample.
136     *
137     * @param highStep This is the step, or interleave factor, of the
138     * high-pass output samples in the highSig array.
139     * */
140    public
141        void analyze_lpf(float inSig[], int inOff, int inLen, int inStep,
142                     float lowSig[], int lowOff, int lowStep,
143                     float highSig[], int highOff, int highStep) {
144        int i,maxi;
145        int iStep = 2 * inStep; //Subsampling in inSig
146        int ik;    //Indexing inSig
147        int lk;    //Indexing lowSig
148        int hk;    //Indexing highSig
149
150        // Generate intermediate high frequency subband
151
152        //Initialize counters
153        ik = inOff + inStep;
154        lk = lowOff;
155        hk = highOff;
156
157        //Apply first lifting step to each "inner" sample
158        for( i = 1, maxi = inLen-1; i < maxi; i += 2 ) {
159            highSig[hk] = inSig[ik] +
160                ALPHA*(inSig[ik-inStep] + inSig[ik+inStep]);
161
162            ik += iStep;
163            hk += highStep;
164        }
165
166        //Handle head boundary effect if input signal has even length
167        if(inLen % 2 == 0) {
168           highSig[hk] = inSig[ik] + 2*ALPHA*inSig[ik-inStep];
169        }
170
171        // Generate intermediate low frequency subband
172
173        //Initialize counters
174        ik = inOff;
175        lk = lowOff;
176        hk = highOff;
177
178        if(inLen>1) {
179            lowSig[lk] = inSig[ik] + 2*BETA*highSig[hk];
180        }
181        else {
182            lowSig[lk] = inSig[ik];
183        }
184
185        ik += iStep;
186        lk += lowStep;
187        hk += highStep;
188
189        //Apply lifting step to each "inner" sample
190        for( i = 2, maxi = inLen-1; i < maxi; i += 2 ) {
191            lowSig[lk] = inSig[ik] +
192                BETA*(highSig[hk-highStep] + highSig[hk]);
193
194            ik += iStep;
195            lk += lowStep;
196            hk += highStep;
197        }
198
199        //Handle head boundary effect if input signal has odd length
200        if((inLen % 2 == 1)&&(inLen>2)) {
201            lowSig[lk] =  inSig[ik] + 2*BETA*highSig[hk-highStep];
202        }
203
204        // Generate high frequency subband
205
206        //Initialize counters
207        lk = lowOff;
208        hk = highOff;
209
210        //Apply first lifting step to each "inner" sample
211        for(i = 1, maxi = inLen-1; i < maxi; i += 2)  {
212            highSig[hk] += GAMMA*(lowSig[lk] + lowSig[lk+lowStep]);
213
214            lk += lowStep;
215            hk += highStep;
216        }
217
218        //Handle head boundary effect if input signal has even length
219        if(inLen % 2 == 0) {
220            highSig[hk] += 2*GAMMA*lowSig[lk];
221        }
222
223        // Generate low frequency subband
224
225        //Initialize counters
226        lk = lowOff;
227        hk = highOff;
228
229        //Handle tail boundary effect
230        //If access the overlap then perform the lifting step
231        if(inLen>1){
232            lowSig[lk] += 2*DELTA*highSig[hk];
233        }
234
235        lk += lowStep;
236        hk += highStep;
237
238        //Apply lifting step to each "inner" sample
239        for(i = 2, maxi = inLen-1; i < maxi; i += 2) {
240            lowSig[lk] +=
241                DELTA*(highSig[hk - highStep] + highSig[hk]);
242
243            lk += lowStep;
244            hk += highStep;
245        }
246
247        //Handle head boundary effect if input signal has odd length
248        if((inLen % 2 == 1)&&(inLen>2)) {
249            lowSig[lk] +=  2*DELTA*highSig[hk-highStep];
250        }
251
252        // Normalize low and high frequency subbands
253
254        //Re-initialize counters
255        lk = lowOff;
256        hk = highOff;
257
258        //Normalize each sample
259        for( i=0 ; i<(inLen>>1); i++ ) {
260            lowSig[lk] *= KL;
261            highSig[hk] *= KH;
262            lk += lowStep;
263            hk += highStep;
264        }
265        //If the input signal has odd length then normalize the last low-pass
266        //coefficient (if input signal is length one filter is identity)
267        if( inLen%2==1 && inLen != 1) {
268            lowSig[lk] *= KL;
269        }
270    }
271
272    /**
273     * An implementation of the analyze_hpf() method that works on int
274     * data, for the forward 9x7 wavelet transform using the
275     * lifting scheme. See the general description of the analyze_hpf() method
276     * in the AnWTFilter class for more details.
277     *
278     * <P>The coefficients of the first lifting step are [ALPHA 1 ALPHA].
279     *
280     * <P>The coefficients of the second lifting step are [BETA 1 BETA].
281     *
282     * <P>The coefficients of the third lifting step are [GAMMA 1 GAMMA].
283     *
284     * <P>The coefficients of the fourth lifting step are [DELTA 1 DELTA].
285     *
286     * <P>The low-pass and high-pass subbands are normalized by respectively
287     * a factor of KL and a factor of KH
288     *
289     * @param inSig This is the array that contains the input
290     * signal.
291     *
292     * @param inOff This is the index in inSig of the first sample to
293     * filter.
294     *
295     * @param inLen This is the number of samples in the input signal
296     * to filter.
297     *
298     * @param inStep This is the step, or interleave factor, of the
299     * input signal samples in the inSig array.
300     *
301     * @param lowSig This is the array where the low-pass output
302     * signal is placed.
303     *
304     * @param lowOff This is the index in lowSig of the element where
305     * to put the first low-pass output sample.
306     *
307     * @param lowStep This is the step, or interleave factor, of the
308     * low-pass output samples in the lowSig array.
309     *
310     * @param highSig This is the array where the high-pass output
311     * signal is placed.
312     *
313     * @param highOff This is the index in highSig of the element where
314     * to put the first high-pass output sample.
315     *
316     * @param highStep This is the step, or interleave factor, of the
317     * high-pass output samples in the highSig array.
318     *
319     * @see AnWTFilter#analyze_hpf
320     * */
321    public void analyze_hpf(float inSig[], int inOff, int inLen, int inStep,
322                    float lowSig[], int lowOff, int lowStep,
323                    float highSig[], int highOff, int highStep) {
324
325        int i,maxi;
326        int iStep = 2 * inStep; //Subsampling in inSig
327        int ik;    //Indexing inSig
328        int lk;    //Indexing lowSig
329        int hk;    //Indexing highSig
330
331        // Generate intermediate high frequency subband
332
333        //Initialize counters
334        ik = inOff;
335        lk = lowOff;
336        hk = highOff;
337
338        if ( inLen>1 ) {
339            // apply symmetric extension.
340            highSig[hk] = inSig[ik] + 2*ALPHA*inSig[ik+inStep];
341        }
342        else {
343            // Normalize for Nyquist gain
344            highSig[hk] = inSig[ik]*2;
345        }
346
347        ik += iStep;
348        hk += highStep;
349
350        //Apply first lifting step to each "inner" sample
351        for( i = 2 ; i < inLen-1 ; i += 2 ) {
352            highSig[hk] = inSig[ik] +
353                ALPHA*(inSig[ik-inStep] + inSig[ik+inStep]);
354            ik += iStep;
355            hk += highStep;
356        }
357
358        //If input signal has odd length then we perform the lifting step
359        // i.e. apply a symmetric extension.
360        if( (inLen%2==1) && (inLen>1) ) {
361            highSig[hk] = inSig[ik] + 2*ALPHA*inSig[ik-inStep];
362        }
363
364        // Generate intermediate low frequency subband
365
366        //Initialize counters
367        //ik = inOff + inStep;
368        ik = inOff + inStep;
369        lk = lowOff;
370        hk = highOff;
371
372        //Apply lifting step to each "inner" sample
373        // we are at the component boundary
374        for(i = 1; i < inLen-1; i += 2) {
375            lowSig[lk] = inSig[ik] +
376                BETA*(highSig[hk] + highSig[hk+highStep]);
377
378            ik += iStep;
379            lk += lowStep;
380            hk += highStep;
381        }
382        if ( inLen>1 && inLen%2==0 ) {
383            // symetric extension
384            lowSig[lk] = inSig[ik]+2*BETA*highSig[hk];
385        }
386
387        // Generate high frequency subband
388
389        //Initialize counters
390        lk = lowOff;
391        hk = highOff;
392
393        if ( inLen>1 ) {
394            // symmetric extension.
395            highSig[hk] += GAMMA*2*lowSig[lk];
396        }
397        //lk += lowStep;
398        hk += highStep;
399
400        //Apply first lifting step to each "inner" sample
401        for(i = 2 ; i < inLen-1 ; i += 2)  {
402            highSig[hk] += GAMMA*(lowSig[lk] + lowSig[lk+lowStep]);
403            lk += lowStep;
404            hk += highStep;
405        }
406
407        //Handle head boundary effect
408        if ( inLen>1 && inLen%2==1 ) {
409            // symmetric extension.
410            highSig[hk] += GAMMA*2*lowSig[lk];
411        }
412
413        // Generate low frequency subband
414
415        //Initialize counters
416        lk = lowOff;
417        hk = highOff;
418
419        // we are at the component boundary
420        for(i = 1 ; i < inLen-1; i += 2) {
421            lowSig[lk] += DELTA*(highSig[hk] + highSig[hk+highStep]);
422            lk += lowStep;
423            hk += highStep;
424        }
425
426        if ( inLen>1 && inLen%2==0 ) {
427            lowSig[lk] += DELTA*2*highSig[hk];
428        }
429
430        // Normalize low and high frequency subbands
431
432        //Re-initialize counters
433        lk = lowOff;
434        hk = highOff;
435
436        //Normalize each sample
437        for( i=0 ; i<(inLen>>1); i++ ) {
438            lowSig[lk] *= KL;
439            highSig[hk] *= KH;
440            lk += lowStep;
441            hk += highStep;
442        }
443        //If the input signal has odd length then normalize the last high-pass
444        //coefficient (if input signal is length one filter is identity)
445        if( inLen%2==1 && inLen != 1) {
446            highSig[hk] *= KH;
447        }
448    }
449
450    /**
451     * Returns the negative support of the low-pass analysis
452     * filter. That is the number of taps of the filter in the
453     * negative direction.
454     *
455     * @return 2
456     * */
457    public int getAnLowNegSupport() {
458        return 4;
459    }
460
461    /**
462     * Returns the positive support of the low-pass analysis
463     * filter. That is the number of taps of the filter in the
464     * negative direction.
465     *
466     * @return The number of taps of the low-pass analysis filter in
467     * the positive direction
468     * */
469    public int getAnLowPosSupport() {
470        return 4;
471    }
472
473    /**
474     * Returns the negative support of the high-pass analysis
475     * filter. That is the number of taps of the filter in the
476     * negative direction.
477     *
478     * @return The number of taps of the high-pass analysis filter in
479     * the negative direction
480     * */
481    public int getAnHighNegSupport() {
482        return 3;
483    }
484
485    /**
486     * Returns the positive support of the high-pass analysis
487     * filter. That is the number of taps of the filter in the
488     * negative direction.
489     *
490     * @return The number of taps of the high-pass analysis filter in
491     * the positive direction
492     * */
493    public int getAnHighPosSupport() {
494        return 3;
495    }
496
497    /**
498     * Returns the negative support of the low-pass synthesis
499     * filter. That is the number of taps of the filter in the
500     * negative direction.
501     *
502     * <P>A MORE PRECISE DEFINITION IS NEEDED
503     *
504     * @return The number of taps of the low-pass synthesis filter in
505     * the negative direction
506     * */
507    public int getSynLowNegSupport() {
508        return 3;
509    }
510
511    /**
512     * Returns the positive support of the low-pass synthesis
513     * filter. That is the number of taps of the filter in the
514     * negative direction.
515     *
516     * <P>A MORE PRECISE DEFINITION IS NEEDED
517     *
518     * @return The number of taps of the low-pass synthesis filter in
519     * the positive direction
520     * */
521    public int getSynLowPosSupport() {
522        return 3;
523    }
524
525    /**
526     * Returns the negative support of the high-pass synthesis
527     * filter. That is the number of taps of the filter in the
528     * negative direction.
529     *
530     * <P>A MORE PRECISE DEFINITION IS NEEDED
531     *
532     * @return The number of taps of the high-pass synthesis filter in
533     * the negative direction
534     * */
535    public int getSynHighNegSupport() {
536        return 4;
537    }
538
539    /**
540     * Returns the positive support of the high-pass synthesis
541     * filter. That is the number of taps of the filter in the
542     * negative direction.
543     *
544     * <P>A MORE PRECISE DEFINITION IS NEEDED
545     *
546     * @return The number of taps of the high-pass synthesis filter in
547     * the positive direction
548     * */
549    public int getSynHighPosSupport() {
550        return 4;
551    }
552
553    /**
554     * Returns the time-reversed low-pass synthesis waveform of the
555     * filter, which is the low-pass filter. This is the time-reversed
556     * impulse response of the low-pass synthesis filter. It is used
557     * to calculate the L2-norm of the synthesis basis functions for a
558     * particular subband (also called energy weight).
559     *
560     * <P>The returned array may not be modified (i.e. a reference to
561     * the internal array may be returned by the implementation of
562     * this method).
563     *
564     * @return The time-reversed low-pass synthesis waveform of the
565     * filter.
566     * */
567    public float[] getLPSynthesisFilter() {
568        return LPSynthesisFilter;
569    }
570
571    /**
572     * Returns the time-reversed high-pass synthesis waveform of the
573     * filter, which is the high-pass filter. This is the
574     * time-reversed impulse response of the high-pass synthesis
575     * filter. It is used to calculate the L2-norm of the synthesis
576     * basis functions for a particular subband (also called energy
577     * weight).
578     *
579     * <P>The returned array may not be modified (i.e. a reference to
580     * the internal array may be returned by the implementation of
581     * this method).
582     *
583     * @return The time-reversed high-pass synthesis waveform of the
584     * filter.
585     * */
586    public float[] getHPSynthesisFilter() {
587        return HPSynthesisFilter;
588    }
589
590    /**
591     * Returns the implementation type of this filter, as defined in
592     * this class, such as WT_FILTER_INT_LIFT, WT_FILTER_FLOAT_LIFT,
593     * WT_FILTER_FLOAT_CONVOL.
594     *
595     * @return WT_FILTER_INT_LIFT.
596     * */
597    public int getImplType() {
598        return WT_FILTER_FLOAT_LIFT;
599    }
600
601    /**
602     * Returns the reversibility of the filter. A filter is considered
603     * reversible if it is suitable for lossless coding.
604     *
605     * @return true since the 9x7 is reversible, provided the appropriate
606     * rounding is performed.
607     * */
608    public boolean isReversible() {
609        return false;
610    }
611
612    /**
613     * Returns true if the wavelet filter computes or uses the
614     * same "inner" subband coefficient as the full frame wavelet transform,
615     * and false otherwise. In particular, for block based transforms with
616     * reduced overlap, this method should return false. The term "inner"
617     * indicates that this applies only with respect to the coefficient that
618     * are not affected by image boundaries processings such as symmetric
619     * extension, since there is not reference method for this.
620     *
621     * <P>The result depends on the length of the allowed overlap when
622     * compared to the overlap required by the wavelet filter. It also
623     * depends on how overlap processing is implemented in the wavelet
624     * filter.
625     *
626     * @param tailOvrlp This is the number of samples in the input
627     * signal before the first sample to filter that can be used for
628     * overlap.
629     *
630     * @param headOvrlp This is the number of samples in the input
631     * signal after the last sample to filter that can be used for
632     * overlap.
633     *
634     * @param inLen This is the lenght of the input signal to filter.The
635     * required number of samples in the input signal after the last sample
636     * depends on the length of the input signal.
637     *
638     * @return true if both overlaps are greater than 2, and correct
639     * processing is applied in the analyze() method.
640     * */
641    public boolean isSameAsFullWT(int tailOvrlp, int headOvrlp, int inLen) {
642
643        //If the input signal has even length.
644        if( inLen % 2 == 0) {
645            if( tailOvrlp >= 4 && headOvrlp >= 3 ) return true;
646            else return false;
647        }
648        //Else if the input signal has odd length.
649        else {
650            if( tailOvrlp >= 4 && headOvrlp >= 4 ) return true;
651            else return false;
652        }
653    }
654
655    /**
656     * Tests if the 'obj' object is the same filter as this one. Two filters
657     * are the same if the same filter code should be output for both filters
658     * by the encodeFilterCode() method.
659     *
660     * <P>Currently the implementation of this method only tests if 'obj' is
661     * also of the class AnWTFilterFloatLift9x7
662     *
663     * @param The object against which to test inequality.
664     * */
665    public boolean equals(Object obj) {
666        // To spped up test, first test for reference equality
667        return obj == this ||
668            obj instanceof AnWTFilterFloatLift9x7;
669    }
670
671    /**
672     * Returns the type of filter used according to the FilterTypes
673     * interface(W9x7).
674     *
675     * @see FilterTypes
676     *
677     * @return The filter type.
678     * */
679    public int getFilterType(){
680        return FilterTypes.W9X7;
681    }
682
683    /** Debugging method */
684    public String toString(){
685        return "w9x7";
686    }
687}