001/*
002 * $RCSfile: Dequantizer.java,v $
003 * $Revision: 1.1 $
004 * $Date: 2005/02/11 05:02:18 $
005 * $State: Exp $
006 *
007 * Class:                   Dequantizer
008 *
009 * Description:             The abstract class for all dequantizers.
010 *
011 *
012 *
013 * COPYRIGHT:
014 *
015 * This software module was originally developed by Raphaël Grosbois and
016 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
017 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
018 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
019 * Centre France S.A) in the course of development of the JPEG2000
020 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
021 * software module is an implementation of a part of the JPEG 2000
022 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
023 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
024 * Partners) agree not to assert against ISO/IEC and users of the JPEG
025 * 2000 Standard (Users) any of their rights under the copyright, not
026 * including other intellectual property rights, for this software module
027 * with respect to the usage by ISO/IEC and Users of this software module
028 * or modifications thereof for use in hardware or software products
029 * claiming conformance to the JPEG 2000 Standard. Those intending to use
030 * this software module in hardware or software products are advised that
031 * their use may infringe existing patents. The original developers of
032 * this software module, JJ2000 Partners and ISO/IEC assume no liability
033 * for use of this software module or modifications thereof. No license
034 * or right to this software module is granted for non JPEG 2000 Standard
035 * conforming products. JJ2000 Partners have full right to use this
036 * software module for his/her own purpose, assign or donate this
037 * software module to any third party and to inhibit third parties from
038 * using this software module for non JPEG 2000 Standard conforming
039 * products. This copyright notice must be included in all copies or
040 * derivative works of this software module.
041 *
042 * Copyright (c) 1999/2000 JJ2000 Partners.
043 */
044package jj2000.j2k.quantization.dequantizer;
045import jj2000.j2k.image.invcomptransf.*;
046import jj2000.j2k.wavelet.synthesis.*;
047import jj2000.j2k.entropy.decoder.*;
048import jj2000.j2k.codestream.*;
049import jj2000.j2k.entropy.*;
050import jj2000.j2k.decoder.*;
051import jj2000.j2k.wavelet.*;
052import jj2000.j2k.image.*;
053import jj2000.j2k.io.*;
054import jj2000.j2k.*;
055
056import java.io.*;
057
058/**
059 * This is the abstract class from which all dequantizers must inherit. This
060 * class has the concept of a current tile and all operations are performed on
061 * the current tile.
062 *
063 * <p>This class provides default implemenations for most of the methods
064 * (wherever it makes sense), under the assumption that the image and
065 * component dimensions, and the tiles, are not modifed by the dequantizer. If
066 * that is not the case for a particular implementation then the methods
067 * should be overriden.</p>
068 *
069 * <p>Sign magnitude representation is used (instead of two's complement) for
070 * the input data. The most significant bit is used for the sign (0 if
071 * positive, 1 if negative). Then the magnitude of the quantized coefficient
072 * is stored in the next most significat bits. The most significant magnitude
073 * bit corresponds to the most significant bit-plane and so on.</p>
074 *
075 * <p>The output data is either in floating-point, or in fixed-point two's
076 * complement. In case of floating-point data the the value returned by
077 * getFixedPoint() must be 0. If the case of fixed-point data the number of
078 * fractional bits must be defined at the constructor of the implementing
079 * class and all operations must be performed accordingly. Each component may
080 * have a different number of fractional bits.</p>
081 * */
082public abstract class Dequantizer extends MultiResImgDataAdapter
083    implements CBlkWTDataSrcDec {
084
085    /** The prefix for dequantizer options: 'Q' */
086    public final static char OPT_PREFIX = 'Q';
087
088    /** The list of parameters that is accepted by the bit stream
089     * readers. They start with 'Q' */
090    private static final String [][] pinfo = null;
091
092    /** The entropy decoder from where to get the quantized data (the
093     * source). */
094    protected CBlkQuantDataSrcDec src;
095
096    /** The "range bits" for each transformed component */
097    protected int rb[] = null;
098
099    /** The "range bits" for each un-transformed component */
100    protected int utrb[] = null;
101
102    /** The inverse component transformation specifications */
103    private CompTransfSpec cts;
104
105    /** Reference to the wavelet filter specifications */
106    private SynWTFilterSpec wfs;
107
108    /**
109     * Initializes the source of compressed data.
110     *
111     * @param src From where to obtain the quantized data.
112     *
113     * @param rb The number of "range bits" for each component (must be the
114     * "range bits" of the un-transformed components. For a definition of
115     * "range bits" see the getNomRangeBits() method.
116     *
117     * @see #getNomRangeBits
118     * */
119    public Dequantizer(CBlkQuantDataSrcDec src,int utrb[],
120                       DecoderSpecs decSpec) {
121        super(src);
122        if (utrb.length != src.getNumComps()) {
123            throw new IllegalArgumentException();
124        }
125        this.src  = src;
126        this.utrb = utrb;
127        this.cts  = decSpec.cts;
128        this.wfs  = decSpec.wfs;
129    }
130
131    /**
132     * Returns the number of bits, referred to as the "range bits",
133     * corresponding to the nominal range of the data in the specified
134     * component.
135     *
136     * <p>The returned value corresponds to the nominal dynamic range of the
137     * reconstructed image data, not of the wavelet coefficients
138     * themselves. This is because different subbands have different gains and
139     * thus different nominal ranges. To have an idea of the nominal range in
140     * each subband the subband analysis gain value from the subband tree
141     * structure, returned by the getSynSubbandTree() method, can be used. See
142     * the Subband class for more details.</p>
143     *
144     * <p>If this number is <i>b</b> then for unsigned data the nominal range
145     * is between 0 and 2^b-1, and for signed data it is between -2^(b-1) and
146     * 2^(b-1)-1.</p>
147     *
148     * @param c The index of the component
149     *
150     * @return The number of bits corresponding to the nominal range of the
151     * data.
152     *
153     * @see Subband
154     * */
155    public int getNomRangeBits(int c) {
156        return rb[c];
157    }
158
159    /**
160     * Returns the subband tree, for the specified tile-component. This method
161     * returns the root element of the subband tree structure, see Subband and
162     * SubbandSyn. The tree comprises all the available resolution levels.
163     *
164     * <P>The number of magnitude bits ('magBits' member variable) for each
165     * subband may have not been not initialized (it depends on the actual
166     * dequantizer and its implementation). However, they are not necessary
167     * for the subsequent steps in the decoder chain.
168     *
169     * @param t The index of the tile, from 0 to T-1.
170     *
171     * @param c The index of the component, from 0 to C-1.
172     *
173     * @return The root of the tree structure.
174     * */
175    public SubbandSyn getSynSubbandTree(int t,int c) {
176        return src.getSynSubbandTree(t,c);
177    }
178
179    /**
180     * Returns the horizontal code-block partition origin. Allowable values
181     * are 0 and 1, nothing else.
182     * */
183    public int getCbULX() {
184        return src.getCbULX();
185    }
186
187    /**
188     * Returns the vertical code-block partition origin. Allowable values are
189     * 0 and 1, nothing else.
190     * */
191    public int getCbULY() {
192        return src.getCbULY();
193    }
194
195    /**
196     * Returns the parameters that are used in this class and
197     * implementing classes. It returns a 2D String array. Each of the
198     * 1D arrays is for a different option, and they have 3
199     * elements. The first element is the option name, the second one
200     * is the synopsis and the third one is a long description of what
201     * the parameter is. The synopsis or description may be 'null', in
202     * which case it is assumed that there is no synopsis or
203     * description of the option, respectively. Null may be returned
204     * if no options are supported.
205     *
206     * @return the options name, their synopsis and their explanation, 
207     * or null if no options are supported.
208     * */
209    public static String[][] getParameterInfo() {
210        return pinfo;
211    }
212
213    /**
214     * Changes the current tile, given the new indexes. An
215     * IllegalArgumentException is thrown if the indexes do not
216     * correspond to a valid tile.
217     *
218     * <P>This default implementation changes the tile in the source
219     * and re-initializes properly component transformation variables..
220     *
221     * @param x The horizontal index of the tile.
222     *
223     * @param y The vertical index of the new tile.
224     * */
225    public void setTile(int x, int y) {
226        src.setTile(x,y);
227        tIdx = getTileIdx(); // index of the current tile
228
229        // initializations
230        int cttype = 0;
231        if( ((Integer)cts.getTileDef(tIdx)).intValue()==InvCompTransf.NONE )
232            cttype = InvCompTransf.NONE;
233        else {
234            int nc = src.getNumComps() > 3 ? 3 : src.getNumComps(); 
235            int rev = 0;
236            for(int c=0; c<nc; c++)
237                rev += (wfs.isReversible(tIdx,c)?1:0);
238            if(rev==3){
239                // All WT are reversible
240                cttype = InvCompTransf.INV_RCT;
241            }
242            else if(rev==0){
243                // All WT irreversible
244                cttype = InvCompTransf.INV_ICT;
245            }
246            else{
247                // Error
248                throw new IllegalArgumentException("Wavelet transformation "+
249                                                   "and "+
250                                                   "component transformation"+
251                                                   " not coherent in tile"+
252                                                   tIdx);
253            }
254        }
255
256        switch(cttype){
257        case InvCompTransf.NONE:
258            rb = utrb;
259            break;
260        case InvCompTransf.INV_RCT:
261            rb = InvCompTransf.
262                calcMixedBitDepths(utrb,InvCompTransf.INV_RCT,null);
263            break;
264        case InvCompTransf.INV_ICT:
265            rb = InvCompTransf.
266                calcMixedBitDepths(utrb,InvCompTransf.INV_ICT,null);
267            break;
268        default:
269            throw new IllegalArgumentException("Non JPEG 2000 part I "+
270                                               "component"+
271                                               " transformation for tile: "+
272                                               tIdx);
273        }
274    }
275
276    /**
277     * Advances to the next tile, in standard scan-line order (by rows then
278     * columns). An NoNextElementException is thrown if the current tile is
279     * the last one (i.e. there is no next tile).
280     *
281     * <P>This default implementation just advances to the next tile in the
282     * source and re-initializes properly component transformation variables.
283     * */
284    public void nextTile() {
285        src.nextTile();
286        tIdx = getTileIdx(); // index of the current tile
287
288        // initializations
289        int cttype = ((Integer)cts.getTileDef(tIdx)).intValue();
290        switch(cttype){
291        case InvCompTransf.NONE:
292            rb = utrb;
293            break;
294        case InvCompTransf.INV_RCT:
295            rb = InvCompTransf.
296                calcMixedBitDepths(utrb,InvCompTransf.INV_RCT,null);
297            break;
298        case InvCompTransf.INV_ICT:
299            rb = InvCompTransf.
300                calcMixedBitDepths(utrb,InvCompTransf.INV_ICT,null);
301            break;
302        default:
303            throw new IllegalArgumentException("Non JPEG 2000 part I "+
304                                               "component"+
305                                               " transformation for tile: "+
306                                               tIdx);
307        }
308    }
309
310}