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