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