001/* 002 * $RCSfile: ForwCompTransfSpec.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:13 $ 005 * $State: Exp $ 006 * 007 * Class: ForwCompTransfSpec 008 * 009 * Description: Component Transformation specification for encoder 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.image.forwcomptransf; 045 046import jj2000.j2k.wavelet.analysis.*; 047import jj2000.j2k.wavelet.*; 048import jj2000.j2k.image.*; 049import jj2000.j2k.util.*; 050import jj2000.j2k.*; 051 052import java.util.*; 053 054import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; 055/** 056 * This class extends CompTransfSpec class in order to hold encoder specific 057 * aspects of CompTransfSpec. 058 * 059 * @see CompTransfSpec 060 * */ 061public class ForwCompTransfSpec extends CompTransfSpec implements FilterTypes { 062 private String defaultValue = null; 063 064 /** 065 * Constructs a new 'ForwCompTransfSpec' for the specified number of 066 * components and tiles and the arguments of <tt>optName</tt> 067 * option. This constructor is called by the encoder. It also 068 * checks that the arguments belongs to the recognized arguments 069 * list. 070 * 071 * <P>This constructor chose the component transformation type 072 * depending on the wavelet filters : RCT with w5x3 filter and ICT 073 * with w9x7 filter. Note: All filters must use the same data 074 * type. 075 * 076 * @param nt The number of tiles 077 * 078 * @param nc The number of components 079 * 080 * @param type the type of the specification module i.e. tile specific, 081 * component specific or both. 082 * 083 * @param wfs The wavelet filter specifications 084 * */ 085 public ForwCompTransfSpec(int nt, int nc, byte type, AnWTFilterSpec wfs, 086 J2KImageWriteParamJava wp, String values){ 087 super(nt,nc,type); 088 089 String param = values; 090 specified = values; 091 if(values==null){ 092 // If less than three component, do not use any component 093 // transformation 094 if(nc<3) { 095 setDefault("none"); 096 return; 097 } 098 // If the compression is lossless, uses RCT 099 else if(wp.getLossless()) { 100 setDefault("rct"); 101 return; 102 } else { 103 AnWTFilter[][] anfilt; 104 int[] filtType = new int[nComp]; 105 for(int c=0; c<3; c++) { 106 anfilt = (AnWTFilter[][])wfs.getCompDef(c); 107 filtType[c] = anfilt[0][0].getFilterType(); 108 } 109 110 // Check that the three first components use the same filters 111 boolean reject = false; 112 for(int c=1; c<3; c++){ 113 if(filtType[c]!=filtType[0]) reject = true; 114 } 115 116 if(reject) { 117 setDefault("none"); 118 } else { 119 anfilt = (AnWTFilter[][])wfs.getCompDef(0); 120 if(anfilt[0][0].getFilterType()==W9X7) { 121 setDefault("ict"); 122 } else { 123 setDefault("rct"); 124 } 125 } 126 } 127 128 // Each tile receives a component transform specification 129 // according the type of wavelet filters that are used by the 130 // three first components 131 for(int t=0; t<nt; t++) { 132 AnWTFilter[][] anfilt; 133 int[] filtType = new int[nComp]; 134 for(int c=0; c<3; c++) { 135 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,c); 136 filtType[c] = anfilt[0][0].getFilterType(); 137 } 138 139 // Check that the three components use the same filters 140 boolean reject = false; 141 for(int c=1; c<nComp;c++){ 142 if(filtType[c]!=filtType[0]) 143 reject = true; 144 } 145 146 if(reject) { 147 setTileDef(t,"none"); 148 } else { 149 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,0); 150 if(anfilt[0][0].getFilterType()==W9X7) { 151 setTileDef(t,"ict"); 152 } else { 153 setTileDef(t,"rct"); 154 } 155 } 156 } 157 return; 158 } 159 160 if (param.equalsIgnoreCase("true")) 161 param = "on"; 162 // Parse argument 163 StringTokenizer stk = new StringTokenizer(param); 164 String word; // current word 165 byte curSpecType = SPEC_DEF; // Specification type of the 166 // current parameter 167 boolean[] tileSpec = null; // Tiles concerned by the 168 // specification 169 Boolean value; 170 171 while(stk.hasMoreTokens()){ 172 word = stk.nextToken(); 173 174 switch(word.charAt(0)){ 175 case 't': // Tiles specification 176 tileSpec = parseIdx(word,nTiles); 177 if(curSpecType==SPEC_COMP_DEF) { 178 curSpecType = SPEC_TILE_COMP; 179 } else { 180 curSpecType = SPEC_TILE_DEF; 181 } 182 break; 183 case 'c': // Components specification 184 throw new IllegalArgumentException("Component specific "+ 185 " parameters"+ 186 " not allowed with "+ 187 "'-Mct' option"); 188 default: 189 if(word.equals("off")) { 190 if(curSpecType==SPEC_DEF) { 191 setDefault("none"); 192 } else if(curSpecType==SPEC_TILE_DEF) { 193 for(int i=tileSpec.length-1; i>=0; i--) 194 if(tileSpec[i]) { 195 setTileDef(i,"none"); 196 } 197 } 198 } else if(word.equals("on")) { 199 if(nc<3) { 200 setDefault("none"); 201 break; 202 } 203 204 if(curSpecType==SPEC_DEF) { // Set arbitrarily the default 205 // value to RCT (later will be found the suitable 206 // component transform for each tile) 207 setDefault("rct"); 208 } else if (curSpecType==SPEC_TILE_DEF) { 209 for(int i=tileSpec.length-1; i>=0; i--) { 210 if(tileSpec[i]) { 211 if(getFilterType(i,wfs)==W5X3) { 212 setTileDef(i,"rct"); 213 } else { 214 setTileDef(i,"ict"); 215 } 216 } 217 } 218 } 219 } else { 220 throw new IllegalArgumentException("Default parameter of "+ 221 "option Mct not"+ 222 " recognized: "+param); 223 } 224 225 // Re-initialize 226 curSpecType = SPEC_DEF; 227 tileSpec = null; 228 break; 229 } 230 } 231 232 // Check that default value has been specified 233 if(getDefault()==null) { 234 // If not, set arbitrarily the default value to 'none' but 235 // specifies explicitely a default value for each tile depending 236 // on the wavelet transform that is used 237 setDefault("none"); 238 239 for(int t=0; t<nt; t++) { 240 if(isTileSpecified(t)) { 241 continue; 242 } 243 244 AnWTFilter[][] anfilt; 245 int[] filtType = new int[nComp]; 246 for(int c=0; c<3; c++) { 247 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,c); 248 filtType[c] = anfilt[0][0].getFilterType(); 249 } 250 251 // Check that the three components use the same filters 252 boolean reject = false; 253 for(int c=1; c<nComp;c++){ 254 if(filtType[c]!=filtType[0]) 255 reject = true; 256 } 257 258 if(reject) { 259 setTileDef(t,"none"); 260 } else { 261 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,0); 262 if(anfilt[0][0].getFilterType()==W9X7) { 263 setTileDef(t,"ict"); 264 } else { 265 setTileDef(t,"rct"); 266 } 267 } 268 } 269 } 270 271 // Check validity of component transformation of each tile compared to 272 // the filter used. 273 for(int t=nt-1; t>=0; t--) { 274 275 if(((String)getTileDef(t)).equals("none")) { 276 // No comp. transf is used. No check is needed 277 continue; 278 } 279 else if(((String)getTileDef(t)).equals("rct")) { 280 // Tile is using Reversible component transform 281 int filterType = getFilterType(t,wfs); 282 switch(filterType){ 283 case FilterTypes.W5X3: // OK 284 break; 285 case FilterTypes.W9X7: // Must use ICT 286 if(isTileSpecified(t)){ 287 // User has requested RCT -> Error 288 throw new IllegalArgumentException("Cannot use RCT "+ 289 "with 9x7 filter "+ 290 "in tile "+t); 291 } 292 else{ // Specify ICT for this tile 293 setTileDef(t,"ict"); 294 } 295 break; 296 default: 297 throw new IllegalArgumentException("Default filter is "+ 298 "not JPEG 2000 part"+ 299 " I compliant"); 300 } 301 } else { // ICT 302 int filterType = getFilterType(t,wfs); 303 switch(filterType) { 304 case FilterTypes.W5X3: // Must use RCT 305 if(isTileSpecified(t)){ 306 // User has requested ICT -> Error 307 throw new IllegalArgumentException("Cannot use ICT "+ 308 "with filter 5x3 "+ 309 "in tile "+t); 310 } 311 else{ 312 setTileDef(t,"rct"); 313 } 314 break; 315 case FilterTypes.W9X7: // OK 316 break; 317 default: 318 throw new IllegalArgumentException("Default filter is "+ 319 "not JPEG 2000 part"+ 320 " I compliant"); 321 322 } 323 } 324 } 325 } 326 327 /** Get the filter type common to all component of a given tile. If the 328 * tile index is -1, it searches common filter type of default 329 * specifications. 330 * 331 * @param t The tile index 332 * 333 * @param wfs The analysis filters specifications 334 * 335 * @return The filter type common to all the components 336 * 337 */ 338 private int getFilterType(int t, AnWTFilterSpec wfs){ 339 AnWTFilter[][] anfilt; 340 int[] filtType = new int[nComp]; 341 for(int c=0;c<nComp; c++){ 342 if(t==-1) 343 anfilt = (AnWTFilter[][])wfs.getCompDef(c); 344 else 345 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,c); 346 filtType[c] = anfilt[0][0].getFilterType(); 347 } 348 349 // Check that all filters are the same one 350 boolean reject = false; 351 for(int c=1; c<nComp;c++){ 352 if(filtType[c]!=filtType[0]) 353 reject = true; 354 } 355 if(reject){ 356 throw new IllegalArgumentException("Can not use component"+ 357 " transformation when "+ 358 "components do not use "+ 359 "the same filters"); 360 } 361 return filtType[0]; 362 } 363}