001: /*
002: * $RCSfile: PrecinctSizeSpec.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:04 $
005: * $State: Exp $
006: *
007: * Class: PrecinctSizeSpec
008: *
009: * Description: Specification of the precinct sizes
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: * */
044: package jj2000.j2k.entropy;
045:
046: import jj2000.j2k.codestream.*;
047: import jj2000.j2k.wavelet.*;
048: import jj2000.j2k.image.*;
049: import jj2000.j2k.util.*;
050: import jj2000.j2k.*;
051:
052: import java.util.*;
053: import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava;
054:
055: /**
056: * This class extends ModuleSpec class for precinct partition sizes holding
057: * purposes.
058: *
059: * <p>It stores the size a of precinct when precinct partition is used or not.
060: * If precinct partition is used, we can have several packets for a given
061: * resolution level whereas there is only one packet per resolution level if
062: * no precinct partition is used.
063: * */
064: public class PrecinctSizeSpec extends ModuleSpec {
065:
066: /** Name of the option */
067: private static final String optName = "Cpp";
068:
069: /** Reference to wavelet number of decomposition levels for each
070: * tile-component. */
071: private IntegerSpec dls;
072:
073: /**
074: * Creates a new PrecinctSizeSpec object for the specified number of tiles
075: * and components.
076: *
077: * @param nt The number of tiles
078: *
079: * @param nc The number of components
080: *
081: * @param type the type of the specification module i.e. tile specific,
082: * component specific or both.
083: *
084: * @param dls Reference to the number of decomposition levels
085: * specification
086: * */
087: public PrecinctSizeSpec(int nt, int nc, byte type, IntegerSpec dls) {
088: super (nt, nc, type);
089: this .dls = dls;
090: }
091:
092: /**
093: * Creates a new PrecinctSizeSpec object for the specified number of tiles
094: * and components and the J2KImageWriteParamJava instance.
095: *
096: * @param nt The number of tiles
097: *
098: * @param nc The number of components
099: *
100: * @param type the type of the specification module i.e. tile specific,
101: * component specific or both.
102: *
103: * @param imgsrc The image source (used to get the image size)
104: *
105: * @param wp The J2KImageWriteParamJava instance
106: * */
107: public PrecinctSizeSpec(int nt, int nc, byte type,
108: BlkImgDataSrc imgsrc, IntegerSpec dls,
109: J2KImageWriteParamJava wp, String values) {
110: super (nt, nc, type);
111:
112: this .dls = dls;
113:
114: // The precinct sizes are stored in a 2 elements vector array, the
115: // first element containing a vector for the precincts width for each
116: // resolution level and the second element containing a vector for the
117: // precincts height for each resolution level. The precincts sizes are
118: // specified from the highest resolution level to the lowest one
119: // (i.e. 0). If there are less elements than the number of
120: // decomposition levels, the last element is used for all remaining
121: // resolution levels (i.e. if the precincts sizes are specified only
122: // for resolutions levels 5, 4 and 3, then the precincts size for
123: // resolution levels 2, 1 and 0 will be the same as the size used for
124: // resolution level 3).
125:
126: // Boolean used to know if we were previously reading a precinct's
127: // size or if we were reading something else.
128: boolean wasReadingPrecinctSize = false;
129:
130: String param = values;
131: /*
132: if (values == null)
133: param = defaultValue; // the default is null
134: */
135: // Set precinct sizes to default i.e. 2^15 =
136: // Markers.PRECINCT_PARTITION_DEF_SIZE
137: Vector tmpv[] = new Vector[2];
138: tmpv[0] = new Vector(); // ppx
139: tmpv[0].addElement(new Integer(
140: Markers.PRECINCT_PARTITION_DEF_SIZE));
141: tmpv[1] = new Vector(); // ppy
142: tmpv[1].addElement(new Integer(
143: Markers.PRECINCT_PARTITION_DEF_SIZE));
144: setDefault(tmpv);
145:
146: if (param == null) {
147: // No precinct size specified in the command line so we do not try
148: // to parse it.
149: return;
150: }
151:
152: // Precinct partition is used : parse arguments
153: StringTokenizer stk = new StringTokenizer(param);
154: byte curSpecType = SPEC_DEF; // Specification type of the
155: // current parameter
156: boolean[] tileSpec = null; // Tiles concerned by the specification
157: boolean[] compSpec = null; // Components concerned by the specification
158: int i, xIdx, ci, ti;
159:
160: boolean endOfParamList = false;
161: String word = null; // current word
162: Integer w, h;
163: String errMsg = null;
164:
165: while ((stk.hasMoreTokens() || wasReadingPrecinctSize)
166: && !endOfParamList) {
167:
168: Vector v[] = new Vector[2]; // v[0] : ppx, v[1] : ppy
169:
170: // We do not read the next token if we were reading a precinct's
171: // size argument as we have already read the next token into word.
172: if (!wasReadingPrecinctSize) {
173: word = stk.nextToken();
174: }
175:
176: wasReadingPrecinctSize = false;
177:
178: switch (word.charAt(0)) {
179:
180: case 't': // Tiles specification
181: tileSpec = parseIdx(word, nTiles);
182: if (curSpecType == SPEC_COMP_DEF) {
183: curSpecType = SPEC_TILE_COMP;
184: } else {
185: curSpecType = SPEC_TILE_DEF;
186: }
187: break;
188:
189: case 'c': // Components specification
190: compSpec = parseIdx(word, nComp);
191: if (curSpecType == SPEC_TILE_DEF) {
192: curSpecType = SPEC_TILE_COMP;
193: } else {
194: curSpecType = SPEC_COMP_DEF;
195: }
196: break;
197:
198: default:
199: if (!Character.isDigit(word.charAt(0))) {
200: errMsg = "Bad construction for parameter: " + word;
201: throw new IllegalArgumentException(errMsg);
202: }
203:
204: // Initialises Vector objects
205: v[0] = new Vector(); // ppx
206: v[1] = new Vector(); // ppy
207:
208: while (true) {
209:
210: // Now get the precinct dimensions
211: try {
212: // Get precinct width
213: w = new Integer(word);
214:
215: // Get next word in argument list
216: try {
217: word = stk.nextToken();
218: } catch (NoSuchElementException e) {
219: errMsg = "'" + optName
220: + "' option : could not "
221: + "parse the precinct's width";
222: throw new IllegalArgumentException(errMsg);
223:
224: }
225: // Get precinct height
226: h = new Integer(word);
227: if (w.intValue() != (1 << MathUtil.log2(w
228: .intValue()))
229: || h.intValue() != (1 << MathUtil
230: .log2(h.intValue()))) {
231: errMsg = "Precinct dimensions must be powers of 2";
232: throw new IllegalArgumentException(errMsg);
233: }
234: } catch (NumberFormatException e) {
235: errMsg = "'" + optName
236: + "' option : the argument '" + word
237: + "' could not be parsed.";
238: throw new IllegalArgumentException(errMsg);
239: }
240: // Store packet's dimensions in Vector arrays
241: v[0].addElement(w);
242: v[1].addElement(h);
243:
244: // Try to get the next token
245: if (stk.hasMoreTokens()) {
246: word = stk.nextToken();
247: if (!Character.isDigit(word.charAt(0))) {
248: // The next token does not start with a digit so
249: // it is not a precinct's size argument. We set
250: // the wasReadingPrecinctSize booleen such that we
251: // know that we don't have to read another token
252: // and check for the end of the parameters list.
253: wasReadingPrecinctSize = true;
254:
255: if (curSpecType == SPEC_DEF) {
256: setDefault(v);
257: } else if (curSpecType == SPEC_TILE_DEF) {
258: for (ti = tileSpec.length - 1; ti >= 0; ti--) {
259: if (tileSpec[ti]) {
260: setTileDef(ti, v);
261: }
262: }
263: } else if (curSpecType == SPEC_COMP_DEF) {
264: for (ci = compSpec.length - 1; ci >= 0; ci--) {
265: if (compSpec[ci]) {
266: setCompDef(ci, v);
267: }
268: }
269: } else {
270: for (ti = tileSpec.length - 1; ti >= 0; ti--) {
271: for (ci = compSpec.length - 1; ci >= 0; ci--) {
272: if (tileSpec[ti]
273: && compSpec[ci]) {
274: setTileCompVal(ti, ci, v);
275: }
276: }
277: }
278: }
279: // Re-initialize
280: curSpecType = SPEC_DEF;
281: tileSpec = null;
282: compSpec = null;
283:
284: // Go back to 'normal' parsing
285: break;
286: } else {
287: // Next token starts with a digit so read it
288: }
289: } else {
290: // We have reached the end of the parameters list so
291: // we store the last precinct's sizes and we stop
292: if (curSpecType == SPEC_DEF) {
293: setDefault(v);
294: } else if (curSpecType == SPEC_TILE_DEF) {
295: for (ti = tileSpec.length - 1; ti >= 0; ti--) {
296: if (tileSpec[ti]) {
297: setTileDef(ti, v);
298: }
299: }
300: } else if (curSpecType == SPEC_COMP_DEF) {
301: for (ci = compSpec.length - 1; ci >= 0; ci--) {
302: if (compSpec[ci]) {
303: setCompDef(ci, v);
304: }
305: }
306: } else {
307: for (ti = tileSpec.length - 1; ti >= 0; ti--) {
308: for (ci = compSpec.length - 1; ci >= 0; ci--) {
309: if (tileSpec[ti] && compSpec[ci]) {
310: setTileCompVal(ti, ci, v);
311: }
312: }
313: }
314: }
315: endOfParamList = true;
316: break;
317: }
318: } // while (true)
319: break;
320: } // switch
321: } // while
322: }
323:
324: /**
325: * Returns the precinct partition width in component 'n' and tile 't' at
326: * resolution level 'rl'. If the tile index is equal to -1 or if the
327: * component index is equal to -1 it means that those should not be taken
328: * into account.
329: *
330: * @param t The tile index, in raster scan order. Specify -1 if it is not
331: * a specific tile.
332: *
333: * @param c The component index. Specify -1 if it is not a specific
334: * component.
335: *
336: * @param rl The resolution level
337: *
338: * @return The precinct partition width in component 'c' and tile 't' at
339: * resolution level 'rl'.
340: * */
341: public int getPPX(int t, int c, int rl) {
342: int mrl, idx;
343: Vector[] v = null;
344: boolean tileSpecified = (t != -1 ? true : false);
345: boolean compSpecified = (c != -1 ? true : false);
346:
347: // Get the maximum number of decomposition levels and the object
348: // (Vector array) containing the precinct dimensions (width and
349: // height) for the specified (or not) tile/component
350: if (tileSpecified && compSpecified) {
351: mrl = ((Integer) dls.getTileCompVal(t, c)).intValue();
352: v = (Vector[]) getTileCompVal(t, c);
353: } else if (tileSpecified && !compSpecified) {
354: mrl = ((Integer) dls.getTileDef(t)).intValue();
355: v = (Vector[]) getTileDef(t);
356: } else if (!tileSpecified && compSpecified) {
357: mrl = ((Integer) dls.getCompDef(c)).intValue();
358: v = (Vector[]) getCompDef(c);
359: } else {
360: mrl = ((Integer) dls.getDefault()).intValue();
361: v = (Vector[]) getDefault();
362: }
363: idx = mrl - rl;
364: if (v[0].size() > idx) {
365: return ((Integer) v[0].elementAt(idx)).intValue();
366: } else {
367: return ((Integer) v[0].elementAt(v[0].size() - 1))
368: .intValue();
369: }
370: }
371:
372: /**
373: * Returns the precinct partition height in component 'n' and tile 't' at
374: * resolution level 'rl'. If the tile index is equal to -1 or if the
375: * component index is equal to -1 it means that those should not be taken
376: * into account.
377: *
378: * @param t The tile index, in raster scan order. Specify -1 if it is not
379: * a specific tile.
380: *
381: * @param c The component index. Specify -1 if it is not a specific
382: * component.
383: *
384: * @param rl The resolution level.
385: *
386: * @return The precinct partition width in component 'n' and tile 't' at
387: * resolution level 'rl'.
388: * */
389: public int getPPY(int t, int c, int rl) {
390: int mrl, idx;
391: Vector[] v = null;
392: boolean tileSpecified = (t != -1 ? true : false);
393: boolean compSpecified = (c != -1 ? true : false);
394:
395: // Get the maximum number of decomposition levels and the object
396: // (Vector array) containing the precinct dimensions (width and
397: // height) for the specified (or not) tile/component
398: if (tileSpecified && compSpecified) {
399: mrl = ((Integer) dls.getTileCompVal(t, c)).intValue();
400: v = (Vector[]) getTileCompVal(t, c);
401: } else if (tileSpecified && !compSpecified) {
402: mrl = ((Integer) dls.getTileDef(t)).intValue();
403: v = (Vector[]) getTileDef(t);
404: } else if (!tileSpecified && compSpecified) {
405: mrl = ((Integer) dls.getCompDef(c)).intValue();
406: v = (Vector[]) getCompDef(c);
407: } else {
408: mrl = ((Integer) dls.getDefault()).intValue();
409: v = (Vector[]) getDefault();
410: }
411: idx = mrl - rl;
412: if (v[1].size() > idx) {
413: return ((Integer) v[1].elementAt(idx)).intValue();
414: } else {
415: return ((Integer) v[1].elementAt(v[1].size() - 1))
416: .intValue();
417: }
418: }
419: }
|