001/* 002 * $RCSfile: QuantTypeSpec.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:18 $ 005 * $State: Exp $ 006 * 007 * Class: QuantTypeSpec 008 * 009 * Description: Quantization type specifications 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; 045 046import jj2000.j2k.util.*; 047import jj2000.j2k.*; 048 049import java.util.*; 050 051import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; 052 053/** 054 * This class extends ModuleSpec class in order to hold specifications about 055 * the quantization type to use in each tile-component. Supported quantization 056 * type are:<br> 057 * 058 * <ul> 059 * <li> Reversible (no quantization)</li> 060 * <li> Derived (the quantization step size is derived from the one of the 061 * LL-subband)</li> 062 * <li> Expounded (the quantization step size of each subband is signalled in 063 * the codestream headers) </li> 064 * </ul> 065 * 066 * @see ModuleSpec 067 * */ 068public class QuantTypeSpec extends ModuleSpec{ 069 070 /** 071 * Constructs an empty 'QuantTypeSpec' with specified number of tile and 072 * components. This constructor is called by the decoder. 073 * 074 * @param nt Number of tiles 075 * 076 * @param nc Number of components 077 * 078 * @param type the type of the specification module i.e. tile specific, 079 * component specific or both. 080 * */ 081 public QuantTypeSpec(int nt, int nc, byte type){ 082 super(nt, nc, type); 083 } 084 085 086 /** 087 * Constructs a new 'QuantTypeSpec' for the specified number of components 088 * and tiles and the arguments of "-Qtype" option. This constructor is 089 * called by the encoder. 090 * 091 * @param nt The number of tiles 092 * 093 * @param nc The number of components 094 * 095 * @param type the type of the specification module i.e. tile specific, 096 * component specific or both. 097 * */ 098 public QuantTypeSpec(int nt, int nc, byte type, J2KImageWriteParamJava wp, String values){ 099 super(nt, nc, type); 100 101 if(values==null){ 102 if(wp.getLossless()) 103 setDefault("reversible"); 104 else 105 setDefault("expounded"); 106 return; 107 } 108 109 // XXX: need to define it 110 specified = values; 111 String param = values; 112 // Parse argument 113 StringTokenizer stk = new StringTokenizer(param); 114 String word; // current word 115 byte curSpecValType = SPEC_DEF; // Specification type of the 116 // current parameter 117 boolean[] tileSpec = null; // Tiles concerned by the specification 118 boolean[] compSpec = null; // Components concerned by the specification 119 120 while(stk.hasMoreTokens()){ 121 word = stk.nextToken().toLowerCase(); 122 123 switch(word.charAt(0)){ 124 case 't': // Tiles specification 125 tileSpec = parseIdx(word,nTiles); 126 if(curSpecValType==SPEC_COMP_DEF){ 127 curSpecValType = SPEC_TILE_COMP; 128 } 129 else{ 130 curSpecValType = SPEC_TILE_DEF; 131 } 132 break; 133 case 'c': // Components specification 134 compSpec = parseIdx(word,nComp); 135 if(curSpecValType==SPEC_TILE_DEF){ 136 curSpecValType = SPEC_TILE_COMP; 137 } 138 else 139 curSpecValType = SPEC_COMP_DEF; 140 break; 141 case 'r': // reversible specification 142 case 'd': // derived quantization step size specification 143 case 'e': // expounded quantization step size specification 144 if(!word.equalsIgnoreCase("reversible") && 145 !word.equalsIgnoreCase("derived") && 146 !word.equalsIgnoreCase("expounded")) 147 throw new IllegalArgumentException("Unknown parameter "+ 148 "for "+ 149 "'-Qtype' option: "+ 150 word); 151 152 if(wp.getLossless() && 153 ( word.equalsIgnoreCase("derived") || 154 word.equalsIgnoreCase("expounded") ) ) 155 throw new IllegalArgumentException("Cannot use non "+ 156 "reversible "+ 157 "quantization with "+ 158 "'-lossless' option"); 159 160 if(curSpecValType==SPEC_DEF){ 161 setDefault(word); 162 } 163 else if(curSpecValType==SPEC_TILE_DEF){ 164 for(int i=tileSpec.length-1; i>=0; i--) 165 if(tileSpec[i]){ 166 setTileDef(i,word); 167 } 168 } 169 else if(curSpecValType==SPEC_COMP_DEF){ 170 for(int i=compSpec.length-1; i>=0; i--) 171 if(compSpec[i]){ 172 setCompDef(i,word); 173 } 174 } 175 else{ 176 for(int i=tileSpec.length-1; i>=0; i--){ 177 for(int j=compSpec.length-1; j>=0 ; j--){ 178 if(tileSpec[i] && compSpec[j]){ 179 setTileCompVal(i,j,word); 180 } 181 } 182 } 183 } 184 185 // Re-initialize 186 curSpecValType = SPEC_DEF; 187 tileSpec = null; 188 compSpec = null; 189 break; 190 191 default: 192 throw new IllegalArgumentException("Unknown parameter for "+ 193 "'-Qtype' option: "+word); 194 } 195 } 196 197 // Check that default value has been specified 198 if(getDefault()==null){ 199 int ndefspec = 0; 200 for(int t=nt-1; t>=0; t--){ 201 for(int c=nc-1; c>=0 ; c--){ 202 if(specValType[t][c] == SPEC_DEF){ 203 ndefspec++; 204 } 205 } 206 } 207 208 // If some tile-component have received no specification, it takes 209 // the default value 210 if(ndefspec!=0){ 211 if(wp.getLossless()) 212 setDefault("reversible"); 213 else 214 setDefault("expounded"); 215 } 216 else{ 217 // All tile-component have been specified, takes the first 218 // tile-component value as default. 219 setDefault(getTileCompVal(0,0)); 220 switch(specValType[0][0]){ 221 case SPEC_TILE_DEF: 222 for(int c=nc-1; c>=0; c--){ 223 if(specValType[0][c]==SPEC_TILE_DEF) 224 specValType[0][c] = SPEC_DEF; 225 } 226 tileDef[0] = null; 227 break; 228 case SPEC_COMP_DEF: 229 for(int t=nt-1; t>=0; t--){ 230 if(specValType[t][0]==SPEC_COMP_DEF) 231 specValType[t][0] = SPEC_DEF; 232 } 233 compDef[0] = null; 234 break; 235 case SPEC_TILE_COMP: 236 specValType[0][0] = SPEC_DEF; 237 tileCompVal.put("t0c0",null); 238 break; 239 } 240 } 241 } 242 } 243 244 /** 245 * Returns true if given tile-component uses derived quantization step 246 * size. 247 * 248 * @param t Tile index 249 * 250 * @param c Component index 251 * 252 * @return True if derived quantization step size 253 * */ 254 public boolean isDerived(int t,int c){ 255 if( ((String)getTileCompVal(t,c)).equals("derived") ) 256 return true; 257 else 258 return false; 259 } 260 261 /** 262 * Check the reversibility of the given tile-component. 263 * 264 * @param t The index of the tile 265 * 266 * @param c The index of the component 267 * 268 * @return Whether or not the tile-component is reversible 269 * */ 270 public boolean isReversible(int t,int c){ 271 if( ((String)getTileCompVal(t,c)).equals("reversible") ) 272 return true; 273 else 274 return false; 275 } 276 277 /** 278 * Check the reversibility of the whole image. 279 * 280 * @return Whether or not the whole image is reversible 281 * */ 282 public boolean isFullyReversible(){ 283 // The whole image is reversible if default specification is 284 // rev and no tile default, component default and 285 // tile-component value has been specificied 286 if( ((String)getDefault()).equals("reversible") ){ 287 for(int t=nTiles-1; t>=0; t--) 288 for(int c=nComp-1; c>=0; c--) 289 if(specValType[t][c]!=SPEC_DEF) 290 return false; 291 return true; 292 } 293 294 return false; 295 } 296 297 /** 298 * Check the irreversibility of the whole image. 299 * 300 * @return Whether or not the whole image is reversible 301 * */ 302 public boolean isFullyNonReversible(){ 303 // The whole image is irreversible no tile-component is reversible 304 for(int t=nTiles-1; t>=0; t--) 305 for(int c=nComp-1; c>=0; c--) 306 if( ((String)getSpec(t,c)).equals("reversible") ) 307 return false; 308 return true; 309 } 310 311}