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