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