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
046package jj2000.j2k.wavelet.synthesis;
047
048
049/**
050 * This class inherits from the synthesis wavelet filter definition for int
051 * data. It implements the inverse wavelet transform specifically for the 9x7
052 * filter. The implementation is based on the lifting scheme.
053 *
054 * <P>See the SynWTFilter class for details such as normalization, how to
055 * split odd-length signals, etc. In particular, this method assumes that the
056 * low-pass coefficient is computed first.
057 *
058 * @see SynWTFilter
059 * @see SynWTFilterFloat
060 * */
061public class SynWTFilterFloatLift9x7 extends SynWTFilterFloat {
062    
063    /** The value of the first lifting step coefficient */
064    public final static float ALPHA = -1.586134342f;
065
066    /** The value of the second lifting step coefficient */
067    public final static float BETA = -0.05298011854f;
068
069    /** The value of the third lifting step coefficient */
070    public final static float GAMMA = 0.8829110762f;
071
072    /** The value of the fourth lifting step coefficient */
073    public final static float DELTA = 0.4435068522f;
074
075    /** The value of the low-pass subband normalization factor */
076    public final static float KL = 0.8128930655f;
077
078    /** The value of the high-pass subband normalization factor */
079    public final static float KH = 1.230174106f;
080    
081    /**
082     * An implementation of the synthetize_lpf() method that works on int
083     * data, for the inverse 9x7 wavelet transform using the lifting
084     * scheme. See the general description of the synthetize_lpf() method in
085     * the SynWTFilter class for more details.
086     *
087     * <P>The low-pass and high-pass subbands are normalized by respectively a
088     * factor of 1/KL and a factor of 1/KH
089     *
090     * <P>The coefficients of the first lifting step are [-DELTA 1 -DELTA]. 
091     *
092     * <P>The coefficients of the second lifting step are [-GAMMA 1 -GAMMA].
093     * 
094     * <P>The coefficients of the third lifting step are [-BETA 1 -BETA]. 
095     *
096     * <P>The coefficients of the fourth lifting step are [-ALPHA 1 -ALPHA].
097     *
098     * @param lowSig This is the array that contains the low-pass input
099     * signal.
100     *
101     * @param lowOff This is the index in lowSig of the first sample to
102     * filter.
103     *
104     * @param lowLen This is the number of samples in the low-pass input
105     * signal to filter.
106     *
107     * @param lowStep This is the step, or interleave factor, of the low-pass
108     * input signal samples in the lowSig array.
109     *
110     * @param highSig This is the array that contains the high-pass input
111     * signal.
112     *
113     * @param highOff This is the index in highSig of the first sample to
114     * filter.
115     *
116     * @param highLen This is the number of samples in the high-pass input
117     * signal to filter.
118     *
119     * @param highStep This is the step, or interleave factor, of the
120     * high-pass input signal samples in the highSig array.
121     *
122     * @param outSig This is the array where the output signal is placed. It
123     * should be long enough to contain the output signal.
124     *
125     * @param outOff This is the index in outSig of the element where to put
126     * the first output sample.
127     *
128     * @param outStep This is the step, or interleave factor, of the output
129     * samples in the outSig array.
130     *
131     * @see SynWTFilter#synthetize_lpf
132     * */
133    public
134        void synthetize_lpf(float[] lowSig,int lowOff,int lowLen,int lowStep,
135                            float[] highSig,int highOff,int highLen,
136                            int highStep,
137                            float[] outSig, int outOff, int outStep) {
138                        
139        int i;
140        int outLen = lowLen + highLen; //Length of the output signal
141        int iStep = 2*outStep; //Upsampling in outSig
142        int ik; //Indexing outSig
143        int lk; //Indexing lowSig
144        int hk; //Indexing highSig
145        
146        // Generate intermediate low frequency subband
147        float sample = 0;
148
149        //Initialize counters
150        lk = lowOff;
151        hk = highOff;
152        ik = outOff;
153        
154        //Handle tail boundary effect. Use symmetric extension
155        if(outLen>1) {
156            outSig[ik] = lowSig[lk]/KL - 2*DELTA*highSig[hk]/KH;
157        }
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 - 
169                DELTA*(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 - 
176                2*DELTA*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 - 
190                GAMMA*(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*outSig[ik-outStep];
196        }       
197
198        // Generate even samples (inverse low-pass filter)
199        
200        //Initialize counters
201        ik = outOff;
202 
203        //Handle tail boundary effect
204        //If access the overlap then perform the lifting step.
205        if(outLen>1) {
206            outSig[ik] -= 2*BETA*outSig[ik+outStep];
207        }
208        ik += iStep;
209 
210        //Apply lifting step to each "inner" sample
211        for(i=2; i<outLen-1; i+=2, ik+=iStep) {
212            outSig[ik] -= BETA*(outSig[ik-outStep] + outSig[ik+outStep]);
213        }
214        
215        //Handle head boundary effect if input signal has odd length
216        if(outLen%2 == 1 && outLen>2) {
217            outSig[ik] -= 2*BETA*outSig[ik-outStep];
218        }
219
220        // Generate odd samples (inverse high pass-filter)
221         
222        //Initialize counters
223        ik = outOff + outStep;
224
225        //Apply first lifting step to each "inner" sample
226        for(i=1; i<outLen-1; i+=2, ik+=iStep) {           
227            outSig[ik] -= ALPHA*(outSig[ik-outStep] + outSig[ik+outStep]);
228        }
229
230        //Handle head boundary effect if input signal has even length
231        if(outLen%2 == 0) {
232            outSig[ik] -= 2*ALPHA*outSig[ik-outStep];
233        }
234    }
235    
236    /**
237     * An implementation of the synthetize_hpf() method that works on int
238     * data, for the inverse 9x7 wavelet transform using the lifting
239     * scheme. See the general description of the synthetize_hpf() method in
240     * the SynWTFilter class for more details.
241     *
242     * <P>The low-pass and high-pass subbands are normalized by respectively
243     * a factor of 1/KL and a factor of 1/KH   
244     *
245     * <P>The coefficients of the first lifting step are [-DELTA 1 -DELTA]. 
246     *
247     * <P>The coefficients of the second lifting step are [-GAMMA 1 -GAMMA].
248     * 
249     * <P>The coefficients of the third lifting step are [-BETA 1 -BETA]. 
250     *
251     * <P>The coefficients of the fourth lifting step are [-ALPHA 1 -ALPHA].
252     *
253     * @param lowSig This is the array that contains the low-pass
254     * input signal.
255     *
256     * @param lowOff This is the index in lowSig of the first sample to
257     * filter.
258     *
259     * @param lowLen This is the number of samples in the low-pass input
260     * signal to filter.
261     *
262     * @param lowStep This is the step, or interleave factor, of the low-pass
263     * input signal samples in the lowSig array.
264     *
265     * @param highSig This is the array that contains the high-pass input
266     * signal.
267     *
268     * @param highOff This is the index in highSig of the first sample to
269     * filter.
270     *
271     * @param highLen This is the number of samples in the high-pass input
272     * signal to filter.
273     *
274     * @param highStep This is the step, or interleave factor, of the
275     * high-pass input signal samples in the highSig array.
276     *
277     * @param outSig This is the array where the output signal is placed. It
278     * should be long enough to contain the output signal.
279     *
280     * @param outOff This is the index in outSig of the element where to put
281     * the first output sample.
282     *
283     * @param outStep This is the step, or interleave factor, of the output
284     * samples in the outSig array.
285     *
286     * @see SynWTFilter#synthetize_hpf
287     * */
288    public
289        void synthetize_hpf(float[] lowSig,int lowOff,int lowLen,int lowStep,
290                            float[] highSig,int highOff,int highLen,
291                            int highStep,float[] outSig,int outOff,
292                            int outStep) {
293                        
294        int i;
295        int outLen = lowLen + highLen; //Length of the output signal
296        int iStep = 2*outStep; //Upsampling in outSig
297        int ik; //Indexing outSig
298        int lk; //Indexing lowSig
299        int hk; //Indexing highSig
300        
301        // Initialize counters
302        lk = lowOff;
303        hk = highOff;
304        
305        if(outLen!=1) {
306            int outLen2 = outLen>>1;
307            // "Inverse normalize" each sample
308            for(i=0; i<outLen2; i++) {
309                lowSig[lk] /= KL;
310                highSig[hk] /= KH;
311                lk += lowStep;  
312                hk += highStep;
313            } 
314            // "Inverse normalise" last high pass coefficient
315            if(outLen%2==1) {
316                highSig[hk] /= KH;
317            }
318        } else {
319            // Normalize for Nyquist gain
320            highSig[highOff] /= 2;
321        }
322        
323        // Generate intermediate low frequency subband
324        
325        //Initialize counters
326        lk = lowOff;
327        hk = highOff;
328        ik = outOff + outStep;
329        
330        //Apply lifting step to each "inner" sample
331        for(i=1; i<outLen-1; i+=2 ) {
332            outSig[ik] = lowSig[lk] - 
333                DELTA*(highSig[hk] + highSig[hk+highStep]);
334            ik += iStep;
335            lk += lowStep;
336            hk += highStep;
337        }
338        
339        if(outLen%2==0 && outLen>1) {
340            //Use symmetric extension
341            outSig[ik] = lowSig[lk] - 2*DELTA*highSig[hk];
342        }
343        
344        // Generate intermediate high frequency subband
345         
346        //Initialize counters
347        hk = highOff;
348        ik = outOff;
349        
350        if(outLen>1) {
351            outSig[ik] = highSig[hk] - 2*GAMMA*outSig[ik+outStep];
352        } else {
353            outSig[ik] = highSig[hk];
354        }
355            
356        ik += iStep;
357        hk += highStep;
358            
359        //Apply lifting step to each "inner" sample
360        for(i=2; i<outLen-1; i+=2 ) {
361            outSig[ik] = highSig[hk] - 
362                GAMMA*(outSig[ik-outStep] + outSig[ik+outStep]);
363            ik += iStep;
364            hk += highStep;
365        }
366
367        //Handle head boundary effect if output signal has even length
368        if(outLen%2==1 && outLen>1) {
369            //Use symmetric extension
370            outSig[ik] = highSig[hk] - 2*GAMMA*outSig[ik-outStep];
371        }        
372
373        // Generate even samples (inverse low-pass filter)
374
375        //Initialize counters
376        ik = outOff + outStep;
377    
378        //Apply lifting step to each "inner" sample
379        for(i=1; i<outLen-1; i+=2 ) {
380            outSig[ik] -= BETA*(outSig[ik-outStep] + outSig[ik+outStep]);
381            ik += iStep;
382        }
383        
384        if(outLen%2==0 && outLen>1) { 
385            // symmetric extension.
386            outSig[ik] -= 2*BETA*outSig[ik-outStep];
387        }
388        
389        // Generate odd samples (inverse high pass-filter)
390         
391        //Initialize counters
392        ik = outOff;
393
394        if(outLen>1) {
395            // symmetric extension.
396            outSig[ik] -= 2*ALPHA*outSig[ik+outStep];
397        }
398        ik += iStep;
399        
400        //Apply first lifting step to each "inner" sample
401        for(i=2; i<outLen-1 ; i+=2) { 
402            outSig[ik] -= ALPHA*(outSig[ik-outStep] + outSig[ik+outStep]);
403            ik += iStep;
404        }
405        
406        //Handle head boundary effect if input signal has even length
407        if((outLen%2==1) && (outLen>1)) {
408            //Use symmetric extension 
409            outSig[ik] -= 2*ALPHA*outSig[ik-outStep];
410        }
411    }
412    
413    /**
414     * Returns the negative support of the low-pass analysis filter. That is
415     * the number of taps of the filter in the negative direction.
416     *
417     * @return 2
418     * */
419    public int getAnLowNegSupport() {
420        return 4;
421    }
422
423    /**
424     * Returns the positive support of the low-pass analysis filter. That is
425     * the number of taps of the filter in the negative direction.
426     *
427     * @return The number of taps of the low-pass analysis filter in the
428     * positive direction
429     * */
430    public int getAnLowPosSupport() {
431        return 4;
432    }
433
434    /**
435     * Returns the negative support of the high-pass analysis filter. That is
436     * the number of taps of the filter in the negative direction.
437     *
438     * @return The number of taps of the high-pass analysis filter in
439     * the negative direction
440     * */
441    public int getAnHighNegSupport() {
442        return 3;
443    }
444
445    /**
446     * Returns the positive support of the high-pass analysis filter. That is
447     * the number of taps of the filter in the negative direction.
448     *
449     * @return The number of taps of the high-pass analysis filter in the
450     * positive direction
451     * */
452    public int getAnHighPosSupport() {
453        return 3;
454    }
455
456    /**
457     * Returns the negative support of the low-pass synthesis filter. That is
458     * the number of taps of the filter in the negative direction.
459     *
460     * <P>A MORE PRECISE DEFINITION IS NEEDED
461     *
462     * @return The number of taps of the low-pass synthesis filter in the
463     * negative direction
464     * */
465    public int getSynLowNegSupport() {
466        return 3;
467    }
468
469    /**
470     * Returns the positive support of the low-pass synthesis filter. That is
471     * the number of taps of the filter in the negative direction.
472     *
473     * <P>A MORE PRECISE DEFINITION IS NEEDED
474     *
475     * @return The number of taps of the low-pass synthesis filter in the
476     * positive direction
477     * */
478    public int getSynLowPosSupport() {
479        return 3;
480    }
481
482    /**
483     * Returns the negative support of the high-pass synthesis filter. That is
484     * the number of taps of the filter in the negative direction.
485     *
486     * <P>A MORE PRECISE DEFINITION IS NEEDED
487     *
488     * @return The number of taps of the high-pass synthesis filter in the
489     * negative direction
490     * */
491    public int getSynHighNegSupport() {
492        return 4;
493    }
494
495    /**
496     * Returns the positive support of the high-pass synthesis filter. That is
497     * the number of taps of the filter in the negative direction.
498     *
499     * <P>A MORE PRECISE DEFINITION IS NEEDED
500     *
501     * @return The number of taps of the high-pass synthesis filter in the
502     * positive direction
503     * */
504    public int getSynHighPosSupport() {
505        return 4;
506    }
507
508    /**
509     * Returns the implementation type of this filter, as defined in this
510     * class, such as WT_FILTER_INT_LIFT, WT_FILTER_FLOAT_LIFT,
511     * WT_FILTER_FLOAT_CONVOL.
512     *
513     * @return WT_FILTER_INT_LIFT.
514     * */
515    public int getImplType() {
516        return WT_FILTER_FLOAT_LIFT;
517    }
518
519    /**
520     * Returns the reversibility of the filter. A filter is considered
521     * reversible if it is suitable for lossless coding.
522     *
523     * @return true since the 9x7 is reversible, provided the appropriate
524     * rounding is performed.
525     * */
526    public boolean isReversible() {
527        return false; 
528    }
529    
530    /**
531     * Returns true if the wavelet filter computes or uses the
532     * same "inner" subband coefficient as the full frame wavelet transform,
533     * and false otherwise. In particular, for block based transforms with 
534     * reduced overlap, this method should return false. The term "inner"
535     * indicates that this applies only with respect to the coefficient that 
536     * are not affected by image boundaries processings such as symmetric
537     * extension, since there is not reference method for this.
538     *
539     * <P>The result depends on the length of the allowed overlap when
540     * compared to the overlap required by the wavelet filter. It also
541     * depends on how overlap processing is implemented in the wavelet
542     * filter.
543     *
544     * @param tailOvrlp This is the number of samples in the input
545     * signal before the first sample to filter that can be used for
546     * overlap.
547     *
548     * @param headOvrlp This is the number of samples in the input
549     * signal after the last sample to filter that can be used for
550     * overlap.
551     *
552     * @param inLen This is the lenght of the input signal to filter.The
553     * required number of samples in the input signal after the last sample
554     * depends on the length of the input signal.
555     *
556     * @return true if both overlaps are greater than 2, and correct 
557     * processing is applied in the analyze() method.
558     *
559     *
560     *
561     */
562    public boolean isSameAsFullWT(int tailOvrlp, int headOvrlp, int inLen) {
563        
564        //If the input signal has even length.
565        if(inLen % 2 == 0) {
566            if(tailOvrlp >= 2 && headOvrlp >= 1) return true;
567            else return false;
568        }
569        //Else if the input signal has odd length.
570        else {
571            if(tailOvrlp >= 2 && headOvrlp >= 2) return true;
572            else return false;
573        }
574    }
575
576    /** 
577     * Returns a string of information about the synthesis wavelet filter
578     *
579     * @return wavelet filter type.
580     *
581     *
582     */
583    public String toString(){
584        return "w9x7 (lifting)";
585    }
586}