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.codestream.writer.*;
047import jj2000.j2k.wavelet.analysis.*;
048import jj2000.j2k.quantization.*;
049import jj2000.j2k.wavelet.*;
050import jj2000.j2k.image.*;
051import jj2000.j2k.util.*;
052import jj2000.j2k.roi.*;
053import 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 *  */
075public 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    /**
097     * The constructor of the mask generator. The constructor is called with
098     * the ROI data. This data is stored in arrays that are used to generate
099     * the SubbandRectROIMask trees for each component.
100     *
101     * @param ROIs The ROI info.
102     *
103     * @param maxShift The flag indicating use of Maxshift method.
104     *
105     * @param nrc number of components.
106     * */
107    public RectROIMaskGenerator(ROI[] ROIs, int nrc){
108        super(ROIs, nrc);
109        int nr=ROIs.length;
110        int r,c;
111        nrROIs=new int[nrc];
112        sMasks=new SubbandRectROIMask[nrc];
113
114        // Count number of ROIs per component
115        for(r=nr-1;r>=0;r--){
116            nrROIs[ROIs[r].comp]++;
117        }
118    }
119
120
121    /**
122     * This functions gets a DataBlk the size of the current code-block and
123     * fills this block with the ROI mask.
124     *
125     * <P> In order to get the mask for a particular Subband, the subband tree
126     * is traversed and at each decomposition, the ROI masks are computed. The
127     * roi bondaries for each subband are stored in the SubbandRectROIMask
128     * tree.
129     *
130     * @param db The data block that is to be filled with the mask
131     *
132     * @param sb The root of the subband tree to which db belongs
133     *
134     * @param magbits The max number of magnitude bits in any code-block
135     *
136     * @param c The component for which to get the mask
137     *
138     * @return Whether or not a mask was needed for this tile
139     * */
140    public boolean getROIMask(DataBlkInt db, Subband sb, int magbits, int c){
141        int x = db.ulx;
142        int y = db.uly;
143        int w = db.w;
144        int h = db.h;
145        int[] mask = db.getDataInt();
146        int i,j,k,r,mink,minj,maxk,maxj;
147        int ulx=0,uly=0,lrx=0,lry=0;
148        int wrap;
149        int maxROI;
150        int[] culxs;
151        int[] culys;
152        int[] clrxs;
153        int[] clrys;
154        SubbandRectROIMask srm;
155
156        // If the ROI bounds have not been calculated for this tile and
157        // component, do so now.
158        if(!tileMaskMade[c]){
159            makeMask(sb,magbits,c);
160            tileMaskMade[c] = true;
161        }
162
163        if(!roiInTile) {
164            return false;
165        }
166
167        // Find relevant subband mask and get ROI bounds
168        srm = (SubbandRectROIMask)sMasks[c].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 ) ||
265                    lrx < tileulx || 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        }
289        else {
290            roiInTile=true;
291        }
292        sMasks[n]=new SubbandRectROIMask(sb,ulxs,ulys,lrxs,lrys,nr);
293    }
294}
295
296
297
298
299