001: /*
002: * $RCSfile: InvCompTransf.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:14 $
005: * $State: Exp $
006: *
007: * Class: InvCompTransf
008: *
009: * Description: Inverse Component transformations applied to tiles
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.image.invcomptransf;
045:
046: import jj2000.j2k.wavelet.synthesis.*;
047: import jj2000.j2k.decoder.*;
048: import jj2000.j2k.image.*;
049: import jj2000.j2k.util.*;
050: import jj2000.j2k.*;
051:
052: /**
053: * This class apply inverse component transformations to the tiles depending
054: * on specification read from the codestream header. These transformations can
055: * be used to improve compression efficiency but are not related to colour
056: * transforms used to map colour values for display purposes. JPEG 2000 part I
057: * defines 2 component transformations: RCT (Reversible Component
058: * Transformation) and ICT (Irreversible Component Transformation).
059: *
060: * @see ModuleSpec
061: * */
062: public class InvCompTransf extends ImgDataAdapter implements
063: BlkImgDataSrc {
064:
065: /** Identifier for no component transformation. Value is 0. */
066: public static final int NONE = 0;
067:
068: /** The prefix for inverse component transformation options: 'M' */
069: public final static char OPT_PREFIX = 'M';
070:
071: /** The list of parameters that is accepted by the inverse
072: * component transformation module. They start with 'M'. */
073: private final static String[][] pinfo = null;
074:
075: /** Identifier for the Inverse Reversible Component Transformation
076: (INV_RCT). Value is 1. */
077: public static final int INV_RCT = 1;
078:
079: /** Identifier for the Inverse Irreversible Component
080: Transformation (INV_ICT). Value is 2 */
081: public static final int INV_ICT = 2;
082:
083: /** The source of image data */
084: private BlkImgDataSrc src;
085:
086: /** The component transformations specifications */
087: private CompTransfSpec cts;
088:
089: /** The wavelet filter specifications */
090: private SynWTFilterSpec wfs;
091:
092: /** The type of the current component transformation JPEG 2000
093: * part I only support NONE, FORW_RCT and FORW_ICT types*/
094: private int transfType = NONE;
095:
096: /** Buffer for each component of output data */
097: private int[][] outdata = new int[3][];
098:
099: /** Block used to request component 0 */
100: private DataBlk block0;
101:
102: /** Block used to request component 1 */
103: private DataBlk block1;
104:
105: /** Block used to request component 2 */
106: private DataBlk block2;
107:
108: /** Data block used only to store coordinates and progressiveness
109: of the buffered blocks */
110: private DataBlkInt dbi = new DataBlkInt();
111:
112: /** The bit-depths of un-transformed components */
113: private int utdepth[];
114:
115: /** Flag indicating whether the decoder should skip the component
116: * transform*/
117: private boolean noCompTransf = false;
118:
119: /**
120: * Constructs a new ForwCompTransf object that operates on the
121: * specified source of image data.
122: *
123: * @param imgSrc The source from where to get the data to be
124: * transformed
125: *
126: * @param decSpec The decoder specifications
127: *
128: * @see BlkImgDataSrc
129: * */
130: public InvCompTransf(BlkImgDataSrc imgSrc, DecoderSpecs decSpec,
131: int[] utdepth) {
132: super (imgSrc);
133: this .cts = decSpec.cts;
134: this .wfs = decSpec.wfs;
135: src = imgSrc;
136: this .utdepth = utdepth;
137: }
138:
139: /**
140: * Returns the parameters that are used in this class and implementing
141: * classes. It returns a 2D String array. Each of the 1D arrays is for a
142: * different option, and they have 4 elements. The first element is the
143: * option name, the second one is the synopsis, the third one is a long
144: * description of what the parameter is and the fourth is its default
145: * value. The synopsis or description may be 'null', in which case it is
146: * assumed that there is no synopsis or description of the option,
147: * respectively. Null may be returned if no options are supported.
148: *
149: * @return the options name, their synopsis and their explanation,
150: * or null if no options are supported.
151: * */
152: public static String[][] getParameterInfo() {
153: return pinfo;
154: }
155:
156: /**
157: * Returns a string with a descriptive text of which inverse component
158: * transformation is used. This can be either "Inverse RCT" or "Inverse
159: * ICT" or "No component transformation" depending on the current tile.
160: *
161: * @return A descriptive string
162: * */
163: public String toString() {
164: switch (transfType) {
165: case INV_RCT:
166: return "Inverse RCT";
167: case INV_ICT:
168: return "Inverse ICT";
169: case NONE:
170: return "No component transformation";
171: default:
172: throw new IllegalArgumentException("Non JPEG 2000 part I"
173: + " component transformation");
174: }
175: }
176:
177: /**
178: * Returns true if this transform is reversible in current
179: * tile. Reversible component transformations are those which operation
180: * can be completely reversed without any loss of information (not even
181: * due to rounding).
182: *
183: * @return Reversibility of component transformation in current
184: * tile
185: * */
186: public boolean isReversible() {
187: switch (transfType) {
188: case NONE:
189: case INV_RCT:
190: return true;
191: case INV_ICT:
192: return false;
193: default:
194: throw new IllegalArgumentException("Non JPEG 2000 part I"
195: + " component transformation");
196: }
197: }
198:
199: /**
200: * Returns the position of the fixed point in the specified
201: * component. This is the position of the least significant integral
202: * (i.e. non-fractional) bit, which is equivalent to the number of
203: * fractional bits. For instance, for fixed-point values with 2 fractional
204: * bits, 2 is returned. For floating-point data this value does not apply
205: * and 0 should be returned. Position 0 is the position of the least
206: * significant bit in the data.
207: *
208: * <P>This default implementation assumes that the number of fractional
209: * bits is not modified by the component mixer.
210: *
211: * @param c The index of the component.
212: *
213: * @return The value of the fixed point position of the source since the
214: * color transform does not affect it.
215: * */
216: public int getFixedPoint(int c) {
217: return src.getFixedPoint(c);
218: }
219:
220: /**
221: * Calculates the bitdepths of the transformed components, given the
222: * bitdepth of the un-transformed components and the component
223: * tranformation type.
224: *
225: * @param utdepth The bitdepth of each un-transformed component
226: *
227: * @param ttype The type ID of the inverse component tranformation
228: *
229: * @param tdepth If not null the results are stored in this
230: * array, otherwise a new array is allocated and returned.
231: *
232: * @return The bitdepth of each transformed component.
233: * */
234: public static int[] calcMixedBitDepths(int utdepth[], int ttype,
235: int tdepth[]) {
236:
237: if (utdepth.length < 3 && ttype != NONE) {
238: throw new IllegalArgumentException();
239: }
240:
241: if (tdepth == null) {
242: tdepth = new int[utdepth.length];
243: }
244:
245: switch (ttype) {
246: case NONE:
247: System.arraycopy(utdepth, 0, tdepth, 0, utdepth.length);
248: break;
249: case INV_RCT:
250: if (utdepth.length > 3) {
251: System.arraycopy(utdepth, 3, tdepth, 3,
252: utdepth.length - 3);
253: }
254: // The formulas are:
255: // tdepth[0] = ceil(log2(2^(utdepth[0])+2^utdepth[1]+
256: // 2^(utdepth[2])))-2+1
257: // tdepth[1] = ceil(log2(2^(utdepth[0])+2^(utdepth[1])-1))+1
258: // tdepth[2] = ceil(log2(2^(utdepth[1])+2^(utdepth[2])-1))+1
259: // The MathUtil.log2(x) function calculates floor(log2(x)), so we
260: // use 'MathUtil.log2(2*x-1)+1', which calculates ceil(log2(x))
261: // for any x>=1, x integer.
262: tdepth[0] = MathUtil.log2((1 << utdepth[0])
263: + (2 << utdepth[1]) + (1 << utdepth[2]) - 1) - 2 + 1;
264: tdepth[1] = MathUtil.log2((1 << utdepth[2])
265: + (1 << utdepth[1]) - 1) + 1;
266: tdepth[2] = MathUtil.log2((1 << utdepth[0])
267: + (1 << utdepth[1]) - 1) + 1;
268: break;
269: case INV_ICT:
270: if (utdepth.length > 3) {
271: System.arraycopy(utdepth, 3, tdepth, 3,
272: utdepth.length - 3);
273: }
274: // The MathUtil.log2(x) function calculates floor(log2(x)), so we
275: // use 'MathUtil.log2(2*x-1)+1', which calculates ceil(log2(x))
276: // for any x>=1, x integer.
277: tdepth[0] = MathUtil.log2((int) Math
278: .floor((1 << utdepth[0]) * 0.299072
279: + (1 << utdepth[1]) * 0.586914
280: + (1 << utdepth[2]) * 0.114014) - 1) + 1;
281: tdepth[1] = MathUtil.log2((int) Math
282: .floor((1 << utdepth[0]) * 0.168701
283: + (1 << utdepth[1]) * 0.331299
284: + (1 << utdepth[2]) * 0.5) - 1) + 1;
285: tdepth[2] = MathUtil
286: .log2((int) Math.floor((1 << utdepth[0]) * 0.5
287: + (1 << utdepth[1]) * 0.418701
288: + (1 << utdepth[2]) * 0.081299) - 1) + 1;
289: break;
290: }
291:
292: return tdepth;
293: }
294:
295: /**
296: * Returns the number of bits, referred to as the "range bits",
297: * corresponding to the nominal range of the data in the specified
298: * component. If this number is <i>b</b> then for unsigned data the
299: * nominal range is between 0 and 2^b-1, and for signed data it is between
300: * -2^(b-1) and 2^(b-1)-1.
301: *
302: * @param c The index of the component.
303: *
304: * @return The bitdepth of un-transformed component 'c'.
305: * */
306: public int getNomRangeBits(int c) {
307: return utdepth[c];
308: }
309:
310: /**
311: * Apply inverse component transformation associated with the current
312: * tile. If no component transformation has been requested by the user,
313: * data are not modified.
314: *
315: * <P>This method calls the getInternCompData() method, but respects the
316: * definitions of the getCompData() method defined in the BlkImgDataSrc
317: * interface.
318: *
319: * @param blk Determines the rectangular area to return, and the
320: * data is returned in this object.
321: *
322: * @param c Index of the output component.
323: *
324: * @return The requested DataBlk
325: *
326: * @see BlkImgDataSrc#getCompData
327: * */
328: public DataBlk getCompData(DataBlk blk, int c) {
329: // If requesting a component whose index is greater than 3 or there is
330: // no transform return a copy of data (getInternCompData returns the
331: // actual data in those cases)
332: if (c >= 3 || transfType == NONE) {
333: return src.getCompData(blk, c);
334: } else { // We can use getInternCompData (since data is a copy anyways)
335: return getInternCompData(blk, c);
336: }
337: }
338:
339: /**
340: * Apply the inverse component transformation associated with the current
341: * tile. If no component transformation has been requested by the user,
342: * data are not modified. Else, appropriate method is called (invRCT or
343: * invICT).
344: *
345: * @see #invRCT
346: *
347: * @see #invICT
348: *
349: * @param blk Determines the rectangular area to return.
350: *
351: * @param c Index of the output component.
352: *
353: * @return The requested DataBlk
354: * */
355: public DataBlk getInternCompData(DataBlk blk, int c) {
356: // if specified in the command line that no component transform should
357: // be made, return original data
358: if (noCompTransf)
359: return src.getInternCompData(blk, c);
360:
361: switch (transfType) {
362: case NONE:
363: return src.getInternCompData(blk, c);
364: case INV_RCT:
365: return invRCT(blk, c);
366: case INV_ICT:
367: return invICT(blk, c);
368: default:
369: throw new IllegalArgumentException("Non JPEG 2000 part I"
370: + " component transformation");
371: }
372: }
373:
374: /**
375: * Apply inverse component transformation to obtain requested component
376: * from specified block of data. Whatever the type of requested DataBlk,
377: * it always returns a DataBlkInt.
378: *
379: * @param blk Determine the rectangular area to return
380: *
381: * @param c The index of the requested component
382: *
383: * @return Data of requested component
384: * */
385: private DataBlk invRCT(DataBlk blk, int c) {
386: // If the component number is three or greater, return original data
387: if (c >= 3 && c < getNumComps()) {
388: // Requesting a component whose index is greater than 3
389: return src.getInternCompData(blk, c);
390: }
391:
392: // If asking a component for the first time for this block,
393: // do transform for the 3 components
394: if ((outdata[c] == null) || (dbi.ulx > blk.ulx)
395: || (dbi.uly > blk.uly)
396: || (dbi.ulx + dbi.w < blk.ulx + blk.w)
397: || (dbi.uly + dbi.h < blk.uly + blk.h)) {
398: int k, k0, k1, k2, mink, i;
399: int w = blk.w; //width of output block
400: int h = blk.h; //height of ouput block
401:
402: //Reference to output block data array
403: outdata[c] = (int[]) blk.getData();
404:
405: //Create data array of blk if necessary
406: if (outdata[c] == null || outdata[c].length != h * w) {
407: outdata[c] = new int[h * w];
408: blk.setData(outdata[c]);
409: }
410:
411: outdata[(c + 1) % 3] = new int[outdata[c].length];
412: outdata[(c + 2) % 3] = new int[outdata[c].length];
413:
414: if (block0 == null
415: || block0.getDataType() != DataBlk.TYPE_INT)
416: block0 = new DataBlkInt();
417: if (block1 == null
418: || block1.getDataType() != DataBlk.TYPE_INT)
419: block1 = new DataBlkInt();
420: if (block2 == null
421: || block2.getDataType() != DataBlk.TYPE_INT)
422: block2 = new DataBlkInt();
423: block0.w = block1.w = block2.w = blk.w;
424: block0.h = block1.h = block2.h = blk.h;
425: block0.ulx = block1.ulx = block2.ulx = blk.ulx;
426: block0.uly = block1.uly = block2.uly = blk.uly;
427:
428: int data0[], data1[], data2[]; // input data arrays
429:
430: // Fill in buffer blocks (to be read only)
431: // Returned blocks may have different size and position
432: block0 = (DataBlkInt) src.getInternCompData(block0, 0);
433: data0 = (int[]) block0.getData();
434: block1 = (DataBlkInt) src.getInternCompData(block1, 1);
435: data1 = (int[]) block1.getData();
436: block2 = (DataBlkInt) src.getInternCompData(block2, 2);
437: data2 = (int[]) block2.getData();
438:
439: // Set the progressiveness of the output data
440: blk.progressive = block0.progressive || block1.progressive
441: || block2.progressive;
442: blk.offset = 0;
443: blk.scanw = w;
444:
445: // set attributes of the DataBlk used for buffering
446: dbi.progressive = blk.progressive;
447: dbi.ulx = blk.ulx;
448: dbi.uly = blk.uly;
449: dbi.w = blk.w;
450: dbi.h = blk.h;
451:
452: // Perform conversion
453:
454: // Initialize general indexes
455: k = w * h - 1;
456: k0 = block0.offset + (h - 1) * block0.scanw + w - 1;
457: k1 = block1.offset + (h - 1) * block1.scanw + w - 1;
458: k2 = block2.offset + (h - 1) * block2.scanw + w - 1;
459:
460: for (i = h - 1; i >= 0; i--) {
461: for (mink = k - w; k > mink; k--, k0--, k1--, k2--) {
462: outdata[1][k] = (data0[k0] - ((data1[k1] + data2[k2]) >> 2));
463: outdata[0][k] = data2[k2] + outdata[1][k];
464: outdata[2][k] = data1[k1] + outdata[1][k];
465: }
466: // Jump to beggining of previous line in input
467: k0 -= block0.scanw - w;
468: k1 -= block1.scanw - w;
469: k2 -= block2.scanw - w;
470: }
471: outdata[c] = null;
472: } else if ((c >= 0) && (c <= 3)) { //Asking for the 2nd or 3rd block component
473: blk.setData(outdata[c]);
474: blk.progressive = dbi.progressive;
475: blk.offset = (blk.uly - dbi.uly) * dbi.w + blk.ulx
476: - dbi.ulx;
477: blk.scanw = dbi.w;
478: outdata[c] = null;
479: } else {
480: // Requesting a non valid component index
481: throw new IllegalArgumentException();
482: }
483: return blk;
484: }
485:
486: /**
487: * Apply inverse irreversible component transformation to obtain requested
488: * component from specified block of data. Whatever the type of requested
489: * DataBlk, it always returns a DataBlkFloat.
490: *
491: * @param blk Determine the rectangular area to return
492: *
493: * @param c The index of the requested component
494: *
495: * @return Data of requested component
496: * */
497: private DataBlk invICT(DataBlk blk, int c) {
498: if (c >= 3 && c < getNumComps()) {
499: // Requesting a component whose index is greater than 3
500: int k, k0, k1, k2, mink, i;
501: int w = blk.w; //width of output block
502: int h = blk.h; //height of ouput block
503:
504: int outdata[]; // array of output data
505:
506: //Reference to output block data array
507: outdata = (int[]) blk.getData();
508:
509: //Create data array of blk if necessary
510: if (outdata == null) {
511: outdata = new int[h * w];
512: blk.setData(outdata);
513: }
514:
515: // Variables
516: DataBlkFloat indb = new DataBlkFloat(blk.ulx, blk.uly, w, h);
517: float indata[]; // input data array
518:
519: // Get the input data
520: // (returned block may be larger than requested one)
521: src.getInternCompData(indb, c);
522: indata = (float[]) indb.getData();
523:
524: // Copy the data converting from int to int
525: k = w * h - 1;
526: k0 = indb.offset + (h - 1) * indb.scanw + w - 1;
527: for (i = h - 1; i >= 0; i--) {
528: for (mink = k - w; k > mink; k--, k0--) {
529: outdata[k] = (int) (indata[k0]);
530: }
531: // Jump to beggining of previous line in input
532: k0 -= indb.scanw - w;
533: }
534:
535: // Set the progressivity and offset
536: blk.progressive = indb.progressive;
537: blk.offset = 0;
538: blk.scanw = w;
539: }
540:
541: // If asking a component for the first time for this block,
542: // do transform for the 3 components
543: else if ((outdata[c] == null) || (dbi.ulx > blk.ulx)
544: || (dbi.uly > blk.uly)
545: || (dbi.ulx + dbi.w < blk.ulx + blk.w)
546: || (dbi.uly + dbi.h < blk.uly + blk.h)) {
547: int k, k0, k1, k2, mink, i;
548: int w = blk.w; //width of output block
549: int h = blk.h; //height of ouput block
550:
551: //Reference to output block data array
552: outdata[c] = (int[]) blk.getData();
553:
554: //Create data array of blk if necessary
555: if (outdata[c] == null || outdata[c].length != w * h) {
556: outdata[c] = new int[h * w];
557: blk.setData(outdata[c]);
558: }
559:
560: outdata[(c + 1) % 3] = new int[outdata[c].length];
561: outdata[(c + 2) % 3] = new int[outdata[c].length];
562:
563: if (block0 == null
564: || block0.getDataType() != DataBlk.TYPE_FLOAT)
565: block0 = new DataBlkFloat();
566: if (block2 == null
567: || block2.getDataType() != DataBlk.TYPE_FLOAT)
568: block2 = new DataBlkFloat();
569: if (block1 == null
570: || block1.getDataType() != DataBlk.TYPE_FLOAT)
571: block1 = new DataBlkFloat();
572: block0.w = block2.w = block1.w = blk.w;
573: block0.h = block2.h = block1.h = blk.h;
574: block0.ulx = block2.ulx = block1.ulx = blk.ulx;
575: block0.uly = block2.uly = block1.uly = blk.uly;
576:
577: float data0[], data1[], data2[]; // input data arrays
578:
579: // Fill in buffer blocks (to be read only)
580: // Returned blocks may have different size and position
581: block0 = (DataBlkFloat) src.getInternCompData(block0, 0);
582: data0 = (float[]) block0.getData();
583: block2 = (DataBlkFloat) src.getInternCompData(block2, 1);
584: data2 = (float[]) block2.getData();
585: block1 = (DataBlkFloat) src.getInternCompData(block1, 2);
586: data1 = (float[]) block1.getData();
587:
588: // Set the progressiveness of the output data
589: blk.progressive = block0.progressive || block1.progressive
590: || block2.progressive;
591: blk.offset = 0;
592: blk.scanw = w;
593:
594: // set attributes of the DataBlk used for buffering
595: dbi.progressive = blk.progressive;
596: dbi.ulx = blk.ulx;
597: dbi.uly = blk.uly;
598: dbi.w = blk.w;
599: dbi.h = blk.h;
600:
601: //Perform conversion
602:
603: // Initialize general indexes
604: k = w * h - 1;
605: k0 = block0.offset + (h - 1) * block0.scanw + w - 1;
606: k2 = block2.offset + (h - 1) * block2.scanw + w - 1;
607: k1 = block1.offset + (h - 1) * block1.scanw + w - 1;
608:
609: for (i = h - 1; i >= 0; i--) {
610: for (mink = k - w; k > mink; k--, k0--, k2--, k1--) {
611: outdata[0][k] = (int) (data0[k0] + 1.402f
612: * data1[k1] + 0.5f);
613: outdata[1][k] = (int) (data0[k0] - 0.34413f
614: * data2[k2] - 0.71414f * data1[k1] + 0.5f);
615: outdata[2][k] = (int) (data0[k0] + 1.772f
616: * data2[k2] + 0.5f);
617: }
618: // Jump to beggining of previous line in input
619: k0 -= block0.scanw - w;
620: k2 -= block2.scanw - w;
621: k1 -= block1.scanw - w;
622: }
623: outdata[c] = null;
624: } else if ((c >= 0) && (c <= 3)) {//Asking for the 2nd or 3rd block component
625: blk.setData(outdata[c]);
626: blk.progressive = dbi.progressive;
627: blk.offset = (blk.uly - dbi.uly) * dbi.w + blk.ulx
628: - dbi.ulx;
629: blk.scanw = dbi.w;
630: outdata[c] = null;
631: } else {
632: // Requesting a non valid component index
633: throw new IllegalArgumentException();
634: }
635: return blk;
636: }
637:
638: /**
639: * Changes the current tile, given the new indexes. An
640: * IllegalArgumentException is thrown if the indexes do not
641: * correspond to a valid tile.
642: *
643: * <P>This default implementation changes the tile in the source
644: * and re-initializes properly component transformation variables..
645: *
646: * @param x The horizontal index of the tile.
647: *
648: * @param y The vertical index of the new tile.
649: *
650: * */
651: public void setTile(int x, int y) {
652: src.setTile(x, y);
653: tIdx = getTileIdx(); // index of the current tile
654:
655: // initializations
656: if (((Integer) cts.getTileDef(tIdx)).intValue() == NONE)
657: transfType = NONE;
658: else {
659: int nc = src.getNumComps() > 3 ? 3 : src.getNumComps();
660: int rev = 0;
661: for (int c = 0; c < nc; c++)
662: rev += (wfs.isReversible(tIdx, c) ? 1 : 0);
663: if (rev == 3) {
664: // All WT are reversible
665: transfType = INV_RCT;
666: } else if (rev == 0) {
667: // All WT irreversible
668: transfType = INV_ICT;
669: } else {
670: // Error
671: throw new IllegalArgumentException(
672: "Wavelet transformation and "
673: + "component transformation"
674: + " not coherent in tile" + tIdx);
675: }
676: }
677: }
678:
679: /**
680: * Advances to the next tile, in standard scan-line order (by rows
681: * then columns). An NoNextElementException is thrown if the
682: * current tile is the last one (i.e. there is no next tile).
683: *
684: * <P>This default implementation just advances to the next tile
685: * in the source and re-initializes properly component
686: * transformation variables.
687: *
688: * */
689: public void nextTile() {
690: src.nextTile();
691: tIdx = getTileIdx(); // index of the current tile
692:
693: // initializations
694: if (((Integer) cts.getTileDef(tIdx)).intValue() == NONE)
695: transfType = NONE;
696: else {
697: int nc = src.getNumComps() > 3 ? 3 : src.getNumComps();
698: int rev = 0;
699: for (int c = 0; c < nc; c++)
700: rev += (wfs.isReversible(tIdx, c) ? 1 : 0);
701: if (rev == 3) {
702: // All WT are reversible
703: transfType = INV_RCT;
704: } else if (rev == 0) {
705: // All WT irreversible
706: transfType = INV_ICT;
707: } else {
708: // Error
709: throw new IllegalArgumentException(
710: "Wavelet transformation and "
711: + "component transformation"
712: + " not coherent in tile" + tIdx);
713: }
714: }
715: }
716:
717: }
|