001/* 002 * $RCSfile: StdDequantizer.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:19 $ 005 * $State: Exp $ 006 * 007 * Class: StdDequantizer 008 * 009 * Description: Scalar deadzone dequantizer that returns integers 010 * or floats. 011 * This is a merger of the ScalarDZDeqInt and 012 * ScalarDZDeqFloat classes by Joel Askelof and Diego 013 * Santa Cruz. 014 * 015 * 016 * 017 * COPYRIGHT: 018 * 019 * This software module was originally developed by Raphaël Grosbois and 020 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel 021 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David 022 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research 023 * Centre France S.A) in the course of development of the JPEG2000 024 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This 025 * software module is an implementation of a part of the JPEG 2000 026 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio 027 * Systems AB and Canon Research Centre France S.A (collectively JJ2000 028 * Partners) agree not to assert against ISO/IEC and users of the JPEG 029 * 2000 Standard (Users) any of their rights under the copyright, not 030 * including other intellectual property rights, for this software module 031 * with respect to the usage by ISO/IEC and Users of this software module 032 * or modifications thereof for use in hardware or software products 033 * claiming conformance to the JPEG 2000 Standard. Those intending to use 034 * this software module in hardware or software products are advised that 035 * their use may infringe existing patents. The original developers of 036 * this software module, JJ2000 Partners and ISO/IEC assume no liability 037 * for use of this software module or modifications thereof. No license 038 * or right to this software module is granted for non JPEG 2000 Standard 039 * conforming products. JJ2000 Partners have full right to use this 040 * software module for his/her own purpose, assign or donate this 041 * software module to any third party and to inhibit third parties from 042 * using this software module for non JPEG 2000 Standard conforming 043 * products. This copyright notice must be included in all copies or 044 * derivative works of this software module. 045 * 046 * Copyright (c) 1999/2000 JJ2000 Partners. 047 * */ 048package jj2000.j2k.quantization.dequantizer; 049 050import jj2000.j2k.decoder.DecoderSpecs; 051import jj2000.j2k.image.DataBlk; 052import jj2000.j2k.image.DataBlkFloat; 053import jj2000.j2k.image.DataBlkInt; 054import jj2000.j2k.quantization.GuardBitsSpec; 055import jj2000.j2k.quantization.QuantStepSizeSpec; 056import jj2000.j2k.quantization.QuantTypeSpec; 057import jj2000.j2k.wavelet.synthesis.SubbandSyn; 058 059/** 060 * This class implements a scalar dequantizer with deadzone. The output can be 061 * either integer ('int') or floating-point ('float') data. The dequantization 062 * step sizes and other parameters are taken from a StdDequantizerParams 063 * class, which inherits from DequantizerParams. 064 * 065 * <P>Sign magnitude representation is used (instead of two's complement) for 066 * the input data. The most significant bit is used for the sign (0 if 067 * positive, 1 if negative). Then the magnitude of the quantized coefficient 068 * is stored in the next most significat bits. The most significant magnitude 069 * bit corresponds to the most significant bit-plane and so on. 070 * 071 * <P>When reversible quantization is used, this class only converts between 072 * the sign-magnitude representation and the integer (or eventually 073 * fixed-point) output, since there is no true quantization. 074 * 075 * <P>The output data is fixed-point two's complement for 'int' output and 076 * floating-point for 'float' output. The type of output and the number number 077 * of fractional bits for 'int' output are defined at the constructor. Each 078 * component may have a different number of fractional bits. 079 * 080 * <P>The reconstruction levels used by the dequantizer are exactly what is 081 * received from the entropy decoder. It is assumed that the entropy decoder 082 * always returns codewords that are midways in the decoded intervals. In this 083 * way the dequantized values will always lie midways in the quantization 084 * intervals. 085 * */ 086public class StdDequantizer extends Dequantizer { 087 088 /** The quantizer type spec */ 089 private QuantTypeSpec qts; 090 091 /** The quantizer step sizes spec */ 092 private QuantStepSizeSpec qsss; 093 094 /** The number of guard bits spec */ 095 private GuardBitsSpec gbs; 096 097 /** The decoding parameters of the dequantizer */ 098 private StdDequantizerParams params; 099 100 /** The 'DataBlkInt' object used to request data, used when output data is 101 * not int */ 102 private DataBlkInt inblk; 103 104 /** Type of the current output data */ 105 private int outdtype; 106 107 /** 108 * Initializes the source of compressed data. And sets the number of range 109 * bits and fraction bits and receives the parameters for the dequantizer. 110 * 111 * @param src From where to obtain the quantized data. 112 * 113 * @param rb The number of "range bits" (bitdepth) for each component 114 * (must be the "range bits" of the un-transformed components). For a 115 * definition of "range bits" see the getNomRangeBits() method. 116 * 117 * @param qts The quantizer type spec 118 * 119 * @param qsss The dequantizer step sizes spec 120 * 121 * @see Dequantizer#getNomRangeBits 122 * 123 * @exception IllegalArgumentException Thrown if 'outdt' is neither 124 * TYPE_FLOAT nor TYPE_INT, or if 'param' specify reversible quantization 125 * and 'outdt' is not TYPE_INT or 'fp' has non-zero values, or if 'outdt' 126 * is TYPE_FLOAT and 'fp' has non-zero values. 127 * */ 128 public StdDequantizer(CBlkQuantDataSrcDec src,int[] utrb, 129 DecoderSpecs decSpec){ 130 super(src,utrb,decSpec); 131 132 if(utrb.length != src.getNumComps()){ 133 throw new IllegalArgumentException("Invalid rb argument"); 134 } 135 this.qsss = decSpec.qsss; 136 this.qts = decSpec.qts; 137 this.gbs = decSpec.gbs; 138 } 139 140 /** 141 * Returns the position of the fixed point in the output data for the 142 * specified component. This is the position of the least significant 143 * integral (i.e. non-fractional) bit, which is equivalent to the number 144 * of fractional bits. For instance, for fixed-point values with 2 145 * fractional bits, 2 is returned. For floating-point data this value does 146 * not apply and 0 should be returned. Position 0 is the position of the 147 * least significant bit in the data. If the output data is 'float' then 0 148 * is always returned. 149 * 150 * <P><u>Note:</u> Fractional bits are no more supported by JJ2000. 151 * 152 * @param c The index of the component. 153 * 154 * @return The position of the fixed-point, which is the same as 155 * the number of fractional bits. For floating-point data 0 is 156 * returned. 157 * */ 158 public int getFixedPoint(int c){ 159 return 0; 160 } 161 162 /** 163 * Returns the specified code-block in the current tile for the specified 164 * component, as a copy (see below). 165 * 166 * <P>The returned code-block may be progressive, which is indicated by 167 * the 'progressive' variable of the returned 'DataBlk' object. If a 168 * code-block is progressive it means that in a later request to this 169 * method for the same code-block it is possible to retrieve data which is 170 * a better approximation, since meanwhile more data to decode for the 171 * code-block could have been received. If the code-block is not 172 * progressive then later calls to this method for the same code-block 173 * will return the exact same data values. 174 * 175 * <P>The data returned by this method is always a copy of the internal 176 * data of this object, if any, and it can be modified "in place" without 177 * any problems after being returned. The 'offset' of the returned data is 178 * 0, and the 'scanw' is the same as the code-block width. See the 179 * 'DataBlk' class. 180 * 181 * @param c The component for which to return the next code-block. 182 * 183 * @param m The vertical index of the code-block to return, in the 184 * specified subband. 185 * 186 * @param n The horizontal index of the code-block to return, in the 187 * specified subband. 188 * 189 * @param sb The subband in which the code-block to return is. 190 * 191 * @param cblk If non-null this object will be used to return the new 192 * code-block. If null a new one will be allocated and returned. If the 193 * "data" array of the object is non-null it will be reused, if possible, 194 * to return the data. 195 * 196 * @return The next code-block in the current tile for component 'n', or 197 * null if all code-blocks for the current tile have been returned. 198 * 199 * @see DataBlk 200 * */ 201 public final DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, 202 DataBlk cblk) { 203 return getInternCodeBlock(c,m,n,sb,cblk); 204 } 205 206 /** 207 * Returns the specified code-block in the current tile for the specified 208 * component (as a reference or copy). 209 * 210 * <P>The returned code-block may be progressive, which is indicated by 211 * the 'progressive' variable of the returned 'DataBlk' 212 * object. If a code-block is progressive it means that in a later request 213 * to this method for the same code-block it is possible to retrieve data 214 * which is a better approximation, since meanwhile more data to decode 215 * for the code-block could have been received. If the code-block is not 216 * progressive then later calls to this method for the same code-block 217 * will return the exact same data values. 218 * 219 * <P>The data returned by this method can be the data in the internal 220 * buffer of this object, if any, and thus can not be modified by the 221 * caller. The 'offset' and 'scanw' of the returned data can be 222 * arbitrary. See the 'DataBlk' class. 223 * 224 * @param c The component for which to return the next code-block. 225 * 226 * @param m The vertical index of the code-block to return, in the 227 * specified subband. 228 * 229 * @param n The horizontal index of the code-block to return, in the 230 * specified subband. 231 * 232 * @param sb The subband in which the code-block to return is. 233 * 234 * @param cblk If non-null this object will be used to return the new 235 * code-block. If null a new one will be allocated and returned. If the 236 * "data" array of the object is non-null it will be reused, if possible, 237 * to return the data. 238 * 239 * @return The next code-block in the current tile for component 'n', or 240 * null if all code-blocks for the current tile have been returned. 241 * 242 * @see DataBlk 243 * */ 244 public final 245 DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, 246 DataBlk cblk) { 247 // This method is declared final since getNextCodeBlock() relies on 248 // the actual implementation of this method. 249 int j,jmin,k; 250 int temp; 251 float step; 252 int shiftBits; 253 int magBits; 254 int[] outiarr,inarr; 255 float[] outfarr; 256 int w,h; 257 boolean reversible = qts.isReversible(tIdx,c); 258 boolean derived = qts.isDerived(tIdx,c); 259 StdDequantizerParams 260 params = (StdDequantizerParams)qsss.getTileCompVal(tIdx,c); 261 int G = ((Integer)gbs.getTileCompVal(tIdx,c)).intValue(); 262 263 outdtype = cblk.getDataType(); 264 265 if (reversible && outdtype!=DataBlk.TYPE_INT) { 266 throw new IllegalArgumentException("Reversible quantizations "+ 267 "must use int data"); 268 } 269 270 // To get compiler happy 271 outiarr = null; 272 outfarr = null; 273 inarr = null; 274 275 // Get source data and initialize output DataBlk object. 276 switch (outdtype) { 277 case DataBlk.TYPE_INT: 278 // With int data we can use the same DataBlk object to get the 279 // data from the source and return the dequantized data, and we 280 // can also work "in place" (i.e. same buffer). 281 cblk = src.getCodeBlock(c,m,n,sb,cblk); 282 // Input and output arrays are the same 283 outiarr = (int[]) cblk.getData(); 284 break; 285 case DataBlk.TYPE_FLOAT: 286 // With float data we must use a different DataBlk objects to get 287 // the data from the source and to return the dequantized data. 288 inblk = (DataBlkInt) src.getInternCodeBlock(c,m,n,sb,inblk); 289 inarr = inblk.getDataInt(); 290 if (cblk == null) { 291 cblk = new DataBlkFloat(); 292 } 293 // Copy the attributes of the CodeBlock object 294 cblk.ulx = inblk.ulx; 295 cblk.uly = inblk.uly; 296 cblk.w = inblk.w; 297 cblk.h = inblk.h; 298 cblk.offset = 0; 299 cblk.scanw = cblk.w; 300 cblk.progressive = inblk.progressive; 301 // Get output data array and check its size 302 outfarr = (float[]) cblk.getData(); 303 if (outfarr == null || outfarr.length < cblk.w*cblk.h) { 304 outfarr = new float[cblk.w*cblk.h]; 305 cblk.setData(outfarr); 306 } 307 break; 308 } 309 310 magBits = sb.magbits; 311 312 // Calculate quantization step and number of magnitude bits 313 // depending on reversibility and derivedness and perform 314 // inverse quantization 315 if(reversible){ 316 shiftBits=31-magBits; 317 // For int data Inverse quantization happens "in-place". The input 318 // array has an offset of 0 and scan width equal to the code-block 319 // width. 320 for (j=outiarr.length-1; j>=0; j--) { 321 temp = outiarr[j]; // input array is same as output one 322 outiarr[j]=(temp >= 0) ? (temp>>shiftBits) : 323 -((temp&0x7FFFFFFF)>>shiftBits); 324 } 325 } 326 else{// Not reversible 327 if(derived){ 328 // Max resolution level 329 int mrl = src.getSynSubbandTree(getTileIdx(),c).resLvl; 330 step=params.nStep[0][0]* 331 (1L<<(rb[c]+sb.anGainExp+mrl-sb.level)); 332 } 333 else{ 334 step=params.nStep[sb.resLvl][sb.sbandIdx]* 335 (1L<<(rb[c]+sb.anGainExp)); 336 } 337 shiftBits=31-magBits; 338 339 // Adjust step to the number of shiftBits 340 step /= (1<<shiftBits); 341 342 switch (outdtype) { 343 case DataBlk.TYPE_INT: 344 // For int data Inverse quantization happens "in-place". The 345 // input array has an offset of 0 and scan width equal to the 346 // code-block width. 347 for (j=outiarr.length-1; j>=0; j--) { 348 temp = outiarr[j]; // input array is same as output one 349 outiarr[j] = (int)(((float)((temp >= 0) ? temp : 350 -(temp&0x7FFFFFFF)))*step); 351 } 352 break; 353 case DataBlk.TYPE_FLOAT: 354 // For float data the inverse quantization can not happen 355 // "in-place". 356 w = cblk.w; 357 h = cblk.h; 358 for (j=w*h-1, k=inblk.offset+(h-1)*inblk.scanw+w-1, 359 jmin = w*(h-1); j>=0; jmin -= w) { 360 for (; j>=jmin; k--, j--) { 361 temp = inarr[k]; 362 outfarr[j] = ((float)((temp >= 0) ? temp : 363 -(temp&0x7FFFFFFF)))*step; 364 } 365 // Jump to beggining of previous line in input 366 k -= inblk.scanw - w; 367 } 368 break; 369 } 370 } 371 // Return the output code-block 372 return cblk; 373 } 374}