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