001/* 002 * $RCSfile: PktEncoder.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:03 $ 005 * $State: Exp $ 006 * 007 * Class: PktEncoder 008 * 009 * Description: Builds bit stream packets and keeps 010 * interpacket dependencies. 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 * */ 045 046package jj2000.j2k.codestream.writer; 047import java.awt.Point; 048 049import jj2000.j2k.wavelet.analysis.*; 050import jj2000.j2k.entropy.encoder.*; 051import jj2000.j2k.codestream.*; 052import jj2000.j2k.wavelet.*; 053import jj2000.j2k.image.*; 054import jj2000.j2k.util.*; 055import jj2000.j2k.*; 056 057import java.util.Vector; 058import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; 059/** 060 * This class builds packets and keeps the state information of packet 061 * interdependencies. It also supports saving the state and reverting 062 * (restoring) to the last saved state, with the save() and restore() methods. 063 * 064 * <P>Each time the encodePacket() method is called a new packet is encoded, 065 * the packet header is returned by the method, and the packet body can be 066 * obtained with the getLastBodyBuf() and getLastBodyLen() methods. 067 * */ 068public class PktEncoder { 069 070 /** The prefix for packet encoding options: 'P' */ 071 public final static char OPT_PREFIX = 'P'; 072 073 /** The list of parameters that is accepted for packet encoding.*/ 074 private final static String [][] pinfo = { 075 { "Psop", "[<tile idx>] true|false"+ 076 "[ [<tile idx>] true|false ...]", 077 "Specifies whether start of packet (SOP) markers should be used. "+ 078 "'true' enables, 'false' disables it.","false"}, 079 { "Peph", "[<tile idx>] true|false"+ 080 "[ [<tile idx>] true|false ...]", 081 "Specifies whether end of packet header (EPH) markers should be "+ 082 " used. 'true' enables, 'false' disables it.","false"} 083 }; 084 085 /** The initial value for the lblock */ 086 private final static int INIT_LBLOCK = 3; 087 088 /** The source object */ 089 private CodedCBlkDataSrcEnc infoSrc; 090 091 /** The encoder specs */ 092 J2KImageWriteParamJava wp; 093 094 /** 095 * The tag tree for inclusion information. The indexes are outlined 096 * below. Note that the layer indexes start at 1, therefore, the layer 097 * index minus 1 is used. The subband indices are used as they are defined 098 * in the Subband class. The tile indices start at 0 and follow a 099 * lexicographical order. 100 * 101 * <ul> 102 * <li>1st index: tile index, in lexicographical order</li> 103 * <li>2nd index: component index </li> 104 * <li>3rd index: resolution level </li> 105 * <li>4th index: subband index </li> 106 * <li>5th index: precinct index </li> 107 * </ul> 108 **/ 109 private TagTreeEncoder ttIncl[][][][][]; 110 111 /** 112 * The tag tree for the maximum significant bit-plane. The indexes are 113 * outlined below. Note that the layer indexes start at 1, therefore, the 114 * layer index minus 1 is used. The subband indices are used as they are 115 * defined in the Subband class. The tile indices start at 0 and follow a 116 * lexicographical order. 117 * 118 * <ul> 119 * <li>1st index: tile index, in lexicographical order</li> 120 * <li>2nd index: component index </li> 121 * <li>3rd index: resolution level </li> 122 * <li>4th index: subband index - subband index offset </li> 123 * <li>5th index: precinct index </li> 124 * </ul> 125 * */ 126 private TagTreeEncoder ttMaxBP[][][][][]; 127 128 /** 129 * The base number of bits for sending code-block length information 130 * (referred as Lblock in the JPEG 2000 standard). The indexes are 131 * outlined below. Note that the layer indexes start at 1, therefore, the 132 * layer index minus 1 is used. The subband indices are used as they are 133 * defined in the Subband class. The tile indices start at 0 and follow a 134 * lexicographical order. 135 * 136 * <ul> 137 * <li>1st index: tile index, in lexicographical order </li> 138 * <li>2nd index: component index </li> 139 * <li>3rd index: resolution level </li> 140 * <li>4th index: subband index - subband index offset </li> 141 * <li>5th index: code-block index, in lexicographical order</li> 142 * </ul> 143 * */ 144 private int lblock[][][][][]; 145 146 /** 147 * The last encoded truncation point for each code-block. A negative value 148 * means that no information has been included for the block, yet. The 149 * indexes are outlined below. The subband indices are used as they are 150 * defined in the Subband class. The tile indices start at 0 and follow a 151 * lexicographical order. The code-block indices follow a lexicographical 152 * order within the subband tile. 153 * 154 * <P>What is actually stored is the index of the element in 155 * CBlkRateDistStats.truncIdxs that gives the real truncation point. 156 * 157 * <ul> 158 * <li>1st index: tile index, in lexicographical order </li> 159 * <li>2nd index: component index </li> 160 * <li>3rd index: resolution level </li> 161 * <li>4th index: subband index - subband index offset </li> 162 * <li>5th index: code-block index, in lexicographical order </li> 163 * </ul> 164 * */ 165 private int prevtIdxs[][][][][]; 166 167 /** 168 * The saved base number of bits for sending code-block length 169 * information. It is used for restoring previous saved state by 170 * restore(). The indexes are outlined below. Note that the layer indexes 171 * start at 1, therefore, the layer index minus 1 is used. The subband 172 * indices are used as they are defined in the Subband class. The tile 173 * indices start at 0 and follow a lexicographical order. 174 * 175 * <ul> 176 * <li>1st index: tile index, in lexicographical order </li> 177 * <li>2nd index: component index </li> 178 * <li>3rd index: resolution level </li> 179 * <li>4th index: subband index - subband index offset </li> 180 * <li>5th index: code-block index, in lexicographical order</li> 181 * </ul> 182 * */ 183 private int bak_lblock[][][][][]; 184 185 /** 186 * The saved last encoded truncation point for each code-block. It is used 187 * for restoring previous saved state by restore(). A negative value means 188 * that no information has been included for the block, yet. The indexes 189 * are outlined below. The subband indices are used as they are defined in 190 * the Subband class. The tile indices start at 0 and follow a 191 * lexicographical order. The code-block indices follow a lexicographical 192 * order within the subband tile. 193 * 194 * <ul> 195 * <li>1st index: tile index, in lexicographical order </li> 196 * <li>2nd index: component index </li> 197 * <li>3rd index: resolution level </li> 198 * <li>4th index: subband index - subband index offset </li> 199 * <li>5th index: code-block index, in lexicographical order </li> 200 * </ul> 201 * */ 202 private int bak_prevtIdxs[][][][][]; 203 204 /** The body buffer of the last encoded packet */ 205 private byte[] lbbuf; 206 207 /** The body length of the last encoded packet */ 208 private int lblen; 209 210 /** The saved state */ 211 private boolean saved; 212 213 /** Whether or not there is ROI information in the last encoded Packet */ 214 private boolean roiInPkt = false; 215 216 /** Length to read in current packet body to get all the ROI information */ 217 private int roiLen = 0; 218 219 /** 220 * Array containing the coordinates, width, height, indexes, ... of the 221 * precincts. 222 * 223 * <ul> 224 * <li> 1st dim: tile index.</li> 225 * <li> 2nd dim: component index.</li> 226 * <li> 3rd dim: resolution level index.</li> 227 * <li> 4th dim: precinct index.</li> 228 * </ul> 229 * */ 230 private PrecInfo ppinfo[][][][]; 231 232 /** Whether or not the current packet is writable */ 233 private boolean packetWritable; 234 235 /** 236 * Creates a new packet header encoder, using the information from the 237 * 'infoSrc' object. The information used is the number of components, 238 * number of tiles, subband decomposition, etc. 239 * 240 * <P>Note that this constructor visits all the tiles in the 'infoSrc' 241 * object. The 'infoSrc' object is left at the original tile (i.e. the 242 * current tile before calling this constructor), but any side effects of 243 * visiting the tiles is not reverted. 244 * 245 * @param infoSrc The source of information to construct the 246 * object. 247 * 248 * @param encSpec The parameters for the encoding 249 * 250 * @param maxNumPrec Maximum number of precinct in each tile, component 251 * and resolution level. 252 * 253 * @param pl ParameterList instance that holds command line options 254 * */ 255 public PktEncoder(CodedCBlkDataSrcEnc infoSrc, J2KImageWriteParamJava wp, 256 Point[][][] numPrec) { 257 this.infoSrc = infoSrc; 258 this.wp = wp; 259// this.numPrec = numPrec; 260 261 // Get number of components and tiles 262 int nc = infoSrc.getNumComps(); 263 int nt = infoSrc.getNumTiles(); 264 265 // Do initial allocation 266 ttIncl = new TagTreeEncoder[nt][nc][][][]; 267 ttMaxBP = new TagTreeEncoder[nt][nc][][][]; 268 lblock = new int[nt][nc][][][]; 269 prevtIdxs = new int[nt][nc][][][]; 270 ppinfo = new PrecInfo[nt][nc][][]; 271 272 // Finish allocation 273 SubbandAn root,sb; 274 int maxs,mins; 275 int mrl; 276 Point tmpCoord = null; 277 int numcb; // Number of code-blocks 278 Vector cblks = null; 279 infoSrc.setTile(0,0); 280 for (int t=0; t<nt; t++) { // Loop on tiles 281 for (int c=0; c<nc; c++) { // Loop on components 282 // Get number of resolution levels 283 root = infoSrc.getAnSubbandTree(t,c); 284 mrl = root.resLvl; 285 286 lblock[t][c] = new int[mrl+1][][]; 287 ttIncl[t][c] = new TagTreeEncoder[mrl+1][][]; 288 ttMaxBP[t][c] = new TagTreeEncoder[mrl+1][][]; 289 prevtIdxs[t][c] = new int[mrl+1][][]; 290 ppinfo[t][c] = new PrecInfo[mrl+1][]; 291 292 for(int r=0; r<=mrl; r++) { // Loop on resolution levels 293 mins = (r==0) ? 0 : 1; 294 maxs = (r==0) ? 1 : 4; 295 296 int maxPrec = numPrec[t][c][r].x*numPrec[t][c][r].y; 297 298 ttIncl[t][c][r] = new TagTreeEncoder[maxPrec][maxs]; 299 ttMaxBP[t][c][r] = new TagTreeEncoder[maxPrec][maxs]; 300 prevtIdxs[t][c][r] = new int[maxs][]; 301 lblock[t][c][r] = new int[maxs][]; 302 303 // Precincts and code-blocks 304 ppinfo[t][c][r] = new PrecInfo[maxPrec]; 305 fillPrecInfo(t,c,r); 306 307 for(int s=mins; s<maxs; s++) { 308 // Loop on subbands 309 sb = (SubbandAn)root.getSubbandByIdx(r,s); 310 numcb = sb.numCb.x*sb.numCb.y; 311 312 lblock[t][c][r][s] = new int[numcb]; 313 ArrayUtil.intArraySet(lblock[t][c][r][s],INIT_LBLOCK); 314 315 prevtIdxs[t][c][r][s] = new int[numcb]; 316 ArrayUtil.intArraySet(prevtIdxs[t][c][r][s],-1); 317 } 318 } 319 } 320 if(t!=nt-1) infoSrc.nextTile(); 321 } 322 } 323 324 325 /** 326 * Retrives precincts and code-blocks coordinates in the given resolution, 327 * component and tile. It terminates TagTreeEncoder initialization as 328 * well. 329 * 330 * @param t Tile index. 331 * 332 * @param c Component index. 333 * 334 * @param r Resolution level index. 335 * */ 336 private void fillPrecInfo(int t,int c,int r) { 337 if(ppinfo[t][c][r].length==0) return; // No precinct in this 338 // resolution level 339 340 Point tileI = infoSrc.getTile(null); 341 Point nTiles = infoSrc.getNumTiles(null); 342 343 int x0siz = infoSrc.getImgULX(); 344 int y0siz = infoSrc.getImgULY(); 345 int xsiz = x0siz + infoSrc.getImgWidth(); 346 int ysiz = y0siz + infoSrc.getImgHeight(); 347 int xt0siz = infoSrc.getTilePartULX(); 348 int yt0siz = infoSrc.getTilePartULY(); 349 int xtsiz = infoSrc.getNomTileWidth(); 350 int ytsiz = infoSrc.getNomTileHeight(); 351 352 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 353 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 354 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 355 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 356 357 int xrsiz = infoSrc.getCompSubsX(c); 358 int yrsiz = infoSrc.getCompSubsY(c); 359 360 int tcx0 = (int)Math.ceil(tx0/(double)(xrsiz)); 361 int tcy0 = (int)Math.ceil(ty0/(double)(yrsiz)); 362 int tcx1 = (int)Math.ceil(tx1/(double)(xrsiz)); 363 int tcy1 = (int)Math.ceil(ty1/(double)(yrsiz)); 364 365 int ndl = infoSrc.getAnSubbandTree(t,c).resLvl-r; 366 int trx0 = (int)Math.ceil(tcx0/(double)(1<<ndl)); 367 int try0 = (int)Math.ceil(tcy0/(double)(1<<ndl)); 368 int trx1 = (int)Math.ceil(tcx1/(double)(1<<ndl)); 369 int try1 = (int)Math.ceil(tcy1/(double)(1<<ndl)); 370 371 int cb0x = infoSrc.getCbULX(); 372 int cb0y = infoSrc.getCbULY(); 373 374 double twoppx = (double)wp.getPrecinctPartition().getPPX(t,c,r); 375 double twoppy = (double)wp.getPrecinctPartition().getPPY(t,c,r); 376 int twoppx2 = (int)(twoppx/2); 377 int twoppy2 = (int)(twoppy/2); 378 379 // Precincts are located at (cb0x+i*twoppx,cb0y+j*twoppy) 380 // Valid precincts are those which intersect with the current 381 // resolution level 382 int maxPrec = ppinfo[t][c][r].length; 383 int nPrec = 0; 384 385 int istart = (int)Math.floor((try0-cb0y)/twoppy); 386 int iend = (int)Math.floor((try1-1-cb0y)/twoppy); 387 int jstart = (int)Math.floor((trx0-cb0x)/twoppx); 388 int jend = (int)Math.floor((trx1-1-cb0x)/twoppx); 389 390 int acb0x,acb0y; 391 392 SubbandAn root = infoSrc.getAnSubbandTree(t,c); 393 SubbandAn sb = null; 394 395 int p0x,p0y,p1x,p1y; // Precinct projection in subband 396 int s0x,s0y,s1x,s1y; // Active subband portion 397 int cw,ch; 398 int kstart,kend,lstart,lend,k0,l0; 399 int prg_ulx,prg_uly; 400 int prg_w = (int)twoppx<<ndl; 401 int prg_h = (int)twoppy<<ndl; 402 403 CBlkCoordInfo cb; 404 405 for(int i=istart; i<=iend; i++) { // Vertical precincts 406 for(int j=jstart; j<=jend; j++,nPrec++) { // Horizontal precincts 407 if(j==jstart && (trx0-cb0x)%(xrsiz*((int)twoppx))!=0) { 408 prg_ulx = tx0; 409 } else { 410 prg_ulx = cb0x+j*xrsiz*((int)twoppx<<ndl); 411 } 412 if(i==istart && (try0-cb0y)%(yrsiz*((int)twoppy))!=0) { 413 prg_uly = ty0; 414 } else { 415 prg_uly = cb0y+i*yrsiz*((int)twoppy<<ndl); 416 } 417 418 ppinfo[t][c][r][nPrec] = 419 new PrecInfo(r,(int)(cb0x+j*twoppx),(int)(cb0y+i*twoppy), 420 (int)twoppx,(int)twoppy, 421 prg_ulx,prg_uly,prg_w,prg_h); 422 423 if(r==0) { // LL subband 424 acb0x = cb0x; 425 acb0y = cb0y; 426 427 p0x = acb0x+j*(int)twoppx; 428 p1x = p0x + (int)twoppx; 429 p0y = acb0y+i*(int)twoppy; 430 p1y = p0y + (int)twoppy; 431 432 sb = (SubbandAn)root.getSubbandByIdx(0,0); 433 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 434 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 435 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 436 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 437 438 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 439 cw = sb.nomCBlkW; 440 ch = sb.nomCBlkH; 441 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 442 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 443 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 444 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 445 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 446 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 447 448 if(s1x-s0x<=0 || s1y-s0y<=0) { 449 ppinfo[t][c][r][nPrec].nblk[0] = 0; 450 ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(0,0); 451 ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(0,0); 452 } else { 453 ttIncl[t][c][r][nPrec][0] = 454 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 455 ttMaxBP[t][c][r][nPrec][0] = 456 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 457 ppinfo[t][c][r][nPrec].cblk[0] = 458 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 459 ppinfo[t][c][r][nPrec]. 460 nblk[0] = (kend-kstart+1)*(lend-lstart+1); 461 462 for(int k=kstart; k<=kend; k++) { // Vertical cblks 463 for(int l=lstart; l<=lend; l++) { // Horiz. cblks 464 465 cb = new CBlkCoordInfo(k-k0,l-l0); 466 ppinfo[t][c][r][nPrec]. 467 cblk[0][k-kstart][l-lstart] = cb; 468 } // Horizontal code-blocks 469 } // Vertical code-blocks 470 } 471 } else { // HL, LH and HH subbands 472 // HL subband 473 acb0x = 0; 474 acb0y = cb0y; 475 476 p0x = acb0x+j*twoppx2; 477 p1x = p0x + twoppx2; 478 p0y = acb0y+i*twoppy2; 479 p1y = p0y + twoppy2; 480 481 sb = (SubbandAn)root.getSubbandByIdx(r,1); 482 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 483 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 484 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 485 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 486 487 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 488 cw = sb.nomCBlkW; 489 ch = sb.nomCBlkH; 490 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 491 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 492 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 493 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 494 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 495 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 496 497 if(s1x-s0x<=0 || s1y-s0y<=0) { 498 ppinfo[t][c][r][nPrec].nblk[1] = 0; 499 ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(0,0); 500 ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(0,0); 501 } else { 502 ttIncl[t][c][r][nPrec][1] = 503 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 504 ttMaxBP[t][c][r][nPrec][1] = 505 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 506 ppinfo[t][c][r][nPrec].cblk[1] = 507 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 508 ppinfo[t][c][r][nPrec]. 509 nblk[1] = (kend-kstart+1)*(lend-lstart+1); 510 511 for(int k=kstart; k<=kend; k++) { // Vertical cblks 512 for(int l=lstart; l<=lend; l++) { // Horiz. cblks 513 cb = new CBlkCoordInfo(k-k0,l-l0); 514 ppinfo[t][c][r][nPrec]. 515 cblk[1][k-kstart][l-lstart] = cb; 516 } // Horizontal code-blocks 517 } // Vertical code-blocks 518 } 519 520 // LH subband 521 acb0x = cb0x; 522 acb0y = 0; 523 524 p0x = acb0x+j*twoppx2; 525 p1x = p0x + twoppx2; 526 p0y = acb0y+i*twoppy2; 527 p1y = p0y + twoppy2; 528 529 sb = (SubbandAn)root.getSubbandByIdx(r,2); 530 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 531 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 532 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 533 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 534 535 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 536 cw = sb.nomCBlkW; 537 ch = sb.nomCBlkH; 538 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 539 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 540 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 541 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 542 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 543 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 544 545 if(s1x-s0x<=0 || s1y-s0y<=0) { 546 ppinfo[t][c][r][nPrec].nblk[2] = 0; 547 ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(0,0); 548 ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(0,0); 549 } else { 550 ttIncl[t][c][r][nPrec][2] = 551 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 552 ttMaxBP[t][c][r][nPrec][2] = 553 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 554 ppinfo[t][c][r][nPrec].cblk[2] = 555 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 556 ppinfo[t][c][r][nPrec]. 557 nblk[2] = (kend-kstart+1)*(lend-lstart+1); 558 559 for(int k=kstart; k<=kend; k++) { // Vertical cblks 560 for(int l=lstart; l<=lend; l++) { // Horiz cblks 561 cb = new CBlkCoordInfo(k-k0,l-l0); 562 ppinfo[t][c][r][nPrec]. 563 cblk[2][k-kstart][l-lstart] = cb; 564 } // Horizontal code-blocks 565 } // Vertical code-blocks 566 } 567 568 // HH subband 569 acb0x = 0; 570 acb0y = 0; 571 572 p0x = acb0x+j*twoppx2; 573 p1x = p0x + twoppx2; 574 p0y = acb0y+i*twoppy2; 575 p1y = p0y + twoppy2; 576 577 sb = (SubbandAn)root.getSubbandByIdx(r,3); 578 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 579 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 580 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 581 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 582 583 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 584 cw = sb.nomCBlkW; 585 ch = sb.nomCBlkH; 586 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 587 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 588 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 589 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 590 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 591 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 592 593 if(s1x-s0x<=0 || s1y-s0y<=0) { 594 ppinfo[t][c][r][nPrec].nblk[3] = 0; 595 ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(0,0); 596 ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(0,0); 597 } else { 598 ttIncl[t][c][r][nPrec][3] = 599 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 600 ttMaxBP[t][c][r][nPrec][3] = 601 new TagTreeEncoder(kend-kstart+1,lend-lstart+1); 602 ppinfo[t][c][r][nPrec].cblk[3] = 603 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 604 ppinfo[t][c][r][nPrec]. 605 nblk[3] = (kend-kstart+1)*(lend-lstart+1); 606 607 for(int k=kstart; k<=kend; k++) { // Vertical cblks 608 for(int l=lstart; l<=lend; l++) { // Horiz cblks 609 cb = new CBlkCoordInfo(k-k0,l-l0); 610 ppinfo[t][c][r][nPrec]. 611 cblk[3][k-kstart][l-lstart] = cb; 612 } // Horizontal code-blocks 613 } // Vertical code-blocks 614 } 615 616 } 617 } // Horizontal precincts 618 } // Vertical precincts 619 } 620 621 622 /** 623 * Encodes a packet and returns the buffer containing the encoded packet 624 * header. The code-blocks appear in a 3D array of CBlkRateDistStats, 625 * 'cbs'. The first index is the tile index in lexicographical order, the 626 * second index is the subband index (as defined in the Subband class), 627 * and the third index is the code-block index (whithin the subband tile) 628 * in lexicographical order as well. The indexes of the new truncation 629 * points for each code-block are specified by the 3D array of int 630 * 'tIndx'. The indices of this array are the same as for cbs. The 631 * truncation point indices in 'tIndx' are the indices of the elements of 632 * the 'truncIdxs' array, of the CBlkRateDistStats class, that give the 633 * real truncation points. If a truncation point index is negative it 634 * means that the code-block has not been included in any layer yet. If 635 * the truncation point is less than or equal to the highest truncation 636 * point used in previous layers then the code-block is not included in 637 * the packet. Otherwise, if larger, the code-block is included in the 638 * packet. The body of the packet can be obtained with the 639 * getLastBodyBuf() and getLastBodyLen() methods. 640 * 641 * <p>Layers must be coded in increasing order, in consecutive manner, for 642 * each tile, component and resolution level (e.g., layer 1, then layer 2, 643 * etc.). For different tile, component and/or resolution level no 644 * particular order must be followed.</p> 645 * 646 * @param ly The layer index (starts at 1). 647 * 648 * @param c The component index. 649 * 650 * @param r The resolution level 651 * 652 * @param t Index of the current tile 653 * 654 * @param cbs The 3D array of coded code-blocks. 655 * 656 * @param tIndx The truncation point indices for each code-block. 657 * 658 * @param hbuf The header buffer. If null a new BitOutputBuffer is created 659 * and returned. This buffer is reset before anything is written to it. 660 * 661 * @param bbuf The body buffer. If null a new one is created. If not large 662 * enough a new one is created. 663 * 664 * @param pIdx The precinct index. 665 * 666 * @return The buffer containing the packet header. 667 * */ 668 public BitOutputBuffer encodePacket(int ly,int c,int r,int t, 669 CBlkRateDistStats cbs[][], 670 int tIndx[][],BitOutputBuffer hbuf, 671 byte bbuf[],int pIdx) { 672 int b,i,maxi; 673 int ncb; 674 int thmax; 675 int newtp; 676 int cblen; 677 int prednbits,nbits,deltabits; 678 TagTreeEncoder cur_ttIncl,cur_ttMaxBP; // inclusion and bit-depth tag 679 // trees 680 int cur_prevtIdxs[]; // last encoded truncation points 681 CBlkRateDistStats cur_cbs[]; 682 int cur_tIndx[]; // truncation points to encode 683 int minsb = (r==0) ? 0 : 1; 684 int maxsb = (r==0) ? 1 : 4; 685 Point cbCoord = null; 686 SubbandAn root = infoSrc.getAnSubbandTree(t,c); 687 SubbandAn sb; 688 roiInPkt = false; 689 roiLen = 0; 690 int mend,nend; 691 692 // Checks if a precinct with such an index exists in this resolution 693 // level 694 if(pIdx>=ppinfo[t][c][r].length) { 695 packetWritable = false; 696 return hbuf; 697 } 698 PrecInfo prec = ppinfo[t][c][r][pIdx]; 699 700 // First, we check if packet is empty (i.e precinct 'pIdx' has no 701 // code-block in any of the subbands) 702 boolean isPrecVoid = true; 703 704 for(int s=minsb; s<maxsb; s++) { 705 if(prec.nblk[s]==0) { 706 // The precinct has no code-block in this subband. 707 continue; 708 } else { 709 // The precinct is not empty in at least one subband -> 710 // stop 711 isPrecVoid = false; 712 break; 713 } 714 } 715 716 if(isPrecVoid) { 717 packetWritable = true; 718 719 if(hbuf == null) { 720 hbuf = new BitOutputBuffer(); 721 } else { 722 hbuf.reset(); 723 } 724 if (bbuf == null) { 725 lbbuf = bbuf = new byte[1]; 726 } 727 hbuf.writeBit(0); 728 lblen = 0; 729 730 return hbuf; 731 } 732 733 if(hbuf == null) { 734 hbuf = new BitOutputBuffer(); 735 } else { 736 hbuf.reset(); 737 } 738 739 // Invalidate last body buffer 740 lbbuf = null; 741 lblen = 0; 742 743 // Signal that packet is present 744 hbuf.writeBit(1); 745 746 for(int s=minsb; s<maxsb; s++) { // Loop on subbands 747 sb = (SubbandAn)root.getSubbandByIdx(r,s); 748 749 // Go directly to next subband if the precinct has no code-block 750 // in the current one. 751 if(prec.nblk[s]==0) { 752 continue; 753 } 754 755 cur_ttIncl = ttIncl[t][c][r][pIdx][s]; 756 cur_ttMaxBP = ttMaxBP[t][c][r][pIdx][s]; 757 cur_prevtIdxs = prevtIdxs[t][c][r][s]; 758 cur_cbs = cbs[s]; 759 cur_tIndx = tIndx[s]; 760 761 // Set tag tree values for code-blocks in this precinct 762 mend = (prec.cblk[s]==null) ? 0 : prec.cblk[s].length; 763 for(int m=0; m<mend; m++) { 764 nend = (prec.cblk[s][m]==null) ? 0 : prec.cblk[s][m].length; 765 for (int n=0; n<nend; n++) { 766 cbCoord = prec.cblk[s][m][n].idx; 767 b = cbCoord.x+cbCoord.y*sb.numCb.x; 768 769 if (cur_tIndx[b]>cur_prevtIdxs[b] && cur_prevtIdxs[b]<0) { 770 // First inclusion 771 cur_ttIncl.setValue(m,n,ly-1); 772 } 773 if (ly==1) { // First layer, need to set the skip of MSBP 774 cur_ttMaxBP.setValue(m,n,cur_cbs[b].skipMSBP); 775 } 776 } 777 } 778 779 // Now encode the information 780 for(int m=0; m<prec.cblk[s].length; m++) { // Vertical code-blocks 781 for (int n=0; n<prec.cblk[s][m].length; n++) { // Horiz. cblks 782 cbCoord = prec.cblk[s][m][n].idx; 783 b = cbCoord.x+cbCoord.y*sb.numCb.x; 784 785 // 1) Inclusion information 786 if (cur_tIndx[b]>cur_prevtIdxs[b]) { 787 // Code-block included in this layer 788 if (cur_prevtIdxs[b]<0) { // First inclusion 789 // Encode layer info 790 cur_ttIncl.encode(m,n,ly,hbuf); 791 792 // 2) Max bitdepth info. Encode value 793 thmax = cur_cbs[b].skipMSBP+1; 794 for (i=1; i<=thmax; i++) { 795 cur_ttMaxBP.encode(m,n,i,hbuf); 796 } 797 798 // Count body size for packet 799 lblen += cur_cbs[b]. 800 truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]; 801 } else { // Already in previous layer 802 // Send "1" bit 803 hbuf.writeBit(1); 804 // Count body size for packet 805 lblen += 806 cur_cbs[b]. 807 truncRates[cur_cbs[b]. 808 truncIdxs[cur_tIndx[b]]] - 809 cur_cbs[b]. 810 truncRates[cur_cbs[b]. 811 truncIdxs[cur_prevtIdxs[b]]]; 812 } 813 814 // 3) Truncation point information 815 if (cur_prevtIdxs[b]<0) { 816 newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]]; 817 } else { 818 newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]]- 819 cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]-1; 820 } 821 822 // Mix of switch and if is faster 823 switch (newtp) { 824 case 0: 825 hbuf.writeBit(0); // Send one "0" bit 826 break; 827 case 1: 828 hbuf.writeBits(2,2); // Send one "1" and one "0" 829 break; 830 case 2: 831 case 3: 832 case 4: 833 // Send two "1" bits followed by 2 bits 834 // representation of newtp-2 835 hbuf.writeBits((3<<2)|(newtp-2),4); 836 break; 837 default: 838 if (newtp <= 35) { 839 // Send four "1" bits followed by a five bits 840 // representation of newtp-5 841 hbuf.writeBits((15<<5)|(newtp-5),9); 842 } else if (newtp <= 163) { 843 // Send nine "1" bits followed by a seven bits 844 // representation of newtp-36 845 hbuf.writeBits((511<<7)|(newtp-36),16); 846 } else { 847 throw new 848 ArithmeticException("Maximum number "+ 849 "of truncation "+ 850 "points exceeded"); 851 } 852 } 853 } else { // Block not included in this layer 854 if (cur_prevtIdxs[b]>=0) { 855 // Already in previous layer. Send "0" bit 856 hbuf.writeBit(0); 857 } else { // Not in any previous layers 858 cur_ttIncl.encode(m,n,ly,hbuf); 859 } 860 // Go to the next one. 861 continue; 862 } 863 864 // Code-block length 865 866 // We need to compute the maximum number of bits needed to 867 // signal the length of each terminated segment and the 868 // final truncation point. 869 newtp = 1; 870 maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]]; 871 cblen = (cur_prevtIdxs[b]<0) ? 0 : 872 cur_cbs[b].truncRates[cur_cbs[b]. 873 truncIdxs[cur_prevtIdxs[b]]]; 874 875 // Loop on truncation points 876 i = (cur_prevtIdxs[b]<0) ? 0 : 877 cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]+1; 878 int minbits = 0; 879 for (; i<maxi; i++, newtp++) { 880 // If terminated truncation point calculate length 881 if (cur_cbs[b].isTermPass != null && 882 cur_cbs[b].isTermPass[i]) { 883 884 // Calculate length 885 cblen = cur_cbs[b].truncRates[i] - cblen; 886 887 // Calculate number of needed bits 888 prednbits = lblock[t][c][r][s][b] + 889 MathUtil.log2(newtp); 890 minbits = ((cblen>0) ? MathUtil.log2(cblen) : 0)+1; 891 892 // Update Lblock increment if needed 893 for(int j=prednbits; j<minbits; j++) { 894 lblock[t][c][r][s][b]++; 895 hbuf.writeBit(1); 896 } 897 // Initialize for next length 898 newtp = 0; 899 cblen = cur_cbs[b].truncRates[i]; 900 } 901 } 902 // Last truncation point length always sent 903 904 // Calculate length 905 cblen = cur_cbs[b].truncRates[i] - cblen; 906 907 // Calculate number of bits 908 prednbits = lblock[t][c][r][s][b] + MathUtil.log2(newtp); 909 minbits = ((cblen>0) ? MathUtil.log2(cblen) : 0)+1; 910 // Update Lblock increment if needed 911 for(int j=prednbits; j<minbits; j++) { 912 lblock[t][c][r][s][b]++; 913 hbuf.writeBit(1); 914 } 915 916 // End of comma-code increment 917 hbuf.writeBit(0); 918 919 // There can be terminated several segments, send length 920 // info for all terminated truncation points in addition 921 // to final one 922 newtp = 1; 923 maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]]; 924 cblen = (cur_prevtIdxs[b]<0) ? 0 : 925 cur_cbs[b].truncRates[cur_cbs[b]. 926 truncIdxs[cur_prevtIdxs[b]]]; 927 // Loop on truncation points and count the groups 928 i = (cur_prevtIdxs[b]<0) ? 0 : 929 cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]+1; 930 for (; i<maxi; i++, newtp++) { 931 // If terminated truncation point, send length 932 if (cur_cbs[b].isTermPass != null && 933 cur_cbs[b].isTermPass[i]) { 934 935 cblen = cur_cbs[b].truncRates[i] - cblen; 936 nbits = MathUtil.log2(newtp)+lblock[t][c][r][s][b]; 937 hbuf.writeBits(cblen,nbits); 938 939 // Initialize for next length 940 newtp = 0; 941 cblen = cur_cbs[b].truncRates[i]; 942 } 943 } 944 // Last truncation point length is always signalled 945 // First calculate number of bits needed to signal 946 // Calculate length 947 cblen = cur_cbs[b].truncRates[i] - cblen; 948 nbits = MathUtil.log2(newtp) + lblock[t][c][r][s][b]; 949 hbuf.writeBits(cblen,nbits); 950 951 } // End loop on horizontal code-blocks 952 } // End loop on vertical code-blocks 953 } // End loop on subband 954 955 // -> Copy the data to the body buffer 956 957 // Ensure size for body data 958 if (bbuf==null || bbuf.length<lblen){ 959 bbuf = new byte[lblen]; 960 } 961 lbbuf = bbuf; 962 lblen = 0; 963 964 for (int s=minsb; s<maxsb; s++) { // Loop on subbands 965 sb = (SubbandAn)root.getSubbandByIdx(r,s); 966 967 cur_prevtIdxs = prevtIdxs[t][c][r][s]; 968 cur_cbs = cbs[s]; 969 cur_tIndx = tIndx[s]; 970 ncb = cur_prevtIdxs.length; 971 972 mend = (prec.cblk[s]==null) ? 0 : prec.cblk[s].length; 973 for(int m=0; m<mend; m++) { // Vertical code-blocks 974 nend = (prec.cblk[s][m]==null) ? 0 : prec.cblk[s][m].length; 975 for (int n=0; n<nend; n++) { // Horiz. cblks 976 cbCoord = prec.cblk[s][m][n].idx; 977 b = cbCoord.x+cbCoord.y*sb.numCb.x; 978 979 if (cur_tIndx[b]>cur_prevtIdxs[b]) { 980 981 // Block included in this precinct -> Copy data to 982 // body buffer and get code-size 983 if (cur_prevtIdxs[b]<0) { 984 cblen = cur_cbs[b]. 985 truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]; 986 System.arraycopy(cur_cbs[b].data,0, 987 lbbuf,lblen,cblen); 988 } else { 989 cblen = cur_cbs[b]. 990 truncRates[cur_cbs[b]. 991 truncIdxs[cur_tIndx[b]]] - 992 cur_cbs[b]. 993 truncRates[cur_cbs[b]. 994 truncIdxs[cur_prevtIdxs[b]]]; 995 System. 996 arraycopy(cur_cbs[b].data, 997 cur_cbs[b]. 998 truncRates[cur_cbs[b]. 999 truncIdxs[cur_prevtIdxs 1000 [b]]], 1001 lbbuf,lblen,cblen); 1002 } 1003 lblen += cblen; 1004 1005 // Verifies if this code-block contains new ROI 1006 // information 1007 if(cur_cbs[b].nROIcoeff!=0 && 1008 (cur_prevtIdxs[b]==-1 || 1009 cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] <= 1010 cur_cbs[b].nROIcp-1) ) { 1011 roiInPkt = true; 1012 roiLen = lblen; 1013 } 1014 1015 // Update truncation point 1016 cur_prevtIdxs[b] = cur_tIndx[b]; 1017 } 1018 } // End loop on horizontal code-blocks 1019 } // End loop on vertical code-blocks 1020 } // End loop on subbands 1021 1022 packetWritable = true; 1023 1024 // Must never happen 1025 if(hbuf.getLength()==0) { 1026 throw new Error("You have found a bug in PktEncoder, method:"+ 1027 " encodePacket"); 1028 } 1029 1030 return hbuf; 1031 } 1032 1033 /** 1034 * Returns the buffer of the body of the last encoded packet. The length 1035 * of the body can be retrieved with the getLastBodyLen() method. The 1036 * length of the array returned by this method may be larger than the 1037 * actual body length. 1038 * 1039 * @return The buffer of body of the last encoded packet. 1040 * 1041 * @exception IllegalArgumentException If no packet has been coded since 1042 * last reset(), last restore(), or object creation. 1043 * 1044 * @see #getLastBodyLen 1045 * */ 1046 public byte[] getLastBodyBuf() { 1047 if (lbbuf == null) { 1048 throw new IllegalArgumentException(); 1049 } 1050 return lbbuf; 1051 } 1052 1053 /** 1054 * Returns the length of the body of the last encoded packet, in 1055 * bytes. The body itself can be retrieved with the getLastBodyBuf() 1056 * method. 1057 * 1058 * @return The length of the body of last encoded packet, in bytes. 1059 * 1060 * @see #getLastBodyBuf 1061 * */ 1062 public int getLastBodyLen() { 1063 return lblen; 1064 } 1065 1066 /** 1067 * Saves the current state of this object. The last saved state 1068 * can be restored with the restore() method. 1069 * 1070 * @see #restore 1071 * */ 1072 public void save() { 1073 int maxsbi,minsbi; 1074 1075 // Have we done any save yet? 1076 if (bak_lblock==null) { 1077 // Allocate backup buffers 1078 bak_lblock = new int[ttIncl.length][][][][]; 1079 bak_prevtIdxs = new int[ttIncl.length][][][][]; 1080 for (int t=ttIncl.length-1; t>=0; t--) { 1081 bak_lblock[t] = new int[ttIncl[t].length][][][]; 1082 bak_prevtIdxs[t] = new int[ttIncl[t].length][][][]; 1083 for (int c=ttIncl[t].length-1; c>=0; c--) { 1084 bak_lblock[t][c] = new int[lblock[t][c].length][][]; 1085 bak_prevtIdxs[t][c] = new int[ttIncl[t][c].length][][]; 1086 for (int r=lblock[t][c].length-1; r>=0; r--) { 1087 bak_lblock[t][c][r] = 1088 new int[lblock[t][c][r].length][]; 1089 bak_prevtIdxs[t][c][r] = 1090 new int[prevtIdxs[t][c][r].length][]; 1091 minsbi = (r==0) ? 0 : 1; 1092 maxsbi = (r==0) ? 1 : 4; 1093 for (int s=minsbi; s<maxsbi; s++) { 1094 bak_lblock[t][c][r][s] = 1095 new int[lblock[t][c][r][s].length]; 1096 bak_prevtIdxs[t][c][r][s] = 1097 new int[prevtIdxs[t][c][r][s].length]; 1098 } 1099 } 1100 } 1101 } 1102 } 1103 1104 //-- Save the data 1105 1106 // Use reference caches to minimize array access overhead 1107 TagTreeEncoder 1108 ttIncl_t_c[][][], 1109 ttMaxBP_t_c[][][], 1110 ttIncl_t_c_r[][], 1111 ttMaxBP_t_c_r[][]; 1112 int 1113 lblock_t_c[][][], 1114 bak_lblock_t_c[][][], 1115 prevtIdxs_t_c_r[][], 1116 bak_prevtIdxs_t_c_r[][]; 1117 1118 // Loop on tiles 1119 for (int t=ttIncl.length-1; t>=0; t--) { 1120 // Loop on components 1121 for (int c=ttIncl[t].length-1; c>=0; c--) { 1122 // Initialize reference caches 1123 lblock_t_c = lblock[t][c]; 1124 bak_lblock_t_c = bak_lblock[t][c]; 1125 ttIncl_t_c = ttIncl[t][c]; 1126 ttMaxBP_t_c = ttMaxBP[t][c]; 1127 // Loop on resolution levels 1128 for (int r=lblock_t_c.length-1; r>=0; r--) { 1129 // Initialize reference caches 1130 ttIncl_t_c_r = ttIncl_t_c[r]; 1131 ttMaxBP_t_c_r = ttMaxBP_t_c[r]; 1132 prevtIdxs_t_c_r = prevtIdxs[t][c][r]; 1133 bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r]; 1134 1135 // Loop on subbands 1136 minsbi = (r==0) ? 0 : 1; 1137 maxsbi = (r==0) ? 1 : 4; 1138 for (int s=minsbi; s<maxsbi; s++) { 1139 // Save 'lblock' 1140 System.arraycopy(lblock_t_c[r][s],0, 1141 bak_lblock_t_c[r][s],0, 1142 lblock_t_c[r][s].length); 1143 // Save 'prevtIdxs' 1144 System.arraycopy(prevtIdxs_t_c_r[s],0, 1145 bak_prevtIdxs_t_c_r[s],0, 1146 prevtIdxs_t_c_r[s].length); 1147 } // End loop on subbands 1148 1149 // Loop on precincts 1150 for(int p=ppinfo[t][c][r].length-1; p>=0; p--) { 1151 if(p<ttIncl_t_c_r.length) { 1152 // Loop on subbands 1153 for(int s=minsbi; s<maxsbi; s++) { 1154 ttIncl_t_c_r[p][s].save(); 1155 ttMaxBP_t_c_r[p][s].save(); 1156 } // End loop on subbands 1157 } 1158 } // End loop on precincts 1159 } // End loop on resolutions 1160 } // End loop on components 1161 } // End loop on tiles 1162 1163 // Set the saved state 1164 saved = true; 1165 } 1166 1167 1168 /** 1169 * Restores the last saved state of this object. An 1170 * IllegalArgumentException is thrown if no state has been saved. 1171 * 1172 * @see #save 1173 * */ 1174 public void restore() { 1175 int maxsbi,minsbi; 1176 1177 if (!saved) { 1178 throw new IllegalArgumentException(); 1179 } 1180 1181 // Invalidate last encoded body buffer 1182 lbbuf = null; 1183 1184 //-- Restore tha data 1185 1186 // Use reference caches to minimize array access overhead 1187 TagTreeEncoder ttIncl_t_c[][][],ttMaxBP_t_c[][][],ttIncl_t_c_r[][], 1188 ttMaxBP_t_c_r[][]; 1189 int lblock_t_c[][][],bak_lblock_t_c[][][],prevtIdxs_t_c_r[][], 1190 bak_prevtIdxs_t_c_r[][]; 1191 1192 // Loop on tiles 1193 for (int t=ttIncl.length-1; t>=0; t--) { 1194 // Loop on components 1195 for (int c=ttIncl[t].length-1; c>=0; c--) { 1196 // Initialize reference caches 1197 lblock_t_c = lblock[t][c]; 1198 bak_lblock_t_c = bak_lblock[t][c]; 1199 ttIncl_t_c = ttIncl[t][c]; 1200 ttMaxBP_t_c = ttMaxBP[t][c]; 1201 // Loop on resolution levels 1202 for (int r=lblock_t_c.length-1; r>=0; r--) { 1203 // Initialize reference caches 1204 ttIncl_t_c_r = ttIncl_t_c[r]; 1205 ttMaxBP_t_c_r = ttMaxBP_t_c[r]; 1206 prevtIdxs_t_c_r = prevtIdxs[t][c][r]; 1207 bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r]; 1208 1209 // Loop on subbands 1210 minsbi = (r==0) ? 0 : 1; 1211 maxsbi = (r==0) ? 1 : 4; 1212 for (int s=minsbi; s<maxsbi; s++) { 1213 // Restore 'lblock' 1214 System.arraycopy(bak_lblock_t_c[r][s],0, 1215 lblock_t_c[r][s],0, 1216 lblock_t_c[r][s].length); 1217 // Restore 'prevtIdxs' 1218 System.arraycopy(bak_prevtIdxs_t_c_r[s],0, 1219 prevtIdxs_t_c_r[s],0, 1220 prevtIdxs_t_c_r[s].length); 1221 } // End loop on subbands 1222 1223 // Loop on precincts 1224 for(int p=ppinfo[t][c][r].length-1; p>=0; p--) { 1225 if(p<ttIncl_t_c_r.length) { 1226 // Loop on subbands 1227 for(int s=minsbi; s<maxsbi; s++) { 1228 ttIncl_t_c_r[p][s].restore(); 1229 ttMaxBP_t_c_r[p][s].restore(); 1230 } // End loop on subbands 1231 } 1232 } // End loop on precincts 1233 } // End loop on resolution levels 1234 } // End loop on components 1235 } // End loop on tiles 1236 } 1237 1238 /** 1239 * Resets the state of the object to the initial state, as if the object 1240 * was just created. 1241 * */ 1242 public void reset() { 1243 int maxsbi,minsbi; 1244 1245 // Invalidate save 1246 saved = false; 1247 // Invalidate last encoded body buffer 1248 lbbuf = null; 1249 1250 // Reinitialize each element in the arrays 1251 1252 // Use reference caches to minimize array access overhead 1253 TagTreeEncoder ttIncl_t_c[][][],ttMaxBP_t_c[][][],ttIncl_t_c_r[][], 1254 ttMaxBP_t_c_r[][]; 1255 int lblock_t_c[][][],prevtIdxs_t_c_r[][]; 1256 1257 // Loop on tiles 1258 for (int t=ttIncl.length-1; t>=0; t--) { 1259 // Loop on components 1260 for (int c=ttIncl[t].length-1; c>=0; c--) { 1261 // Initialize reference caches 1262 lblock_t_c = lblock[t][c]; 1263 ttIncl_t_c = ttIncl[t][c]; 1264 ttMaxBP_t_c = ttMaxBP[t][c]; 1265 // Loop on resolution levels 1266 for (int r=lblock_t_c.length-1; r>=0; r--) { 1267 // Initialize reference caches 1268 ttIncl_t_c_r = ttIncl_t_c[r]; 1269 ttMaxBP_t_c_r = ttMaxBP_t_c[r]; 1270 prevtIdxs_t_c_r = prevtIdxs[t][c][r]; 1271 1272 // Loop on subbands 1273 minsbi = (r==0) ? 0 : 1; 1274 maxsbi = (r==0) ? 1 : 4; 1275 for (int s=minsbi; s<maxsbi; s++) { 1276 // Reset 'prevtIdxs' 1277 ArrayUtil.intArraySet(prevtIdxs_t_c_r[s],-1); 1278 // Reset 'lblock' 1279 ArrayUtil.intArraySet(lblock_t_c[r][s],INIT_LBLOCK); 1280 } // End loop on subbands 1281 1282 // Loop on precincts 1283 for(int p=ppinfo[t][c][r].length-1; p>=0; p--) { 1284 if(p<ttIncl_t_c_r.length) { 1285 // Loop on subbands 1286 for(int s=minsbi; s<maxsbi; s++) { 1287 ttIncl_t_c_r[p][s].reset(); 1288 ttMaxBP_t_c_r[p][s].reset(); 1289 } // End loop on subbands 1290 } 1291 } // End loop on precincts 1292 } // End loop on resolution levels 1293 } // End loop on components 1294 } // End loop on tiles 1295 } 1296 1297 /** 1298 * Returns true if the current packet is writable i.e. should be written. 1299 * Returns false otherwise. 1300 * */ 1301 public boolean isPacketWritable() { 1302 return packetWritable; 1303 } 1304 1305 /** 1306 * Tells if there was ROI information in the last written packet 1307 * */ 1308 public boolean isROIinPkt(){ 1309 return roiInPkt; 1310 } 1311 1312 /** Gives the length to read in current packet body to get all ROI 1313 * information */ 1314 public int getROILen(){ 1315 return roiLen; 1316 } 1317 1318 /** 1319 * Returns the parameters that are used in this class and implementing 1320 * classes. It returns a 2D String array. Each of the 1D arrays is for a 1321 * different option, and they have 3 elements. The first element is the 1322 * option name, the second one is the synopsis, the third one is a long 1323 * description of what the parameter is and the fourth is its default 1324 * value. The synopsis or description may be 'null', in which case it is 1325 * assumed that there is no synopsis or description of the option, 1326 * respectively. Null may be returned if no options are supported. 1327 * 1328 * @return the options name, their synopsis and their explanation, 1329 * or null if no options are supported. 1330 * */ 1331 public static String[][] getParameterInfo() { 1332 return pinfo; 1333 } 1334 1335 /** 1336 * Returns information about a given precinct 1337 * 1338 * @param t Tile index. 1339 * 1340 * @param c Component index. 1341 * 1342 * @param r Resolution level index. 1343 * 1344 * @param p Precinct index 1345 * */ 1346 public PrecInfo getPrecInfo(int t,int c,int r,int p) { 1347 return ppinfo[t][c][r][p]; 1348 } 1349}