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 // Parse argument 162 StringTokenizer stk = new StringTokenizer(param); 163 String word; // current word 164 byte curSpecType = SPEC_DEF; // Specification type of the 165 // current parameter 166 boolean[] tileSpec = null; // Tiles concerned by the 167 // specification 168 Boolean value; 169 170 while(stk.hasMoreTokens()){ 171 word = stk.nextToken(); 172 173 switch(word.charAt(0)){ 174 case 't': // Tiles specification 175 tileSpec = parseIdx(word,nTiles); 176 if(curSpecType==SPEC_COMP_DEF) { 177 curSpecType = SPEC_TILE_COMP; 178 } else { 179 curSpecType = SPEC_TILE_DEF; 180 } 181 break; 182 case 'c': // Components specification 183 throw new IllegalArgumentException("Component specific "+ 184 " parameters"+ 185 " not allowed with "+ 186 "'-Mct' option"); 187 default: 188 if(word.equals("off")) { 189 if(curSpecType==SPEC_DEF) { 190 setDefault("none"); 191 } else if(curSpecType==SPEC_TILE_DEF) { 192 for(int i=tileSpec.length-1; i>=0; i--) 193 if(tileSpec[i]) { 194 setTileDef(i,"none"); 195 } 196 } 197 } else if(word.equals("on")) { 198 if(nc<3) { 199 setDefault("none"); 200 break; 201 } 202 203 if(curSpecType==SPEC_DEF) { // Set arbitrarily the default 204 // value to RCT (later will be found the suitable 205 // component transform for each tile) 206 setDefault("rct"); 207 } else if (curSpecType==SPEC_TILE_DEF) { 208 for(int i=tileSpec.length-1; i>=0; i--) { 209 if(tileSpec[i]) { 210 if(getFilterType(i,wfs)==W5X3) { 211 setTileDef(i,"rct"); 212 } else { 213 setTileDef(i,"ict"); 214 } 215 } 216 } 217 } 218 } else { 219 throw new IllegalArgumentException("Default parameter of "+ 220 "option Mct not"+ 221 " recognized: "+param); 222 } 223 224 // Re-initialize 225 curSpecType = SPEC_DEF; 226 tileSpec = null; 227 break; 228 } 229 } 230 231 // Check that default value has been specified 232 if(getDefault()==null) { 233 // If not, set arbitrarily the default value to 'none' but 234 // specifies explicitely a default value for each tile depending 235 // on the wavelet transform that is used 236 setDefault("none"); 237 238 for(int t=0; t<nt; t++) { 239 if(isTileSpecified(t)) { 240 continue; 241 } 242 243 AnWTFilter[][] anfilt; 244 int[] filtType = new int[nComp]; 245 for(int c=0; c<3; c++) { 246 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,c); 247 filtType[c] = anfilt[0][0].getFilterType(); 248 } 249 250 // Check that the three components use the same filters 251 boolean reject = false; 252 for(int c=1; c<nComp;c++){ 253 if(filtType[c]!=filtType[0]) 254 reject = true; 255 } 256 257 if(reject) { 258 setTileDef(t,"none"); 259 } else { 260 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,0); 261 if(anfilt[0][0].getFilterType()==W9X7) { 262 setTileDef(t,"ict"); 263 } else { 264 setTileDef(t,"rct"); 265 } 266 } 267 } 268 } 269 270 // Check validity of component transformation of each tile compared to 271 // the filter used. 272 for(int t=nt-1; t>=0; t--) { 273 274 if(((String)getTileDef(t)).equals("none")) { 275 // No comp. transf is used. No check is needed 276 continue; 277 } 278 else if(((String)getTileDef(t)).equals("rct")) { 279 // Tile is using Reversible component transform 280 int filterType = getFilterType(t,wfs); 281 switch(filterType){ 282 case FilterTypes.W5X3: // OK 283 break; 284 case FilterTypes.W9X7: // Must use ICT 285 if(isTileSpecified(t)){ 286 // User has requested RCT -> Error 287 throw new IllegalArgumentException("Cannot use RCT "+ 288 "with 9x7 filter "+ 289 "in tile "+t); 290 } 291 else{ // Specify ICT for this tile 292 setTileDef(t,"ict"); 293 } 294 break; 295 default: 296 throw new IllegalArgumentException("Default filter is "+ 297 "not JPEG 2000 part"+ 298 " I compliant"); 299 } 300 } else { // ICT 301 int filterType = getFilterType(t,wfs); 302 switch(filterType) { 303 case FilterTypes.W5X3: // Must use RCT 304 if(isTileSpecified(t)){ 305 // User has requested ICT -> Error 306 throw new IllegalArgumentException("Cannot use ICT "+ 307 "with filter 5x3 "+ 308 "in tile "+t); 309 } 310 else{ 311 setTileDef(t,"rct"); 312 } 313 break; 314 case FilterTypes.W9X7: // OK 315 break; 316 default: 317 throw new IllegalArgumentException("Default filter is "+ 318 "not JPEG 2000 part"+ 319 " I compliant"); 320 321 } 322 } 323 } 324 } 325 326 /** Get the filter type common to all component of a given tile. If the 327 * tile index is -1, it searches common filter type of default 328 * specifications. 329 * 330 * @param t The tile index 331 * 332 * @param wfs The analysis filters specifications 333 * 334 * @return The filter type common to all the components 335 * 336 */ 337 private int getFilterType(int t, AnWTFilterSpec wfs){ 338 AnWTFilter[][] anfilt; 339 int[] filtType = new int[nComp]; 340 for(int c=0;c<nComp; c++){ 341 if(t==-1) 342 anfilt = (AnWTFilter[][])wfs.getCompDef(c); 343 else 344 anfilt = (AnWTFilter[][])wfs.getTileCompVal(t,c); 345 filtType[c] = anfilt[0][0].getFilterType(); 346 } 347 348 // Check that all filters are the same one 349 boolean reject = false; 350 for(int c=1; c<nComp;c++){ 351 if(filtType[c]!=filtType[0]) 352 reject = true; 353 } 354 if(reject){ 355 throw new IllegalArgumentException("Can not use component"+ 356 " transformation when "+ 357 "components do not use "+ 358 "the same filters"); 359 } 360 return filtType[0]; 361 } 362}