001: /*
002: * $RCSfile: ROIDeScaler.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:21 $
005: * $State: Exp $
006: *
007: *
008: * Class: ROIDeScaler
009: *
010: * Description: The class taking care of de-scaling ROI coeffs.
011: *
012: *
013: *
014: * COPYRIGHT:
015: *
016: * This software module was originally developed by Raphaël Grosbois and
017: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
018: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
019: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
020: * Centre France S.A) in the course of development of the JPEG2000
021: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
022: * software module is an implementation of a part of the JPEG 2000
023: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
024: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
025: * Partners) agree not to assert against ISO/IEC and users of the JPEG
026: * 2000 Standard (Users) any of their rights under the copyright, not
027: * including other intellectual property rights, for this software module
028: * with respect to the usage by ISO/IEC and Users of this software module
029: * or modifications thereof for use in hardware or software products
030: * claiming conformance to the JPEG 2000 Standard. Those intending to use
031: * this software module in hardware or software products are advised that
032: * their use may infringe existing patents. The original developers of
033: * this software module, JJ2000 Partners and ISO/IEC assume no liability
034: * for use of this software module or modifications thereof. No license
035: * or right to this software module is granted for non JPEG 2000 Standard
036: * conforming products. JJ2000 Partners have full right to use this
037: * software module for his/her own purpose, assign or donate this
038: * software module to any third party and to inhibit third parties from
039: * using this software module for non JPEG 2000 Standard conforming
040: * products. This copyright notice must be included in all copies or
041: * derivative works of this software module.
042: *
043: * Copyright (c) 1999/2000 JJ2000 Partners.
044: * */
045: package jj2000.j2k.roi;
046:
047: import jj2000.j2k.quantization.dequantizer.*;
048: import jj2000.j2k.codestream.reader.*;
049: import jj2000.j2k.wavelet.synthesis.*;
050: import jj2000.j2k.codestream.*;
051: import jj2000.j2k.entropy.*;
052: import jj2000.j2k.decoder.*;
053: import jj2000.j2k.image.*;
054: import jj2000.j2k.util.*;
055: import jj2000.j2k.io.*;
056: import jj2000.j2k.*;
057:
058: import java.io.*;
059:
060: import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReadParamJava;
061:
062: /**
063: * This class takes care of the de-scaling of ROI coefficients. The de-scaler
064: * works on a tile basis and any mask that is generated is for the current
065: * mask only
066: *
067: * <P>Default implementations of the methods in 'MultiResImgData' are provided
068: * through the 'MultiResImgDataAdapter' abstract class.
069: *
070: * <P>Sign magnitude representation is used (instead of two's complement) for
071: * the output data. The most significant bit is used for the sign (0 if
072: * positive, 1 if negative). Then the magnitude of the quantized coefficient
073: * is stored in the next most significat bits. The most significant magnitude
074: * bit corresponds to the most significant bit-plane and so on.
075: * */
076: public class ROIDeScaler extends MultiResImgDataAdapter implements
077: CBlkQuantDataSrcDec {
078:
079: /** The MaxShiftSpec containing the scaling values for all tile-components
080: * */
081: private MaxShiftSpec mss;
082:
083: /** The prefix for ROI decoder options: 'R' */
084: public final static char OPT_PREFIX = 'R';
085:
086: /** The list of parameters that is accepted by the entropy decoders. They
087: * start with 'R'. */
088: private final static String[][] pinfo = { {
089: "Rno_roi",
090: null,
091: "This argument makes sure that the no ROI de-scaling is performed. "
092: + "Decompression is done like there is no ROI in the image",
093: null }, };
094:
095: /** The entropy decoder from where to get the compressed data (the source)
096: * */
097: private CBlkQuantDataSrcDec src;
098:
099: /**
100: * Constructor of the ROI descaler, takes EntropyDEcoder as source of data
101: * to de-scale.
102: *
103: * @param src The EntropyDecoder that is the source of data.
104: *
105: * @param mss The MaxShiftSpec containing the scaling values for all
106: * tile-components
107: * */
108: public ROIDeScaler(CBlkQuantDataSrcDec src, MaxShiftSpec mss) {
109: super (src);
110: this .src = src;
111: this .mss = mss;
112: }
113:
114: /**
115: * Returns the subband tree, for the specified tile-component. This method
116: * returns the root element of the subband tree structure, see Subband and
117: * SubbandSyn. The tree comprises all the available resolution levels.
118: *
119: * <P>The number of magnitude bits ('magBits' member variable) for each
120: * subband is not initialized.
121: *
122: * @param t The index of the tile, from 0 to T-1.
123: *
124: * @param c The index of the component, from 0 to C-1.
125: *
126: * @return The root of the tree structure.
127: * */
128: public SubbandSyn getSynSubbandTree(int t, int c) {
129: return src.getSynSubbandTree(t, c);
130: }
131:
132: /**
133: * Returns the horizontal code-block partition origin. Allowable values
134: * are 0 and 1, nothing else.
135: * */
136: public int getCbULX() {
137: return src.getCbULX();
138: }
139:
140: /**
141: * Returns the vertical code-block partition origin. Allowable values are
142: * 0 and 1, nothing else.
143: * */
144: public int getCbULY() {
145: return src.getCbULY();
146: }
147:
148: /**
149: * Returns the parameters that are used in this class and implementing
150: * classes. It returns a 2D String array. Each of the 1D arrays is for a
151: * different option, and they have 3 elements. The first element is the
152: * option name, the second one is the synopsis and the third one is a long
153: * description of what the parameter is. The synopsis or description may
154: * be 'null', in which case it is assumed that there is no synopsis or
155: * description of the option, respectively. Null may be returned if no
156: * options are supported.
157: *
158: * @return the options name, their synopsis and their explanation, or null
159: * if no options are supported.
160: * */
161: public static String[][] getParameterInfo() {
162: return pinfo;
163: }
164:
165: /**
166: * Returns the specified code-block in the current tile for the specified
167: * component, as a copy (see below).
168: *
169: * <P>The returned code-block may be progressive, which is indicated by
170: * the 'progressive' variable of the returned 'DataBlk' object. If a
171: * code-block is progressive it means that in a later request to this
172: * method for the same code-block it is possible to retrieve data which is
173: * a better approximation, since meanwhile more data to decode for the
174: * code-block could have been received. If the code-block is not
175: * progressive then later calls to this method for the same code-block
176: * will return the exact same data values.
177: *
178: * <P>The data returned by this method is always a copy of the internal
179: * data of this object, if any, and it can be modified "in place" without
180: * any problems after being returned. The 'offset' of the returned data is
181: * 0, and the 'scanw' is the same as the code-block width. See the
182: * 'DataBlk' class.
183: *
184: * <P>The 'ulx' and 'uly' members of the returned 'DataBlk' object contain
185: * the coordinates of the top-left corner of the block, with respect to
186: * the tile, not the subband.
187: *
188: * @param c The component for which to return the next code-block.
189: *
190: * @param m The vertical index of the code-block to return, in the
191: * specified subband.
192: *
193: * @param n The horizontal index of the code-block to return, in the
194: * specified subband.
195: *
196: * @param sb The subband in which the code-block to return is.
197: *
198: * @param cblk If non-null this object will be used to return the new
199: * code-block. If null a new one will be allocated and returned. If the
200: * "data" array of the object is non-null it will be reused, if possible,
201: * to return the data.
202: *
203: * @return The next code-block in the current tile for component 'n', or
204: * null if all code-blocks for the current tile have been returned.
205: *
206: * @see DataBlk
207: * */
208: public DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb,
209: DataBlk cblk) {
210: return getInternCodeBlock(c, m, n, sb, cblk);
211: }
212:
213: /**
214: * Returns the specified code-block in the current tile for the specified
215: * component (as a reference or copy).
216: *
217: * <P>The returned code-block may be progressive, which is indicated by
218: * the 'progressive' variable of the returned 'DataBlk' object. If a
219: * code-block is progressive it means that in a later request to this
220: * method for the same code-block it is possible to retrieve data which is
221: * a better approximation, since meanwhile more data to decode for the
222: * code-block could have been received. If the code-block is not
223: * progressive then later calls to this method for the same code-block
224: * will return the exact same data values.
225: *
226: * <P>The data returned by this method can be the data in the internal
227: * buffer of this object, if any, and thus can not be modified by the
228: * caller. The 'offset' and 'scanw' of the returned data can be
229: * arbitrary. See the 'DataBlk' class.
230: *
231: * <P>The 'ulx' and 'uly' members of the returned 'DataBlk' object contain
232: * the coordinates of the top-left corner of the block, with respect to
233: * the tile, not the subband.
234: *
235: * @param c The component for which to return the next code-block.
236: *
237: * @param m The vertical index of the code-block to return, in the
238: * specified subband.
239: *
240: * @param n The horizontal index of the code-block to return, in the
241: * specified subband.
242: *
243: * @param sb The subband in which the code-block to return is.
244: *
245: * @param cblk If non-null this object will be used to return the new
246: * code-block. If null a new one will be allocated and returned. If the
247: * "data" array of the object is non-null it will be reused, if possible,
248: * to return the data.
249: *
250: * @return The requested code-block in the current tile for component 'c'.
251: *
252: * @see DataBlk
253: * */
254: public DataBlk getInternCodeBlock(int c, int m, int n,
255: SubbandSyn sb, DataBlk cblk) {
256: int mi, i, j, k, wrap;
257: int ulx, uly, w, h;
258: int[] data; // local copy of quantized data
259: int tmp;
260: int limit;
261:
262: // Get data block from entropy decoder
263: cblk = src.getInternCodeBlock(c, m, n, sb, cblk);
264:
265: // If there are no ROIs in the tile, Or if we already got all blocks
266: boolean noRoiInTile = false;
267: if (mss == null || mss.getTileCompVal(getTileIdx(), c) == null)
268: noRoiInTile = true;
269:
270: if (noRoiInTile || cblk == null) {
271: return cblk;
272: }
273: data = (int[]) cblk.getData();
274: ulx = cblk.ulx;
275: uly = cblk.uly;
276: w = cblk.w;
277: h = cblk.h;
278:
279: // Scale coefficients according to magnitude. If the magnitude of a
280: // coefficient is lower than 2 pow 31-magbits then it is a background
281: // coeff and should be up-scaled
282: int boost = ((Integer) mss.getTileCompVal(getTileIdx(), c))
283: .intValue();
284: int mask = ((1 << sb.magbits) - 1) << (31 - sb.magbits);
285: int mask2 = (~mask) & 0x7FFFFFFF;
286:
287: wrap = cblk.scanw - w;
288: i = cblk.offset + cblk.scanw * (h - 1) + w - 1;
289: for (j = h; j > 0; j--) {
290: for (k = w; k > 0; k--, i--) {
291: tmp = data[i];
292: if ((tmp & mask) == 0) { // BG
293: data[i] = (tmp & 0x80000000) | (tmp << boost);
294: } else { // ROI
295: if ((tmp & mask2) != 0) {
296: // decoded more than magbits bit-planes, set
297: // quantization mid-interval approx. bit just after
298: // the magbits.
299: data[i] = (tmp & (~mask2))
300: | (1 << (30 - sb.magbits));
301: }
302: }
303: }
304: i -= wrap;
305: }
306: return cblk;
307: }
308:
309: /**
310: * Creates a ROIDeScaler object. The information needed to create the
311: * object is the Entropy decoder used and the parameters.
312: *
313: * @param src The source of data that is to be descaled
314: *
315: * @param pl The parameter list (or options).
316: *
317: * @param decSpec The decoding specifications
318: *
319: * @exception IllegalArgumentException If an error occurs while parsing
320: * the options in 'pl'
321: * */
322: public static ROIDeScaler createInstance(CBlkQuantDataSrcDec src,
323: J2KImageReadParamJava j2krparam, DecoderSpecs decSpec) {
324: // Check if no_roi specified in command line or no roi signalled
325: // in bit stream
326: boolean noRoi = j2krparam.getNoROIDescaling();
327: if (noRoi || decSpec.rois == null) {
328: // no_roi specified in commandline!
329: return new ROIDeScaler(src, null);
330: }
331:
332: return new ROIDeScaler(src, decSpec.rois);
333: }
334: }
|