001: /*
002: * $RCSfile: RectROIMaskGenerator.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:23 $
005: * $State: Exp $
006: *
007: * Class: RectROIMaskGenerator
008: *
009: * Description: Generates masks when only rectangular ROIs exist
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.roi.encoder;
045:
046: import jj2000.j2k.codestream.writer.*;
047: import jj2000.j2k.wavelet.analysis.*;
048: import jj2000.j2k.quantization.*;
049: import jj2000.j2k.wavelet.*;
050: import jj2000.j2k.image.*;
051: import jj2000.j2k.util.*;
052: import jj2000.j2k.roi.*;
053: import jj2000.j2k.roi.*;
054:
055: /**
056: * This class generates the ROI masks when there are only rectangular ROIs in
057: * the image. The ROI mask generation can then be simplified by only
058: * calculating the boundaries of the ROI mask in the particular subbands
059: *
060: * <P>The values are calculated from the scaling factors of the ROIs. The
061: * values with which to scale are equal to u-umin where umin is the lowest
062: * scaling factor within the block. The umin value is sent to the entropy
063: * coder to be used for scaling the distortion values.
064: *
065: * <P> To generate and to store the boundaries of the ROIs, the class
066: * SubbandRectROIMask is used. There is one tree of SubbandMasks for each
067: * component.
068: *
069: * @see SubbandRectROIMask
070: *
071: * @see ROIMaskGenerator
072: *
073: * @see ArbROIMaskGenerator
074: * */
075: public class RectROIMaskGenerator extends ROIMaskGenerator {
076:
077: /** The upper left xs of the ROIs*/
078: private int[] ulxs;
079:
080: /** The upper left ys of the ROIs*/
081: private int[] ulys;
082:
083: /** The lower right xs of the ROIs*/
084: private int[] lrxs;
085:
086: /** The lower right ys of the ROIs*/
087: private int[] lrys;
088:
089: /** Number of ROIs */
090: private int nrROIs[];
091:
092: /** The tree of subbandmask. One for each component */
093: private SubbandRectROIMask[] sMasks;
094:
095: /**
096: * The constructor of the mask generator. The constructor is called with
097: * the ROI data. This data is stored in arrays that are used to generate
098: * the SubbandRectROIMask trees for each component.
099: *
100: * @param ROIs The ROI info.
101: *
102: * @param maxShift The flag indicating use of Maxshift method.
103: *
104: * @param nrc number of components.
105: * */
106: public RectROIMaskGenerator(ROI[] ROIs, int nrc) {
107: super (ROIs, nrc);
108: int nr = ROIs.length;
109: int r, c;
110: nrROIs = new int[nrc];
111: sMasks = new SubbandRectROIMask[nrc];
112:
113: // Count number of ROIs per component
114: for (r = nr - 1; r >= 0; r--) {
115: nrROIs[ROIs[r].comp]++;
116: }
117: }
118:
119: /**
120: * This functions gets a DataBlk the size of the current code-block and
121: * fills this block with the ROI mask.
122: *
123: * <P> In order to get the mask for a particular Subband, the subband tree
124: * is traversed and at each decomposition, the ROI masks are computed. The
125: * roi bondaries for each subband are stored in the SubbandRectROIMask
126: * tree.
127: *
128: * @param db The data block that is to be filled with the mask
129: *
130: * @param sb The root of the subband tree to which db belongs
131: *
132: * @param magbits The max number of magnitude bits in any code-block
133: *
134: * @param c The component for which to get the mask
135: *
136: * @return Whether or not a mask was needed for this tile
137: * */
138: public boolean getROIMask(DataBlkInt db, Subband sb, int magbits,
139: int c) {
140: int x = db.ulx;
141: int y = db.uly;
142: int w = db.w;
143: int h = db.h;
144: int[] mask = db.getDataInt();
145: int i, j, k, r, mink, minj, maxk, maxj;
146: int ulx = 0, uly = 0, lrx = 0, lry = 0;
147: int wrap;
148: int maxROI;
149: int[] culxs;
150: int[] culys;
151: int[] clrxs;
152: int[] clrys;
153: SubbandRectROIMask srm;
154:
155: // If the ROI bounds have not been calculated for this tile and
156: // component, do so now.
157: if (!tileMaskMade[c]) {
158: makeMask(sb, magbits, c);
159: tileMaskMade[c] = true;
160: }
161:
162: if (!roiInTile) {
163: return false;
164: }
165:
166: // Find relevant subband mask and get ROI bounds
167: srm = (SubbandRectROIMask) sMasks[c]
168: .getSubbandRectROIMask(x, y);
169: culxs = srm.ulxs;
170: culys = srm.ulys;
171: clrxs = srm.lrxs;
172: clrys = srm.lrys;
173: maxROI = culxs.length - 1;
174: // Make sure that only parts of ROIs within the code-block are used
175: // and make the bounds local to this block the LR bounds are counted
176: // as the distance from the lower right corner of the block
177: x -= srm.ulx;
178: y -= srm.uly;
179: for (r = maxROI; r >= 0; r--) {
180: ulx = culxs[r] - x;
181: if (ulx < 0) {
182: ulx = 0;
183: } else if (ulx >= w) {
184: ulx = w;
185: }
186:
187: uly = culys[r] - y;
188: if (uly < 0) {
189: uly = 0;
190: } else if (uly >= h) {
191: uly = h;
192: }
193:
194: lrx = clrxs[r] - x;
195: if (lrx < 0) {
196: lrx = -1;
197: } else if (lrx >= w) {
198: lrx = w - 1;
199: }
200:
201: lry = clrys[r] - y;
202: if (lry < 0) {
203: lry = -1;
204: } else if (lry >= h) {
205: lry = h - 1;
206: }
207:
208: // Add the masks of the ROI
209: i = w * lry + lrx;
210: maxj = (lrx - ulx);
211: wrap = w - maxj - 1;
212: maxk = lry - uly;
213:
214: for (k = maxk; k >= 0; k--) {
215: for (j = maxj; j >= 0; j--, i--)
216: mask[i] = magbits;
217: i -= wrap;
218: }
219: }
220: return true;
221: }
222:
223: /**
224: * This function returns the relevant data of the mask generator
225: * */
226: public String toString() {
227: return ("Fast rectangular ROI mask generator");
228: }
229:
230: /**
231: * This function generates the ROI mask for the entire tile. The mask is
232: * generated for one component. This method is called once for each tile
233: * and component.
234: *
235: * @param sb The root of the subband tree used in the decomposition
236: *
237: * @param n component number
238: * */
239: public void makeMask(Subband sb, int magbits, int n) {
240: int nr = nrROIs[n];
241: int r;
242: int ulx, uly, lrx, lry;
243: int tileulx = sb.ulcx;
244: int tileuly = sb.ulcy;
245: int tilew = sb.w;
246: int tileh = sb.h;
247: ROI[] ROIs = rois; // local copy
248:
249: ulxs = new int[nr];
250: ulys = new int[nr];
251: lrxs = new int[nr];
252: lrys = new int[nr];
253:
254: nr = 0;
255:
256: for (r = ROIs.length - 1; r >= 0; r--) {
257: if (ROIs[r].comp == n) {
258: ulx = ROIs[r].ulx;
259: uly = ROIs[r].uly;
260: lrx = ROIs[r].w + ulx - 1;
261: lry = ROIs[r].h + uly - 1;
262:
263: if (ulx > (tileulx + tilew - 1)
264: || uly > (tileuly + tileh - 1) || lrx < tileulx
265: || lry < tileuly) // no part of ROI in tile
266: continue;
267:
268: // Check bounds
269: ulx -= tileulx;
270: lrx -= tileulx;
271: uly -= tileuly;
272: lry -= tileuly;
273:
274: ulx = (ulx < 0) ? 0 : ulx;
275: uly = (uly < 0) ? 0 : uly;
276: lrx = (lrx > (tilew - 1)) ? tilew - 1 : lrx;
277: lry = (lry > (tileh - 1)) ? tileh - 1 : lry;
278:
279: ulxs[nr] = ulx;
280: ulys[nr] = uly;
281: lrxs[nr] = lrx;
282: lrys[nr] = lry;
283: nr++;
284: }
285: }
286: if (nr == 0) {
287: roiInTile = false;
288: } else {
289: roiInTile = true;
290: }
291: sMasks[n] = new SubbandRectROIMask(sb, ulxs, ulys, lrxs, lrys,
292: nr);
293: }
294: }
|