001/* 002 * $RCSfile: CBlkRateDistStats.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:07 $ 005 * $State: Exp $ 006 * 007 * Class: CBlkRateDistStats 008 * 009 * Description: The coded (compressed) code-block with 010 * rate-distortion statistics. 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 * */ 045package jj2000.j2k.entropy.encoder; 046 047import jj2000.j2k.entropy.CodedCBlk; 048import jj2000.j2k.wavelet.analysis.SubbandAn; 049 050/** 051 * This class stores coded (compressed) code-blocks with their associated 052 * rate-distortion statistics. This object should always contain all the 053 * compressed data of the code-block. It is applicable to the encoder engine 054 * only. Some data of the coded-block is stored in the super class, see 055 * CodedCBlk. 056 * 057 * <P>The rate-distortion statistics (i.e. R-D slope) is stored for valid 058 * points only. The set of valid points is determined by the entropy coder 059 * engine itself. Normally they are selected so as to lye in a convex hull, 060 * which can be achived by using the 'selectConvexHull' method of this class, 061 * but some other strategies might be employed. 062 * 063 * <P>The rate (in bytes) for each truncation point (valid or not) is stored 064 * in the 'truncRates' array. The rate of a truncation point is the total 065 * number of bytes in 'data' (see super class) that have to be decoded to 066 * reach the truncation point. 067 * 068 * <P>The slope (reduction of distortion divided by the increase in rate) at 069 * each of the valid truncation points is stored in 'truncSlopes'. 070 * 071 * <P>The index of each valid truncation point is stored in 'truncIdxs'. The 072 * index should be interpreted in the following way: a valid truncation point 073 * at position 'n' has the index 'truncIdxs[n]', the rate 074 * 'truncRates[truncIdxs[n]]' and the slope 'truncSlopes[n]'. The arrays 075 * 'truncIdxs' and 'truncRates' have at least 'nVldTrunc' elements. The 076 * 'truncRates' array has at least 'nTotTrunc' elements. 077 * 078 * <P>In addition the 'isTermPass' array contains a flag for each truncation 079 * point (valid and non-valid ones) that tells if the pass is terminated or 080 * not. If this variable is null then it means that no pass is terminated, 081 * except the last one which always is. 082 * 083 * <P>The compressed data is stored in the 'data' member variable of the super 084 * class. 085 * 086 * @see CodedCBlk 087 * */ 088public class CBlkRateDistStats extends CodedCBlk { 089 090 /** The subband to which the code-block belongs */ 091 public SubbandAn sb; 092 093 /** The total number of truncation points */ 094 public int nTotTrunc; 095 096 /** The number of valid truncation points */ 097 public int nVldTrunc; 098 099 /** The rate (in bytes) for each truncation point (valid and non-valid 100 * ones) */ 101 public int truncRates[]; 102 103 /** The distortion for each truncation point (valid and non-valid ones) */ 104 public double truncDists[]; 105 106 /** The negative of the rate-distortion slope for each valid truncation 107 point */ 108 public float truncSlopes[]; 109 110 /** The indices of the valid truncation points, in increasing 111 * order. */ 112 public int truncIdxs[]; 113 114 /** Array of flags indicating terminated passes (valid or non-valid 115 * truncation points). */ 116 public boolean isTermPass[]; 117 118 /** The number of ROI coefficients in the code-block */ 119 public int nROIcoeff = 0; 120 121 /** Number of ROI coding passes */ 122 public int nROIcp = 0; 123 124 /** 125 * Creates a new CBlkRateDistStats object without allocating any space for 126 * 'truncRates', 'truncSlopes', 'truncDists' and 'truncIdxs' or 'data'. 127 * */ 128 public CBlkRateDistStats() { 129 } 130 131 /** 132 * Creates a new CBlkRateDistStats object and initializes the valid 133 * truncation points, their rates and their slopes, from the 'rates' and 134 * 'dist' arrays. The 'rates', 'dist' and 'termp' arrays must contain the 135 * rate (in bytes), the reduction in distortion (from nothing coded) and 136 * the flag indicating if termination is used, respectively, for each 137 * truncation point. 138 * 139 * <P>The valid truncation points are selected by taking them as lying on 140 * a convex hull. This is done by calling the method selectConvexHull(). 141 * 142 * <P> Note that the arrays 'rates' and 'termp' are copied, not 143 * referenced, so they can be modified after a call to this constructor. 144 * 145 * @param m The horizontal index of the code-block, within the subband. 146 * 147 * @param n The vertical index of the code-block, within the subband. 148 * 149 * @param skipMSBP The number of skipped most significant bit-planes for 150 * this code-block. 151 * 152 * @param data The compressed data. This array is referenced by this 153 * object so it should not be modified after. 154 * 155 * @param rates The rates (in bytes) for each truncation point in the 156 * compressed data. This array is modified by the method but no reference 157 * is kept to it. 158 * 159 * @param dists The reduction in distortion (with respect to no information 160 * coded) for each truncation point. This array is modified by the method 161 * but no reference is kept to it. 162 * 163 * @param termp An array of boolean flags indicating, for each pass, if a 164 * pass is terminated or not (true if terminated). If null then it is 165 * assumed that no pass is terminated except the last one which always is. 166 * 167 * @param np The number of truncation points contained in 'rates', 'dist' 168 * and 'termp'. 169 * 170 * @param inclast If false the convex hull is constructed as for lossy 171 * coding. If true it is constructed as for lossless coding, in which case 172 * it is ensured that all bit-planes are sent (i.e. the last truncation 173 * point is always included). 174 * */ 175 public CBlkRateDistStats(int m, int n, int skipMSBP, byte data[], 176 int rates[], double dists[], boolean termp[], 177 int np, boolean inclast) { 178 super(m,n,skipMSBP,data); 179 selectConvexHull(rates,dists,termp,np,inclast); 180 } 181 182 /** 183 * Compute the rate-distorsion slopes and selects those that lie in a 184 * convex hull. It will compute the slopes, select the ones that form the 185 * convex hull and initialize the 'truncIdxs' and 'truncSlopes' arrays, as 186 * well as 'nVldTrunc', with the selected truncation points. It will also 187 * initialize 'truncRates' and 'isTermPass' arrays, as well as 188 * 'nTotTrunc', with all the truncation points (selected or not). 189 * 190 * <P> Note that the arrays 'rates' and 'termp' are copied, not 191 * referenced, so they can be modified after a call to this method. 192 * 193 * @param rates The rates (in bytes) for each truncation point in the 194 * compressed data. This array is modified by the method. 195 * 196 * @param dists The reduction in distortion (with respect to no 197 * information coded) for each truncation point. This array is modified by 198 * the method. 199 * 200 * @param termp An array of boolean flags indicating, for each pass, if a 201 * pass is terminated or not (true if terminated). If null then it is 202 * assumed that no pass is terminated except the last one which always is. 203 * 204 * @param n The number of truncation points contained in 'rates', 'dist' 205 * and 'termp'. 206 * 207 * @param inclast If false the convex hull is constructed as for lossy 208 * coding. If true it is constructed as for lossless coding, in which case 209 * it is ensured that all bit-planes are sent (i.e. the last truncation 210 * point is always included). 211 * */ 212 public void selectConvexHull(int rates[], double dists[], boolean termp[], 213 int n, boolean inclast) { 214 int first_pnt; // The first point containing some coded data 215 int p; // last selected point 216 int k; // current point 217 int i; // current valid point 218 int npnt; // number of selected (i.e. valid) points 219 int delta_rate; // Rate difference 220 double delta_dist; // Distortion difference 221 float k_slope; // R-D slope for the current point 222 float p_slope; // R-D slope for the last selected point 223 int ll_rate; // Rate for "lossless" coding (i.e. all coded info) 224 225 // Convention: when a negative value is stored in 'rates' it meas an 226 // invalid point. The absolute value is always the rate for that point. 227 228 // Look for first point with some coded info (rate not 0) 229 first_pnt = 0; 230 while (first_pnt < n && rates[first_pnt] <= 0) { 231 first_pnt++; 232 } 233 234 // Select the valid points 235 npnt = n-first_pnt; 236 p_slope = 0f; // To keep compiler happy 237ploop: 238 do { 239 p = -1; 240 for (k=first_pnt; k<n; k++) { 241 if (rates[k] < 0) { // Already invalidated point 242 continue; 243 } 244 // Calculate decrease in distortion and rate 245 if (p >= 0) { 246 delta_rate = rates[k]-rates[p]; 247 delta_dist = dists[k]-dists[p]; 248 } 249 else { // This is with respect to no info coded 250 delta_rate = rates[k]; 251 delta_dist = dists[k]; 252 } 253 // If exactly same distortion don't eliminate if the rates are 254 // equal, otherwise it can lead to infinite slope in lossless 255 // coding. 256 if (delta_dist < 0f || (delta_dist == 0f && delta_rate > 0)) { 257 // This point increases distortion => invalidate 258 rates[k] = -rates[k]; 259 npnt--; 260 continue; // Goto next point 261 } 262 k_slope = (float)(delta_dist/delta_rate); 263 // Check that there is a decrease in distortion, slope is not 264 // infinite (i.e. delta_dist is not 0) and slope is 265 // decreasing. 266 if (p>=0 && 267 (delta_rate <= 0 || k_slope >= p_slope )) { 268 // Last point was not good 269 rates[p] = -rates[p]; // Remove p from valid points 270 npnt--; 271 continue ploop; // Restart from the first one 272 } 273 else { 274 p_slope = k_slope; 275 p = k; 276 } 277 } 278 // If we get to last point we are done 279 break; 280 } while (true); // We end the loop with the break statement 281 282 // If in lossless mode make sure we don't eliminate any last bit-planes 283 // from being sent. 284 if (inclast && n > 0 && rates[n-1] < 0) { 285 rates[n-1] = -rates[n-1]; 286 // This rate can never be equal to any previous selected rate, 287 // given the selection algorithm above, so no problem arises of 288 // infinite slopes. 289 npnt++; 290 } 291 292 // Initialize the arrays of this object 293 nTotTrunc = n; 294 nVldTrunc = npnt; 295 truncRates = new int[n]; 296 truncDists = new double[n]; 297 truncSlopes = new float[npnt]; 298 truncIdxs = new int[npnt]; 299 if (termp != null) { 300 isTermPass = new boolean[n]; 301 System.arraycopy(termp,0,isTermPass,0,n); 302 } 303 else { 304 isTermPass = null; 305 } 306 System.arraycopy(rates,0,truncRates,0,n); 307 for (k=first_pnt, p=-1, i=0; k<n; k++) { 308 if (rates[k]>0) { // A valid point 309 truncDists[k] = dists[k]; 310 if (p<0) { // Only arrives at first valid point 311 truncSlopes[i] = (float)(dists[k]/rates[k]); 312 } 313 else { 314 truncSlopes[i] = (float)((dists[k]-dists[p])/ 315 (rates[k]-rates[p])); 316 } 317 truncIdxs[i] = k; 318 i++; 319 p = k; 320 } 321 else { 322 truncDists[k] = -1; 323 truncRates[k] = -truncRates[k]; 324 } 325 } 326 } 327 328 /** 329 * Returns the contents of the object in a string. This is used for 330 * debugging. 331 * 332 * @return A string with the contents of the object 333 * */ 334 public String toString() { 335 return super.toString() + 336 "\n nVldTrunc = "+nVldTrunc+", nTotTrunc="+nTotTrunc+", num. ROI"+ 337 " coeff="+nROIcoeff+", num. ROI coding passes="+nROIcp; 338 } 339}