001: /*
002: * $RCSfile: ModuleSpec.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:01:58 $
005: * $State: Exp $
006: *
007: * Class: ModuleSpec
008: *
009: * Description: Generic class for storing module specs
010: *
011: * from WTFilterSpec (Diego Santa Cruz)
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: * */
044: package jj2000.j2k;
045:
046: import java.awt.Point;
047: import java.util.*;
048:
049: /**
050: * This generic class is used to handle values to be used by a module for each
051: * tile and component. It uses attribute to determine which value to use. It
052: * should be extended by each module needing this feature.
053: *
054: * This class might be used for values that are only tile specific or
055: * component specific but not both.
056: *
057: * <P>The attributes to use are defined by a hierarchy. The hierarchy is:
058: *
059: * <ul>
060: * <li> Tile and component specific attribute</li>
061: * <li> Tile specific default attribute</li>
062: * <li> Component main default attribute</li>
063: * <li> Main default attribute</li>
064: * </ul>
065: * */
066:
067: public class ModuleSpec implements Cloneable {
068:
069: /** The identifier for a specification module that applies only to
070: * components */
071: public final static byte SPEC_TYPE_COMP = 0;
072:
073: /** The identifier for a specification module that applies only to
074: tiles */
075: public final static byte SPEC_TYPE_TILE = 1;
076:
077: /** The identifier for a specification module that applies both to
078: * tiles and components */
079: public final static byte SPEC_TYPE_TILE_COMP = 2;
080:
081: /** The identifier for default specification */
082: public final static byte SPEC_DEF = 0;
083:
084: /** The identifier for "component default" specification */
085: public final static byte SPEC_COMP_DEF = 1;
086:
087: /** The identifier for "tile default" specification */
088: public final static byte SPEC_TILE_DEF = 2;
089:
090: /** The identifier for a "tile-component" specification */
091: public final static byte SPEC_TILE_COMP = 3;
092:
093: /** The type of the specification module */
094: protected int specType;
095:
096: /** The number of tiles */
097: protected int nTiles = 0;
098:
099: /** The number of components */
100: protected int nComp = 0;
101:
102: /** The spec type for each tile-component. The first index is
103: * the tile index, the second is the component index.
104: */
105: protected byte[][] specValType;
106:
107: /** Default value for each tile-component */
108: protected Object def = null;
109:
110: /** The default value for each component. Null if no component
111: specific value is defined */
112: protected Object[] compDef = null;
113:
114: /** The default value for each tile. Null if no tile specific
115: value is defined */
116: protected Object[] tileDef = null;
117:
118: /** The specific value for each tile-component. Value of tile 16 component
119: * 3 is accessible through the hash value "t16c3". Null if no
120: * tile-component specific value is defined */
121: protected Hashtable tileCompVal;
122:
123: /** The specified value in string format */
124: protected String specified;
125:
126: public ModuleSpec getCopy() {
127: return (ModuleSpec) this .clone();
128: }
129:
130: /**
131: * Constructs a 'ModuleSpec' object, initializing all the components and
132: * tiles to the 'SPEC_DEF' spec val type, for the specified number of
133: * components and tiles.
134: *
135: * @param nt The number of tiles
136: *
137: * @param nc The number of components
138: *
139: * @param type the type of the specification module i.e. tile specific,
140: * component specific or both.
141: * */
142: public ModuleSpec(int nt, int nc, byte type) {
143:
144: nTiles = nt;
145: nComp = nc;
146: specValType = new byte[nt][nc];
147: switch (type) {
148: case SPEC_TYPE_TILE:
149: specType = SPEC_TYPE_TILE;
150: break;
151: case SPEC_TYPE_COMP:
152: specType = SPEC_TYPE_COMP;
153: break;
154: case SPEC_TYPE_TILE_COMP:
155: specType = SPEC_TYPE_TILE_COMP;
156: break;
157: }
158: }
159:
160: protected Object clone() {
161: ModuleSpec ms;
162: try {
163: ms = (ModuleSpec) super .clone();
164: } catch (CloneNotSupportedException e) {
165: throw new Error("Error when cloning ModuleSpec instance");
166: }
167: // Create a copy of the specValType array
168: ms.specValType = new byte[nTiles][nComp];
169: for (int t = 0; t < nTiles; t++) {
170: for (int c = 0; c < nComp; c++) {
171: ms.specValType[t][c] = specValType[t][c];
172: }
173: }
174: // Create a copy of tileDef
175: if (tileDef != null) {
176: ms.tileDef = new Object[nTiles];
177: for (int t = 0; t < nTiles; t++) {
178: ms.tileDef[t] = tileDef[t];
179: }
180: }
181: // Create a copy of tileCompVal
182: if (tileCompVal != null) {
183: ms.tileCompVal = new Hashtable();
184: String tmpKey;
185: Object tmpVal;
186: for (Enumeration e = tileCompVal.keys(); e
187: .hasMoreElements();) {
188: tmpKey = (String) e.nextElement();
189: tmpVal = tileCompVal.get(tmpKey);
190: ms.tileCompVal.put(tmpKey, tmpVal);
191: }
192: }
193: return ms;
194: }
195:
196: /**
197: * Rotate the ModuleSpec instance by 90 degrees (this modifies only tile
198: * and tile-component specifications).
199: *
200: * @param nT Number of tiles along horizontal and vertical axis after
201: * rotation.
202: * */
203: public void rotate90(Point anT) {
204: // Rotate specValType
205: byte[][] tmpsvt = new byte[nTiles][];
206: int ax, ay;
207: Point bnT = new Point(anT.y, anT.x);
208: for (int by = 0; by < bnT.y; by++) {
209: for (int bx = 0; bx < bnT.x; bx++) {
210: ay = bx;
211: ax = bnT.y - by - 1;
212: tmpsvt[ay * anT.x + ax] = specValType[by * bnT.x + bx];
213: }
214: }
215: specValType = tmpsvt;
216:
217: // Rotate tileDef
218: if (tileDef != null) {
219: Object[] tmptd = new Object[nTiles];
220: for (int by = 0; by < bnT.y; by++) {
221: for (int bx = 0; bx < bnT.x; bx++) {
222: ay = bx;
223: ax = bnT.y - by - 1;
224: tmptd[ay * anT.x + ax] = tileDef[by * bnT.x + bx];
225: }
226: }
227: tileDef = tmptd;
228: }
229:
230: // Rotate tileCompVal
231: if (tileCompVal != null && tileCompVal.size() > 0) {
232: Hashtable tmptcv = new Hashtable();
233: String tmpKey;
234: Object tmpVal;
235: int btIdx, atIdx;
236: int i1, i2;
237: int bx, by;
238: for (Enumeration e = tileCompVal.keys(); e
239: .hasMoreElements();) {
240: tmpKey = (String) e.nextElement();
241: tmpVal = tileCompVal.get(tmpKey);
242: i1 = tmpKey.indexOf('t');
243: i2 = tmpKey.indexOf('c');
244: btIdx = (new Integer(tmpKey.substring(i1 + 1, i2)))
245: .intValue();
246: bx = btIdx % bnT.x;
247: by = btIdx / bnT.x;
248: ay = bx;
249: ax = bnT.y - by - 1;
250: atIdx = ax + ay * anT.x;
251: tmptcv.put("t" + atIdx + tmpKey.substring(i2), tmpVal);
252: }
253: tileCompVal = tmptcv;
254: }
255: }
256:
257: /**
258: * Sets default value for this module
259: * */
260: public void setDefault(Object value) {
261: def = value;
262: }
263:
264: /**
265: * Gets default value for this module.
266: *
267: * @return The default value (Must be casted before use)
268: * */
269: public Object getDefault() {
270: return def;
271: }
272:
273: /**
274: * Sets default value for specified component and specValType tag if
275: * allowed by its priority.
276: *
277: * @param c Component index
278: * */
279: public void setCompDef(int c, Object value) {
280: if (specType == SPEC_TYPE_TILE) {
281: String errMsg = "Option whose value is '"
282: + value
283: + "' cannot be "
284: + "specified for components as it is a 'tile only' specific "
285: + "option";
286: throw new Error(errMsg);
287: }
288: if (compDef == null)
289: compDef = new Object[nComp];
290: for (int i = 0; i < nTiles; i++) {
291: if (specValType[i][c] < SPEC_COMP_DEF) {
292: specValType[i][c] = SPEC_COMP_DEF;
293: }
294: }
295: compDef[c] = value;
296: }
297:
298: /**
299: * Gets default value of the specified component. If no specification have
300: * been entered for this component, returns default value.
301: *
302: * @param c Component index
303: *
304: * @return The default value for this component (Must be casted before
305: * use)
306: *
307: * @see #setCompDef
308: * */
309: public Object getCompDef(int c) {
310: if (specType == SPEC_TYPE_TILE) {
311: throw new Error("Illegal use of ModuleSpec class");
312: }
313: if (compDef == null || compDef[c] == null) {
314: return getDefault();
315: } else
316: return compDef[c];
317: }
318:
319: /**
320: * Sets default value for specified tile and specValType tag if
321: * allowed by its priority.
322: *
323: * @param c Tile index.
324: * */
325: public void setTileDef(int t, Object value) {
326: if (specType == SPEC_TYPE_COMP) {
327: String errMsg = "Option whose value is '"
328: + value
329: + "' cannot be "
330: + "specified for tiles as it is a 'component only' specific "
331: + "option";
332: throw new Error(errMsg);
333: }
334: if (tileDef == null)
335: tileDef = new Object[nTiles];
336: for (int i = 0; i < nComp; i++) {
337: if (specValType[t][i] < SPEC_TILE_DEF) {
338: specValType[t][i] = SPEC_TILE_DEF;
339: }
340: }
341: tileDef[t] = value;
342: }
343:
344: /**
345: * Gets default value of the specified tile. If no specification
346: * has been entered, it returns the default value.
347: *
348: * @param t Tile index
349: *
350: * @return The default value for this tile (Must be casted before use)
351: *
352: * @see #setTileDef
353: * */
354: public Object getTileDef(int t) {
355: if (specType == SPEC_TYPE_COMP) {
356: throw new Error("Illegal use of ModuleSpec class");
357: }
358: if (tileDef == null || tileDef[t] == null) {
359: return getDefault();
360: } else
361: return tileDef[t];
362: }
363:
364: /**
365: * Sets value for specified tile-component.
366: *
367: * @param t Tie index
368: *
369: * @param c Component index
370: * */
371: public void setTileCompVal(int t, int c, Object value) {
372: if (specType != SPEC_TYPE_TILE_COMP) {
373: String errMsg = "Option whose value is '" + value
374: + "' cannot be " + "specified for ";
375: switch (specType) {
376: case SPEC_TYPE_TILE:
377: errMsg += "components as it is a 'tile only' specific option";
378: break;
379: case SPEC_TYPE_COMP:
380: errMsg += "tiles as it is a 'component only' specific option";
381: break;
382: }
383: throw new Error(errMsg);
384: }
385: if (tileCompVal == null)
386: tileCompVal = new Hashtable();
387: specValType[t][c] = SPEC_TILE_COMP;
388: tileCompVal.put("t" + t + "c" + c, value);
389: }
390:
391: /**
392: * Gets value of specified tile-component. This method calls getSpec but
393: * has a public access.
394: *
395: * @param t Tile index
396: *
397: * @param c Component index
398: *
399: * @return The value of this tile-component (Must be casted before use)
400: *
401: * @see #setTileCompVal
402: *
403: * @see #getSpec
404: * */
405: public Object getTileCompVal(int t, int c) {
406: if (specType != SPEC_TYPE_TILE_COMP) {
407: throw new Error("Illegal use of ModuleSpec class");
408: }
409: return getSpec(t, c);
410: }
411:
412: /**
413: * Gets value of specified tile-component without knowing if a
414: * specific tile-component value has been previously entered. It
415: * first check if a tile-component specific value has been
416: * entered, then if a tile specific value exist, then if a
417: * component specific value exist. If not the default value is
418: * returned.
419: *
420: * @param t Tile index
421: *
422: * @param c Component index
423: *
424: * @return Value for this tile component.
425: * */
426: protected Object getSpec(int t, int c) {
427: switch (specValType[t][c]) {
428: case SPEC_DEF:
429: return getDefault();
430: case SPEC_COMP_DEF:
431: return getCompDef(c);
432: case SPEC_TILE_DEF:
433: return getTileDef(t);
434: case SPEC_TILE_COMP:
435: return tileCompVal.get("t" + t + "c" + c);
436: default:
437: throw new IllegalArgumentException(
438: "Not recognized spec type");
439: }
440: }
441:
442: /**
443: * Return the spec type of the given tile-component.
444: *
445: * @param t Tile index
446: *
447: * @param c Component index
448: * */
449: public byte getSpecValType(int t, int c) {
450: return specValType[t][c];
451: }
452:
453: /**
454: * Whether or not specifications have been entered for the given
455: * component.
456: *
457: * @param c Index of the component
458: *
459: * @return True if component specification has been defined
460: * */
461: public boolean isCompSpecified(int c) {
462: if (compDef == null || compDef[c] == null)
463: return false;
464: else
465: return true;
466: }
467:
468: /**
469: * Whether or not specifications have been entered for the given
470: * tile.
471: *
472: * @param t Index of the tile
473: *
474: * @return True if tile specification has been entered
475: * */
476: public boolean isTileSpecified(int t) {
477: if (tileDef == null || tileDef[t] == null)
478: return false;
479: else
480: return true;
481: }
482:
483: /**
484: * Whether or not a tile-component specification has been defined
485: *
486: * @param t Tile index
487: *
488: * @param c Component index
489: *
490: * @return True if a tile-component specification has been defined.
491: * */
492: public boolean isTileCompSpecified(int t, int c) {
493: if (tileCompVal == null
494: || tileCompVal.get("t" + t + "c" + c) == null)
495: return false;
496: else
497: return true;
498: }
499:
500: /**
501: * This method is responsible of parsing tile indexes set and
502: * component indexes set for an option. Such an argument must
503: * follow the following policy:<br>
504: *
505: * <tt>t\<indexes set\></tt> or <tt>c\<indexes set\></tt> where
506: * tile or component indexes are separated by commas or a
507: * dashes.
508: *
509: * <p><u>Example:</u><br>
510: * <li> <tt>t0,3,4</tt> means tiles with indexes 0, 3 and 4.<br>
511: * <li> <tt>t2-4</tt> means tiles with indexes 2,3 and 4.<br>
512: *
513: * It returns a boolean array skteching which tile or component are
514: * concerned by the next parameters.
515: *
516: * @param word The word to parse.
517: *
518: * @param maxIdx Maximum authorized index
519: *
520: * @return Indexes concerned by this parameter.
521: * */
522: public static final boolean[] parseIdx(String word, int maxIdx) {
523: int nChar = word.length(); // Number of characters
524: char c = word.charAt(0); // current character
525: int idx = -1; // Current (tile or component) index
526: int lastIdx = -1; // Last (tile or component) index
527: boolean isDash = false; // Whether or not last separator was a dash
528:
529: boolean[] idxSet = new boolean[maxIdx];
530: int i = 1; // index of the current character
531:
532: while (i < nChar) {
533: c = word.charAt(i);
534: if (Character.isDigit(c)) {
535: if (idx == -1)
536: idx = 0;
537: idx = idx * 10 + (c - '0');
538: } else {
539: if (idx == -1 || (c != ',' && c != '-')) {
540: throw new IllegalArgumentException(
541: "Bad construction for " + "parameter: "
542: + word);
543: }
544: if (idx < 0 || idx >= maxIdx) {
545: throw new IllegalArgumentException(
546: "Out of range index in " + "parameter `"
547: + word + "' : " + +idx);
548: }
549:
550: // Found a comma
551: if (c == ',') {
552: if (isDash) { // Previously found a dash, fill idxSet
553: for (int j = lastIdx + 1; j < idx; j++) {
554: idxSet[j] = true;
555: }
556: }
557: isDash = false;
558: } else
559: // Found a dash
560: isDash = true;
561:
562: // Udate idxSet
563: idxSet[idx] = true;
564: lastIdx = idx;
565: idx = -1;
566: }
567: i++;
568: }
569:
570: // Process last found index
571: if (idx < 0 || idx >= maxIdx) {
572: throw new IllegalArgumentException("Out of range index in "
573: + "parameter `" + word + "' : " + idx);
574: }
575: if (isDash)
576: for (int j = lastIdx + 1; j < idx; j++) {
577: idxSet[j] = true;
578: }
579: idxSet[idx] = true;
580:
581: return idxSet;
582: }
583:
584: /**
585: * Returns a tile-component representative using default value.
586: *
587: * @return Tile component index in an array (first element: tile
588: * index, second element: component index).
589: * */
590: /*
591: public int[] getDefRep(){
592: int[] tcidx = new int[2];
593: for(int t=nTiles-1; t>=0; t--){
594: for(int c=nComp-1; c>=0; c--){
595: if(specValType[t][c]==SPEC_DEF){
596: tcidx[0] = t;
597: tcidx[1] = c;
598: return tcidx;
599: }
600: }
601: }
602:
603: throw new IllegalArgumentException("No representative for "+
604: "default value");
605: }
606: */
607: /**
608: * Returns a component representative using tile default value.
609: *
610: * @param t Tile index
611: *
612: * @return component index of the representant
613: * */
614: /*
615: public int getTileDefRep(int t){
616: for(int c=nComp-1; c>=0; c--)
617: if(specValType[t][c]==SPEC_TILE_DEF){
618: return c;
619: }
620:
621: throw new IllegalArgumentException("No representative for tile "+
622: "default value");
623: }
624: */
625: /**
626: * Returns a tile representative using component default value.
627: *
628: * @param c Component index
629: *
630: * @return tile index of the representant
631: * */
632: /*
633: public int getCompDefRep(int c){
634: for(int t=nTiles-1; t>=0; t--) {
635: if(specValType[t][c]==SPEC_COMP_DEF){
636: return t;
637: }
638: }
639:
640: throw new IllegalArgumentException("No representative for component "+
641: "default value, c="+c);
642: }
643: */
644: /*
645: public String getSpecified() {
646: return specified;
647: }
648: */
649: }
|