Source Code Cross Referenced for PktEncoder.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » jj2000 » j2k » codestream » writer » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » jj2000.j2k.codestream.writer 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: PktEncoder.java,v $
0003:         * $Revision: 1.1 $
0004:         * $Date: 2005/02/11 05:02:03 $
0005:         * $State: Exp $
0006:         *
0007:         * Class:                   PktEncoder
0008:         *
0009:         * Description:             Builds bit stream packets and keeps
0010:         *                          interpacket dependencies.
0011:         *
0012:         *
0013:         *
0014:         * COPYRIGHT:
0015:         *
0016:         * This software module was originally developed by Raphaël Grosbois and
0017:         * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
0018:         * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
0019:         * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
0020:         * Centre France S.A) in the course of development of the JPEG2000
0021:         * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
0022:         * software module is an implementation of a part of the JPEG 2000
0023:         * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
0024:         * Systems AB and Canon Research Centre France S.A (collectively JJ2000
0025:         * Partners) agree not to assert against ISO/IEC and users of the JPEG
0026:         * 2000 Standard (Users) any of their rights under the copyright, not
0027:         * including other intellectual property rights, for this software module
0028:         * with respect to the usage by ISO/IEC and Users of this software module
0029:         * or modifications thereof for use in hardware or software products
0030:         * claiming conformance to the JPEG 2000 Standard. Those intending to use
0031:         * this software module in hardware or software products are advised that
0032:         * their use may infringe existing patents. The original developers of
0033:         * this software module, JJ2000 Partners and ISO/IEC assume no liability
0034:         * for use of this software module or modifications thereof. No license
0035:         * or right to this software module is granted for non JPEG 2000 Standard
0036:         * conforming products. JJ2000 Partners have full right to use this
0037:         * software module for his/her own purpose, assign or donate this
0038:         * software module to any third party and to inhibit third parties from
0039:         * using this software module for non JPEG 2000 Standard conforming
0040:         * products. This copyright notice must be included in all copies or
0041:         * derivative works of this software module.
0042:         *
0043:         * Copyright (c) 1999/2000 JJ2000 Partners.
0044:         * */
0045:
0046:        package jj2000.j2k.codestream.writer;
0047:
0048:        import java.awt.Point;
0049:
0050:        import jj2000.j2k.wavelet.analysis.*;
0051:        import jj2000.j2k.entropy.encoder.*;
0052:        import jj2000.j2k.codestream.*;
0053:        import jj2000.j2k.wavelet.*;
0054:        import jj2000.j2k.image.*;
0055:        import jj2000.j2k.util.*;
0056:        import jj2000.j2k.*;
0057:
0058:        import java.util.Vector;
0059:        import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava;
0060:
0061:        /**
0062:         * This class builds packets and keeps the state information of packet
0063:         * interdependencies. It also supports saving the state and reverting
0064:         * (restoring) to the last saved state, with the save() and restore() methods.
0065:         *
0066:         * <P>Each time the encodePacket() method is called a new packet is encoded,
0067:         * the packet header is returned by the method, and the packet body can be
0068:         * obtained with the getLastBodyBuf() and getLastBodyLen() methods.
0069:         * */
0070:        public class PktEncoder {
0071:
0072:            /** The prefix for packet encoding options: 'P' */
0073:            public final static char OPT_PREFIX = 'P';
0074:
0075:            /** The list of parameters that is accepted for packet encoding.*/
0076:            private final static String[][] pinfo = {
0077:                    {
0078:                            "Psop",
0079:                            "[<tile idx>] true|false"
0080:                                    + "[ [<tile idx>] true|false ...]",
0081:                            "Specifies whether start of packet (SOP) markers should be used. "
0082:                                    + "'true' enables, 'false' disables it.",
0083:                            "false" },
0084:                    {
0085:                            "Peph",
0086:                            "[<tile idx>] true|false"
0087:                                    + "[ [<tile  idx>] true|false ...]",
0088:                            "Specifies whether end of packet header (EPH) markers should be "
0089:                                    + " used. 'true' enables, 'false' disables it.",
0090:                            "false" } };
0091:
0092:            /** The initial value for the lblock */
0093:            private final static int INIT_LBLOCK = 3;
0094:
0095:            /** The source object */
0096:            private CodedCBlkDataSrcEnc infoSrc;
0097:
0098:            /** The encoder specs */
0099:            J2KImageWriteParamJava wp;
0100:
0101:            /**
0102:             * The tag tree for inclusion information. The indexes are outlined
0103:             * below. Note that the layer indexes start at 1, therefore, the layer
0104:             * index minus 1 is used. The subband indices are used as they are defined
0105:             * in the Subband class. The tile indices start at 0 and follow a
0106:             * lexicographical order.
0107:             *
0108:             * <ul>
0109:             * <li>1st index: tile index, in lexicographical order</li>
0110:             * <li>2nd index: component index </li>
0111:             * <li>3rd index: resolution level </li>
0112:             * <li>4th index: subband index </li>
0113:             * <li>5th index: precinct index </li>
0114:             * </ul>
0115:             **/
0116:            private TagTreeEncoder ttIncl[][][][][];
0117:
0118:            /**
0119:             * The tag tree for the maximum significant bit-plane. The indexes are
0120:             * outlined below. Note that the layer indexes start at 1, therefore, the
0121:             * layer index minus 1 is used. The subband indices are used as they are
0122:             * defined in the Subband class. The tile indices start at 0 and follow a
0123:             * lexicographical order.
0124:             *
0125:             * <ul>
0126:             * <li>1st index: tile index, in lexicographical order</li>
0127:             * <li>2nd index: component index </li>
0128:             * <li>3rd index: resolution level </li>
0129:             * <li>4th index: subband index - subband index offset </li>
0130:             * <li>5th index: precinct index </li>
0131:             * </ul>
0132:             * */
0133:            private TagTreeEncoder ttMaxBP[][][][][];
0134:
0135:            /**
0136:             * The base number of bits for sending code-block length information
0137:             * (referred as Lblock in the JPEG 2000 standard). The indexes are
0138:             * outlined below. Note that the layer indexes start at 1, therefore, the
0139:             * layer index minus 1 is used. The subband indices are used as they are
0140:             * defined in the Subband class. The tile indices start at 0 and follow a
0141:             * lexicographical order.
0142:             *
0143:             * <ul>
0144:             * <li>1st index: tile index, in lexicographical order </li>
0145:             * <li>2nd index: component index </li>
0146:             * <li>3rd index: resolution level </li>
0147:             * <li>4th index: subband index - subband index offset </li>
0148:             * <li>5th index: code-block index, in lexicographical order</li>
0149:             * </ul>
0150:             * */
0151:            private int lblock[][][][][];
0152:
0153:            /**
0154:             * The last encoded truncation point for each code-block. A negative value
0155:             * means that no information has been included for the block, yet. The
0156:             * indexes are outlined below. The subband indices are used as they are
0157:             * defined in the Subband class. The tile indices start at 0 and follow a
0158:             * lexicographical order. The code-block indices follow a lexicographical
0159:             * order within the subband tile.
0160:             *
0161:             * <P>What is actually stored is the index of the element in
0162:             * CBlkRateDistStats.truncIdxs that gives the real truncation point.
0163:             *
0164:             * <ul>
0165:             * <li>1st index: tile index, in lexicographical order </li>
0166:             * <li>2nd index: component index </li>
0167:             * <li>3rd index: resolution level </li>
0168:             * <li>4th index: subband index - subband index offset </li>
0169:             * <li>5th index: code-block index, in lexicographical order </li>
0170:             * </ul>
0171:             *  */
0172:            private int prevtIdxs[][][][][];
0173:
0174:            /**
0175:             * The saved base number of bits for sending code-block length
0176:             * information. It is used for restoring previous saved state by
0177:             * restore(). The indexes are outlined below. Note that the layer indexes
0178:             * start at 1, therefore, the layer index minus 1 is used. The subband
0179:             * indices are used as they are defined in the Subband class. The tile
0180:             * indices start at 0 and follow a lexicographical order.
0181:             *
0182:             * <ul>
0183:             * <li>1st index: tile index, in lexicographical order </li>
0184:             * <li>2nd index: component index </li>
0185:             * <li>3rd index: resolution level </li>
0186:             * <li>4th index: subband index - subband index offset </li>
0187:             * <li>5th index: code-block index, in lexicographical order</li>
0188:             * </ul>
0189:             * */
0190:            private int bak_lblock[][][][][];
0191:
0192:            /**
0193:             * The saved last encoded truncation point for each code-block. It is used
0194:             * for restoring previous saved state by restore(). A negative value means
0195:             * that no information has been included for the block, yet. The indexes
0196:             * are outlined below. The subband indices are used as they are defined in
0197:             * the Subband class. The tile indices start at 0 and follow a
0198:             * lexicographical order. The code-block indices follow a lexicographical
0199:             * order within the subband tile.
0200:             *
0201:             * <ul>
0202:             * <li>1st index: tile index, in lexicographical order </li>
0203:             * <li>2nd index: component index </li>
0204:             * <li>3rd index: resolution level </li>
0205:             * <li>4th index: subband index - subband index offset </li>
0206:             * <li>5th index: code-block index, in lexicographical order </li>
0207:             * </ul>
0208:             *  */
0209:            private int bak_prevtIdxs[][][][][];
0210:
0211:            /** The body buffer of the last encoded packet */
0212:            private byte[] lbbuf;
0213:
0214:            /** The body length of the last encoded packet */
0215:            private int lblen;
0216:
0217:            /** The saved state */
0218:            private boolean saved;
0219:
0220:            /** Whether or not there is ROI information in the last encoded Packet */
0221:            private boolean roiInPkt = false;
0222:
0223:            /** Length to read in current packet body to get all the ROI information */
0224:            private int roiLen = 0;
0225:
0226:            /**
0227:             * Array containing the coordinates, width, height, indexes, ... of the
0228:             * precincts.
0229:             *
0230:             * <ul>
0231:             * <li> 1st dim: tile index.</li>
0232:             * <li> 2nd dim: component index.</li>
0233:             * <li> 3rd dim: resolution level index.</li>
0234:             * <li> 4th dim: precinct index.</li>
0235:             * </ul> 
0236:             * */
0237:            private PrecInfo ppinfo[][][][];
0238:
0239:            /** Whether or not the current packet is writable */
0240:            private boolean packetWritable;
0241:
0242:            /**
0243:             * Creates a new packet header encoder, using the information from the
0244:             * 'infoSrc' object. The information used is the number of components,
0245:             * number of tiles, subband decomposition, etc.
0246:             *
0247:             * <P>Note that this constructor visits all the tiles in the 'infoSrc'
0248:             * object. The 'infoSrc' object is left at the original tile (i.e. the
0249:             * current tile before calling this constructor), but any side effects of
0250:             * visiting the tiles is not reverted.
0251:             *
0252:             * @param infoSrc The source of information to construct the
0253:             * object.
0254:             *
0255:             * @param encSpec The parameters for the encoding
0256:             *
0257:             * @param maxNumPrec Maximum number of precinct in each tile, component
0258:             * and resolution level.
0259:             *
0260:             * @param pl ParameterList instance that holds command line options
0261:             * */
0262:            public PktEncoder(CodedCBlkDataSrcEnc infoSrc,
0263:                    J2KImageWriteParamJava wp, Point[][][] numPrec) {
0264:                this .infoSrc = infoSrc;
0265:                this .wp = wp;
0266:                //        this.numPrec = numPrec;
0267:
0268:                // Get number of components and tiles
0269:                int nc = infoSrc.getNumComps();
0270:                int nt = infoSrc.getNumTiles();
0271:
0272:                // Do initial allocation
0273:                ttIncl = new TagTreeEncoder[nt][nc][][][];
0274:                ttMaxBP = new TagTreeEncoder[nt][nc][][][];
0275:                lblock = new int[nt][nc][][][];
0276:                prevtIdxs = new int[nt][nc][][][];
0277:                ppinfo = new PrecInfo[nt][nc][][];
0278:
0279:                // Finish allocation
0280:                SubbandAn root, sb;
0281:                int maxs, mins;
0282:                int mrl;
0283:                Point tmpCoord = null;
0284:                int numcb; // Number of code-blocks
0285:                Vector cblks = null;
0286:                infoSrc.setTile(0, 0);
0287:                for (int t = 0; t < nt; t++) { // Loop on tiles
0288:                    for (int c = 0; c < nc; c++) { // Loop on components
0289:                        // Get number of resolution levels
0290:                        root = infoSrc.getAnSubbandTree(t, c);
0291:                        mrl = root.resLvl;
0292:
0293:                        lblock[t][c] = new int[mrl + 1][][];
0294:                        ttIncl[t][c] = new TagTreeEncoder[mrl + 1][][];
0295:                        ttMaxBP[t][c] = new TagTreeEncoder[mrl + 1][][];
0296:                        prevtIdxs[t][c] = new int[mrl + 1][][];
0297:                        ppinfo[t][c] = new PrecInfo[mrl + 1][];
0298:
0299:                        for (int r = 0; r <= mrl; r++) { // Loop on resolution levels
0300:                            mins = (r == 0) ? 0 : 1;
0301:                            maxs = (r == 0) ? 1 : 4;
0302:
0303:                            int maxPrec = numPrec[t][c][r].x
0304:                                    * numPrec[t][c][r].y;
0305:
0306:                            ttIncl[t][c][r] = new TagTreeEncoder[maxPrec][maxs];
0307:                            ttMaxBP[t][c][r] = new TagTreeEncoder[maxPrec][maxs];
0308:                            prevtIdxs[t][c][r] = new int[maxs][];
0309:                            lblock[t][c][r] = new int[maxs][];
0310:
0311:                            // Precincts and code-blocks
0312:                            ppinfo[t][c][r] = new PrecInfo[maxPrec];
0313:                            fillPrecInfo(t, c, r);
0314:
0315:                            for (int s = mins; s < maxs; s++) {
0316:                                // Loop on subbands
0317:                                sb = (SubbandAn) root.getSubbandByIdx(r, s);
0318:                                numcb = sb.numCb.x * sb.numCb.y;
0319:
0320:                                lblock[t][c][r][s] = new int[numcb];
0321:                                ArrayUtil.intArraySet(lblock[t][c][r][s],
0322:                                        INIT_LBLOCK);
0323:
0324:                                prevtIdxs[t][c][r][s] = new int[numcb];
0325:                                ArrayUtil
0326:                                        .intArraySet(prevtIdxs[t][c][r][s], -1);
0327:                            }
0328:                        }
0329:                    }
0330:                    if (t != nt - 1)
0331:                        infoSrc.nextTile();
0332:                }
0333:            }
0334:
0335:            /** 
0336:             * Retrives precincts and code-blocks coordinates in the given resolution,
0337:             * component and tile. It terminates TagTreeEncoder initialization as
0338:             * well.
0339:             *
0340:             * @param t Tile index.
0341:             *
0342:             * @param c Component index.
0343:             *
0344:             * @param r Resolution level index.
0345:             * */
0346:            private void fillPrecInfo(int t, int c, int r) {
0347:                if (ppinfo[t][c][r].length == 0)
0348:                    return; // No precinct in this
0349:                // resolution level
0350:
0351:                Point tileI = infoSrc.getTile(null);
0352:                Point nTiles = infoSrc.getNumTiles(null);
0353:
0354:                int x0siz = infoSrc.getImgULX();
0355:                int y0siz = infoSrc.getImgULY();
0356:                int xsiz = x0siz + infoSrc.getImgWidth();
0357:                int ysiz = y0siz + infoSrc.getImgHeight();
0358:                int xt0siz = infoSrc.getTilePartULX();
0359:                int yt0siz = infoSrc.getTilePartULY();
0360:                int xtsiz = infoSrc.getNomTileWidth();
0361:                int ytsiz = infoSrc.getNomTileHeight();
0362:
0363:                int tx0 = (tileI.x == 0) ? x0siz : xt0siz + tileI.x * xtsiz;
0364:                int ty0 = (tileI.y == 0) ? y0siz : yt0siz + tileI.y * ytsiz;
0365:                int tx1 = (tileI.x != nTiles.x - 1) ? xt0siz + (tileI.x + 1)
0366:                        * xtsiz : xsiz;
0367:                int ty1 = (tileI.y != nTiles.y - 1) ? yt0siz + (tileI.y + 1)
0368:                        * ytsiz : ysiz;
0369:
0370:                int xrsiz = infoSrc.getCompSubsX(c);
0371:                int yrsiz = infoSrc.getCompSubsY(c);
0372:
0373:                int tcx0 = (int) Math.ceil(tx0 / (double) (xrsiz));
0374:                int tcy0 = (int) Math.ceil(ty0 / (double) (yrsiz));
0375:                int tcx1 = (int) Math.ceil(tx1 / (double) (xrsiz));
0376:                int tcy1 = (int) Math.ceil(ty1 / (double) (yrsiz));
0377:
0378:                int ndl = infoSrc.getAnSubbandTree(t, c).resLvl - r;
0379:                int trx0 = (int) Math.ceil(tcx0 / (double) (1 << ndl));
0380:                int try0 = (int) Math.ceil(tcy0 / (double) (1 << ndl));
0381:                int trx1 = (int) Math.ceil(tcx1 / (double) (1 << ndl));
0382:                int try1 = (int) Math.ceil(tcy1 / (double) (1 << ndl));
0383:
0384:                int cb0x = infoSrc.getCbULX();
0385:                int cb0y = infoSrc.getCbULY();
0386:
0387:                double twoppx = (double) wp.getPrecinctPartition().getPPX(t, c,
0388:                        r);
0389:                double twoppy = (double) wp.getPrecinctPartition().getPPY(t, c,
0390:                        r);
0391:                int twoppx2 = (int) (twoppx / 2);
0392:                int twoppy2 = (int) (twoppy / 2);
0393:
0394:                // Precincts are located at (cb0x+i*twoppx,cb0y+j*twoppy)
0395:                // Valid precincts are those which intersect with the current
0396:                // resolution level
0397:                int maxPrec = ppinfo[t][c][r].length;
0398:                int nPrec = 0;
0399:
0400:                int istart = (int) Math.floor((try0 - cb0y) / twoppy);
0401:                int iend = (int) Math.floor((try1 - 1 - cb0y) / twoppy);
0402:                int jstart = (int) Math.floor((trx0 - cb0x) / twoppx);
0403:                int jend = (int) Math.floor((trx1 - 1 - cb0x) / twoppx);
0404:
0405:                int acb0x, acb0y;
0406:
0407:                SubbandAn root = infoSrc.getAnSubbandTree(t, c);
0408:                SubbandAn sb = null;
0409:
0410:                int p0x, p0y, p1x, p1y; // Precinct projection in subband
0411:                int s0x, s0y, s1x, s1y; // Active subband portion
0412:                int cw, ch;
0413:                int kstart, kend, lstart, lend, k0, l0;
0414:                int prg_ulx, prg_uly;
0415:                int prg_w = (int) twoppx << ndl;
0416:                int prg_h = (int) twoppy << ndl;
0417:
0418:                CBlkCoordInfo cb;
0419:
0420:                for (int i = istart; i <= iend; i++) { // Vertical precincts
0421:                    for (int j = jstart; j <= jend; j++, nPrec++) { // Horizontal precincts
0422:                        if (j == jstart
0423:                                && (trx0 - cb0x) % (xrsiz * ((int) twoppx)) != 0) {
0424:                            prg_ulx = tx0;
0425:                        } else {
0426:                            prg_ulx = cb0x + j * xrsiz * ((int) twoppx << ndl);
0427:                        }
0428:                        if (i == istart
0429:                                && (try0 - cb0y) % (yrsiz * ((int) twoppy)) != 0) {
0430:                            prg_uly = ty0;
0431:                        } else {
0432:                            prg_uly = cb0y + i * yrsiz * ((int) twoppy << ndl);
0433:                        }
0434:
0435:                        ppinfo[t][c][r][nPrec] = new PrecInfo(r,
0436:                                (int) (cb0x + j * twoppx), (int) (cb0y + i
0437:                                        * twoppy), (int) twoppx, (int) twoppy,
0438:                                prg_ulx, prg_uly, prg_w, prg_h);
0439:
0440:                        if (r == 0) { // LL subband
0441:                            acb0x = cb0x;
0442:                            acb0y = cb0y;
0443:
0444:                            p0x = acb0x + j * (int) twoppx;
0445:                            p1x = p0x + (int) twoppx;
0446:                            p0y = acb0y + i * (int) twoppy;
0447:                            p1y = p0y + (int) twoppy;
0448:
0449:                            sb = (SubbandAn) root.getSubbandByIdx(0, 0);
0450:                            s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0451:                            s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0452:                            s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0453:                            s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0454:
0455:                            // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0456:                            cw = sb.nomCBlkW;
0457:                            ch = sb.nomCBlkH;
0458:                            k0 = (int) Math.floor((sb.ulcy - acb0y)
0459:                                    / (double) ch);
0460:                            kstart = (int) Math.floor((s0y - acb0y)
0461:                                    / (double) ch);
0462:                            kend = (int) Math.floor((s1y - 1 - acb0y)
0463:                                    / (double) ch);
0464:                            l0 = (int) Math.floor((sb.ulcx - acb0x)
0465:                                    / (double) cw);
0466:                            lstart = (int) Math.floor((s0x - acb0x)
0467:                                    / (double) cw);
0468:                            lend = (int) Math.floor((s1x - 1 - acb0x)
0469:                                    / (double) cw);
0470:
0471:                            if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0472:                                ppinfo[t][c][r][nPrec].nblk[0] = 0;
0473:                                ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(
0474:                                        0, 0);
0475:                                ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(
0476:                                        0, 0);
0477:                            } else {
0478:                                ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(
0479:                                        kend - kstart + 1, lend - lstart + 1);
0480:                                ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(
0481:                                        kend - kstart + 1, lend - lstart + 1);
0482:                                ppinfo[t][c][r][nPrec].cblk[0] = new CBlkCoordInfo[kend
0483:                                        - kstart + 1][lend - lstart + 1];
0484:                                ppinfo[t][c][r][nPrec].nblk[0] = (kend - kstart + 1)
0485:                                        * (lend - lstart + 1);
0486:
0487:                                for (int k = kstart; k <= kend; k++) { // Vertical cblks
0488:                                    for (int l = lstart; l <= lend; l++) { // Horiz. cblks
0489:
0490:                                        cb = new CBlkCoordInfo(k - k0, l - l0);
0491:                                        ppinfo[t][c][r][nPrec].cblk[0][k
0492:                                                - kstart][l - lstart] = cb;
0493:                                    } // Horizontal code-blocks
0494:                                } // Vertical code-blocks
0495:                            }
0496:                        } else { // HL, LH and HH subbands
0497:                            // HL subband
0498:                            acb0x = 0;
0499:                            acb0y = cb0y;
0500:
0501:                            p0x = acb0x + j * twoppx2;
0502:                            p1x = p0x + twoppx2;
0503:                            p0y = acb0y + i * twoppy2;
0504:                            p1y = p0y + twoppy2;
0505:
0506:                            sb = (SubbandAn) root.getSubbandByIdx(r, 1);
0507:                            s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0508:                            s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0509:                            s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0510:                            s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0511:
0512:                            // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0513:                            cw = sb.nomCBlkW;
0514:                            ch = sb.nomCBlkH;
0515:                            k0 = (int) Math.floor((sb.ulcy - acb0y)
0516:                                    / (double) ch);
0517:                            kstart = (int) Math.floor((s0y - acb0y)
0518:                                    / (double) ch);
0519:                            kend = (int) Math.floor((s1y - 1 - acb0y)
0520:                                    / (double) ch);
0521:                            l0 = (int) Math.floor((sb.ulcx - acb0x)
0522:                                    / (double) cw);
0523:                            lstart = (int) Math.floor((s0x - acb0x)
0524:                                    / (double) cw);
0525:                            lend = (int) Math.floor((s1x - 1 - acb0x)
0526:                                    / (double) cw);
0527:
0528:                            if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0529:                                ppinfo[t][c][r][nPrec].nblk[1] = 0;
0530:                                ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(
0531:                                        0, 0);
0532:                                ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(
0533:                                        0, 0);
0534:                            } else {
0535:                                ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(
0536:                                        kend - kstart + 1, lend - lstart + 1);
0537:                                ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(
0538:                                        kend - kstart + 1, lend - lstart + 1);
0539:                                ppinfo[t][c][r][nPrec].cblk[1] = new CBlkCoordInfo[kend
0540:                                        - kstart + 1][lend - lstart + 1];
0541:                                ppinfo[t][c][r][nPrec].nblk[1] = (kend - kstart + 1)
0542:                                        * (lend - lstart + 1);
0543:
0544:                                for (int k = kstart; k <= kend; k++) { // Vertical cblks
0545:                                    for (int l = lstart; l <= lend; l++) { // Horiz. cblks
0546:                                        cb = new CBlkCoordInfo(k - k0, l - l0);
0547:                                        ppinfo[t][c][r][nPrec].cblk[1][k
0548:                                                - kstart][l - lstart] = cb;
0549:                                    } // Horizontal code-blocks
0550:                                } // Vertical code-blocks
0551:                            }
0552:
0553:                            // LH subband
0554:                            acb0x = cb0x;
0555:                            acb0y = 0;
0556:
0557:                            p0x = acb0x + j * twoppx2;
0558:                            p1x = p0x + twoppx2;
0559:                            p0y = acb0y + i * twoppy2;
0560:                            p1y = p0y + twoppy2;
0561:
0562:                            sb = (SubbandAn) root.getSubbandByIdx(r, 2);
0563:                            s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0564:                            s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0565:                            s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0566:                            s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0567:
0568:                            // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0569:                            cw = sb.nomCBlkW;
0570:                            ch = sb.nomCBlkH;
0571:                            k0 = (int) Math.floor((sb.ulcy - acb0y)
0572:                                    / (double) ch);
0573:                            kstart = (int) Math.floor((s0y - acb0y)
0574:                                    / (double) ch);
0575:                            kend = (int) Math.floor((s1y - 1 - acb0y)
0576:                                    / (double) ch);
0577:                            l0 = (int) Math.floor((sb.ulcx - acb0x)
0578:                                    / (double) cw);
0579:                            lstart = (int) Math.floor((s0x - acb0x)
0580:                                    / (double) cw);
0581:                            lend = (int) Math.floor((s1x - 1 - acb0x)
0582:                                    / (double) cw);
0583:
0584:                            if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0585:                                ppinfo[t][c][r][nPrec].nblk[2] = 0;
0586:                                ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(
0587:                                        0, 0);
0588:                                ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(
0589:                                        0, 0);
0590:                            } else {
0591:                                ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(
0592:                                        kend - kstart + 1, lend - lstart + 1);
0593:                                ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(
0594:                                        kend - kstart + 1, lend - lstart + 1);
0595:                                ppinfo[t][c][r][nPrec].cblk[2] = new CBlkCoordInfo[kend
0596:                                        - kstart + 1][lend - lstart + 1];
0597:                                ppinfo[t][c][r][nPrec].nblk[2] = (kend - kstart + 1)
0598:                                        * (lend - lstart + 1);
0599:
0600:                                for (int k = kstart; k <= kend; k++) { // Vertical cblks
0601:                                    for (int l = lstart; l <= lend; l++) { // Horiz cblks
0602:                                        cb = new CBlkCoordInfo(k - k0, l - l0);
0603:                                        ppinfo[t][c][r][nPrec].cblk[2][k
0604:                                                - kstart][l - lstart] = cb;
0605:                                    } // Horizontal code-blocks
0606:                                } // Vertical code-blocks
0607:                            }
0608:
0609:                            // HH subband
0610:                            acb0x = 0;
0611:                            acb0y = 0;
0612:
0613:                            p0x = acb0x + j * twoppx2;
0614:                            p1x = p0x + twoppx2;
0615:                            p0y = acb0y + i * twoppy2;
0616:                            p1y = p0y + twoppy2;
0617:
0618:                            sb = (SubbandAn) root.getSubbandByIdx(r, 3);
0619:                            s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0620:                            s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0621:                            s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0622:                            s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0623:
0624:                            // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0625:                            cw = sb.nomCBlkW;
0626:                            ch = sb.nomCBlkH;
0627:                            k0 = (int) Math.floor((sb.ulcy - acb0y)
0628:                                    / (double) ch);
0629:                            kstart = (int) Math.floor((s0y - acb0y)
0630:                                    / (double) ch);
0631:                            kend = (int) Math.floor((s1y - 1 - acb0y)
0632:                                    / (double) ch);
0633:                            l0 = (int) Math.floor((sb.ulcx - acb0x)
0634:                                    / (double) cw);
0635:                            lstart = (int) Math.floor((s0x - acb0x)
0636:                                    / (double) cw);
0637:                            lend = (int) Math.floor((s1x - 1 - acb0x)
0638:                                    / (double) cw);
0639:
0640:                            if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0641:                                ppinfo[t][c][r][nPrec].nblk[3] = 0;
0642:                                ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(
0643:                                        0, 0);
0644:                                ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(
0645:                                        0, 0);
0646:                            } else {
0647:                                ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(
0648:                                        kend - kstart + 1, lend - lstart + 1);
0649:                                ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(
0650:                                        kend - kstart + 1, lend - lstart + 1);
0651:                                ppinfo[t][c][r][nPrec].cblk[3] = new CBlkCoordInfo[kend
0652:                                        - kstart + 1][lend - lstart + 1];
0653:                                ppinfo[t][c][r][nPrec].nblk[3] = (kend - kstart + 1)
0654:                                        * (lend - lstart + 1);
0655:
0656:                                for (int k = kstart; k <= kend; k++) { // Vertical cblks
0657:                                    for (int l = lstart; l <= lend; l++) { // Horiz cblks
0658:                                        cb = new CBlkCoordInfo(k - k0, l - l0);
0659:                                        ppinfo[t][c][r][nPrec].cblk[3][k
0660:                                                - kstart][l - lstart] = cb;
0661:                                    } // Horizontal code-blocks
0662:                                } // Vertical code-blocks
0663:                            }
0664:
0665:                        }
0666:                    } // Horizontal precincts
0667:                } // Vertical precincts
0668:            }
0669:
0670:            /**
0671:             * Encodes a packet and returns the buffer containing the encoded packet
0672:             * header. The code-blocks appear in a 3D array of CBlkRateDistStats,
0673:             * 'cbs'. The first index is the tile index in lexicographical order, the
0674:             * second index is the subband index (as defined in the Subband class),
0675:             * and the third index is the code-block index (whithin the subband tile)
0676:             * in lexicographical order as well. The indexes of the new truncation
0677:             * points for each code-block are specified by the 3D array of int
0678:             * 'tIndx'. The indices of this array are the same as for cbs. The
0679:             * truncation point indices in 'tIndx' are the indices of the elements of
0680:             * the 'truncIdxs' array, of the CBlkRateDistStats class, that give the
0681:             * real truncation points. If a truncation point index is negative it
0682:             * means that the code-block has not been included in any layer yet. If
0683:             * the truncation point is less than or equal to the highest truncation
0684:             * point used in previous layers then the code-block is not included in
0685:             * the packet. Otherwise, if larger, the code-block is included in the
0686:             * packet. The body of the packet can be obtained with the
0687:             * getLastBodyBuf() and getLastBodyLen() methods.
0688:             *
0689:             * <p>Layers must be coded in increasing order, in consecutive manner, for
0690:             * each tile, component and resolution level (e.g., layer 1, then layer 2,
0691:             * etc.). For different tile, component and/or resolution level no
0692:             * particular order must be followed.</p>
0693:             *
0694:             * @param ly The layer index (starts at 1).
0695:             *
0696:             * @param c The component index.
0697:             *
0698:             * @param r The resolution level
0699:             *
0700:             * @param t Index of the current tile
0701:             *
0702:             * @param cbs The 3D array of coded code-blocks.
0703:             *
0704:             * @param tIndx The truncation point indices for each code-block.
0705:             *
0706:             * @param hbuf The header buffer. If null a new BitOutputBuffer is created
0707:             * and returned. This buffer is reset before anything is written to it.
0708:             *
0709:             * @param bbuf The body buffer. If null a new one is created. If not large
0710:             * enough a new one is created.
0711:             *
0712:             * @param pIdx The precinct index.
0713:             *
0714:             * @return The buffer containing the packet header.
0715:             * */
0716:            public BitOutputBuffer encodePacket(int ly, int c, int r, int t,
0717:                    CBlkRateDistStats cbs[][], int tIndx[][],
0718:                    BitOutputBuffer hbuf, byte bbuf[], int pIdx) {
0719:                int b, i, maxi;
0720:                int ncb;
0721:                int thmax;
0722:                int newtp;
0723:                int cblen;
0724:                int prednbits, nbits, deltabits;
0725:                TagTreeEncoder cur_ttIncl, cur_ttMaxBP; // inclusion and bit-depth tag
0726:                // trees 
0727:                int cur_prevtIdxs[]; // last encoded truncation points
0728:                CBlkRateDistStats cur_cbs[];
0729:                int cur_tIndx[]; // truncation points to encode
0730:                int minsb = (r == 0) ? 0 : 1;
0731:                int maxsb = (r == 0) ? 1 : 4;
0732:                Point cbCoord = null;
0733:                SubbandAn root = infoSrc.getAnSubbandTree(t, c);
0734:                SubbandAn sb;
0735:                roiInPkt = false;
0736:                roiLen = 0;
0737:                int mend, nend;
0738:
0739:                // Checks if a precinct with such an index exists in this resolution
0740:                // level
0741:                if (pIdx >= ppinfo[t][c][r].length) {
0742:                    packetWritable = false;
0743:                    return hbuf;
0744:                }
0745:                PrecInfo prec = ppinfo[t][c][r][pIdx];
0746:
0747:                // First, we check if packet is empty (i.e precinct 'pIdx' has no
0748:                // code-block in any of the subbands)
0749:                boolean isPrecVoid = true;
0750:
0751:                for (int s = minsb; s < maxsb; s++) {
0752:                    if (prec.nblk[s] == 0) {
0753:                        // The precinct has no code-block in this subband.
0754:                        continue;
0755:                    } else {
0756:                        // The precinct is not empty in at least one subband ->
0757:                        // stop
0758:                        isPrecVoid = false;
0759:                        break;
0760:                    }
0761:                }
0762:
0763:                if (isPrecVoid) {
0764:                    packetWritable = true;
0765:
0766:                    if (hbuf == null) {
0767:                        hbuf = new BitOutputBuffer();
0768:                    } else {
0769:                        hbuf.reset();
0770:                    }
0771:                    if (bbuf == null) {
0772:                        lbbuf = bbuf = new byte[1];
0773:                    }
0774:                    hbuf.writeBit(0);
0775:                    lblen = 0;
0776:
0777:                    return hbuf;
0778:                }
0779:
0780:                if (hbuf == null) {
0781:                    hbuf = new BitOutputBuffer();
0782:                } else {
0783:                    hbuf.reset();
0784:                }
0785:
0786:                // Invalidate last body buffer
0787:                lbbuf = null;
0788:                lblen = 0;
0789:
0790:                // Signal that packet is present
0791:                hbuf.writeBit(1);
0792:
0793:                for (int s = minsb; s < maxsb; s++) { // Loop on subbands
0794:                    sb = (SubbandAn) root.getSubbandByIdx(r, s);
0795:
0796:                    // Go directly to next subband if the precinct has no code-block
0797:                    // in the current one.
0798:                    if (prec.nblk[s] == 0) {
0799:                        continue;
0800:                    }
0801:
0802:                    cur_ttIncl = ttIncl[t][c][r][pIdx][s];
0803:                    cur_ttMaxBP = ttMaxBP[t][c][r][pIdx][s];
0804:                    cur_prevtIdxs = prevtIdxs[t][c][r][s];
0805:                    cur_cbs = cbs[s];
0806:                    cur_tIndx = tIndx[s];
0807:
0808:                    // Set tag tree values for code-blocks in this precinct
0809:                    mend = (prec.cblk[s] == null) ? 0 : prec.cblk[s].length;
0810:                    for (int m = 0; m < mend; m++) {
0811:                        nend = (prec.cblk[s][m] == null) ? 0
0812:                                : prec.cblk[s][m].length;
0813:                        for (int n = 0; n < nend; n++) {
0814:                            cbCoord = prec.cblk[s][m][n].idx;
0815:                            b = cbCoord.x + cbCoord.y * sb.numCb.x;
0816:
0817:                            if (cur_tIndx[b] > cur_prevtIdxs[b]
0818:                                    && cur_prevtIdxs[b] < 0) {
0819:                                // First inclusion
0820:                                cur_ttIncl.setValue(m, n, ly - 1);
0821:                            }
0822:                            if (ly == 1) { // First layer, need to set the skip of MSBP
0823:                                cur_ttMaxBP.setValue(m, n, cur_cbs[b].skipMSBP);
0824:                            }
0825:                        }
0826:                    }
0827:
0828:                    // Now encode the information
0829:                    for (int m = 0; m < prec.cblk[s].length; m++) { // Vertical code-blocks
0830:                        for (int n = 0; n < prec.cblk[s][m].length; n++) { // Horiz. cblks
0831:                            cbCoord = prec.cblk[s][m][n].idx;
0832:                            b = cbCoord.x + cbCoord.y * sb.numCb.x;
0833:
0834:                            // 1) Inclusion information
0835:                            if (cur_tIndx[b] > cur_prevtIdxs[b]) {
0836:                                // Code-block included in this layer
0837:                                if (cur_prevtIdxs[b] < 0) { // First inclusion
0838:                                    // Encode layer info
0839:                                    cur_ttIncl.encode(m, n, ly, hbuf);
0840:
0841:                                    // 2) Max bitdepth info. Encode value
0842:                                    thmax = cur_cbs[b].skipMSBP + 1;
0843:                                    for (i = 1; i <= thmax; i++) {
0844:                                        cur_ttMaxBP.encode(m, n, i, hbuf);
0845:                                    }
0846:
0847:                                    // Count body size for packet
0848:                                    lblen += cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]];
0849:                                } else { // Already in previous layer
0850:                                    // Send "1" bit
0851:                                    hbuf.writeBit(1);
0852:                                    // Count body size for packet
0853:                                    lblen += cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]
0854:                                            - cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
0855:                                }
0856:
0857:                                // 3) Truncation point information
0858:                                if (cur_prevtIdxs[b] < 0) {
0859:                                    newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]];
0860:                                } else {
0861:                                    newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]]
0862:                                            - cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]
0863:                                            - 1;
0864:                                }
0865:
0866:                                // Mix of switch and if is faster
0867:                                switch (newtp) {
0868:                                case 0:
0869:                                    hbuf.writeBit(0); // Send one "0" bit
0870:                                    break;
0871:                                case 1:
0872:                                    hbuf.writeBits(2, 2); // Send one "1" and one "0"
0873:                                    break;
0874:                                case 2:
0875:                                case 3:
0876:                                case 4:
0877:                                    // Send two "1" bits followed by 2 bits
0878:                                    // representation of newtp-2
0879:                                    hbuf.writeBits((3 << 2) | (newtp - 2), 4);
0880:                                    break;
0881:                                default:
0882:                                    if (newtp <= 35) {
0883:                                        // Send four "1" bits followed by a five bits
0884:                                        // representation of newtp-5
0885:                                        hbuf.writeBits((15 << 5) | (newtp - 5),
0886:                                                9);
0887:                                    } else if (newtp <= 163) {
0888:                                        // Send nine "1" bits followed by a seven bits
0889:                                        // representation of newtp-36
0890:                                        hbuf.writeBits((511 << 7)
0891:                                                | (newtp - 36), 16);
0892:                                    } else {
0893:                                        throw new ArithmeticException(
0894:                                                "Maximum number "
0895:                                                        + "of truncation "
0896:                                                        + "points exceeded");
0897:                                    }
0898:                                }
0899:                            } else { // Block not included in this layer
0900:                                if (cur_prevtIdxs[b] >= 0) {
0901:                                    // Already in previous layer. Send "0" bit
0902:                                    hbuf.writeBit(0);
0903:                                } else { // Not in any previous layers
0904:                                    cur_ttIncl.encode(m, n, ly, hbuf);
0905:                                }
0906:                                // Go to the next one.
0907:                                continue;
0908:                            }
0909:
0910:                            // Code-block length
0911:
0912:                            // We need to compute the maximum number of bits needed to
0913:                            // signal the length of each terminated segment and the
0914:                            // final truncation point.
0915:                            newtp = 1;
0916:                            maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]];
0917:                            cblen = (cur_prevtIdxs[b] < 0) ? 0
0918:                                    : cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
0919:
0920:                            // Loop on truncation points
0921:                            i = (cur_prevtIdxs[b] < 0) ? 0
0922:                                    : cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] + 1;
0923:                            int minbits = 0;
0924:                            for (; i < maxi; i++, newtp++) {
0925:                                // If terminated truncation point calculate length
0926:                                if (cur_cbs[b].isTermPass != null
0927:                                        && cur_cbs[b].isTermPass[i]) {
0928:
0929:                                    // Calculate length
0930:                                    cblen = cur_cbs[b].truncRates[i] - cblen;
0931:
0932:                                    // Calculate number of needed bits
0933:                                    prednbits = lblock[t][c][r][s][b]
0934:                                            + MathUtil.log2(newtp);
0935:                                    minbits = ((cblen > 0) ? MathUtil
0936:                                            .log2(cblen) : 0) + 1;
0937:
0938:                                    // Update Lblock increment if needed
0939:                                    for (int j = prednbits; j < minbits; j++) {
0940:                                        lblock[t][c][r][s][b]++;
0941:                                        hbuf.writeBit(1);
0942:                                    }
0943:                                    // Initialize for next length
0944:                                    newtp = 0;
0945:                                    cblen = cur_cbs[b].truncRates[i];
0946:                                }
0947:                            }
0948:                            // Last truncation point length always sent
0949:
0950:                            // Calculate length
0951:                            cblen = cur_cbs[b].truncRates[i] - cblen;
0952:
0953:                            // Calculate number of bits
0954:                            prednbits = lblock[t][c][r][s][b]
0955:                                    + MathUtil.log2(newtp);
0956:                            minbits = ((cblen > 0) ? MathUtil.log2(cblen) : 0) + 1;
0957:                            // Update Lblock increment if needed
0958:                            for (int j = prednbits; j < minbits; j++) {
0959:                                lblock[t][c][r][s][b]++;
0960:                                hbuf.writeBit(1);
0961:                            }
0962:
0963:                            // End of comma-code increment
0964:                            hbuf.writeBit(0);
0965:
0966:                            // There can be terminated several segments, send length
0967:                            // info for all terminated truncation points in addition
0968:                            // to final one
0969:                            newtp = 1;
0970:                            maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]];
0971:                            cblen = (cur_prevtIdxs[b] < 0) ? 0
0972:                                    : cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
0973:                            // Loop on truncation points and count the groups
0974:                            i = (cur_prevtIdxs[b] < 0) ? 0
0975:                                    : cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] + 1;
0976:                            for (; i < maxi; i++, newtp++) {
0977:                                // If terminated truncation point, send length
0978:                                if (cur_cbs[b].isTermPass != null
0979:                                        && cur_cbs[b].isTermPass[i]) {
0980:
0981:                                    cblen = cur_cbs[b].truncRates[i] - cblen;
0982:                                    nbits = MathUtil.log2(newtp)
0983:                                            + lblock[t][c][r][s][b];
0984:                                    hbuf.writeBits(cblen, nbits);
0985:
0986:                                    // Initialize for next length
0987:                                    newtp = 0;
0988:                                    cblen = cur_cbs[b].truncRates[i];
0989:                                }
0990:                            }
0991:                            // Last truncation point length is always signalled
0992:                            // First calculate number of bits needed to signal
0993:                            // Calculate length
0994:                            cblen = cur_cbs[b].truncRates[i] - cblen;
0995:                            nbits = MathUtil.log2(newtp)
0996:                                    + lblock[t][c][r][s][b];
0997:                            hbuf.writeBits(cblen, nbits);
0998:
0999:                        } // End loop on horizontal code-blocks
1000:                    } // End loop on vertical code-blocks
1001:                } // End loop on subband
1002:
1003:                // -> Copy the data to the body buffer
1004:
1005:                // Ensure size for body data
1006:                if (bbuf == null || bbuf.length < lblen) {
1007:                    bbuf = new byte[lblen];
1008:                }
1009:                lbbuf = bbuf;
1010:                lblen = 0;
1011:
1012:                for (int s = minsb; s < maxsb; s++) { // Loop on subbands
1013:                    sb = (SubbandAn) root.getSubbandByIdx(r, s);
1014:
1015:                    cur_prevtIdxs = prevtIdxs[t][c][r][s];
1016:                    cur_cbs = cbs[s];
1017:                    cur_tIndx = tIndx[s];
1018:                    ncb = cur_prevtIdxs.length;
1019:
1020:                    mend = (prec.cblk[s] == null) ? 0 : prec.cblk[s].length;
1021:                    for (int m = 0; m < mend; m++) { // Vertical code-blocks
1022:                        nend = (prec.cblk[s][m] == null) ? 0
1023:                                : prec.cblk[s][m].length;
1024:                        for (int n = 0; n < nend; n++) { // Horiz. cblks
1025:                            cbCoord = prec.cblk[s][m][n].idx;
1026:                            b = cbCoord.x + cbCoord.y * sb.numCb.x;
1027:
1028:                            if (cur_tIndx[b] > cur_prevtIdxs[b]) {
1029:
1030:                                // Block included in this precinct -> Copy data to
1031:                                // body buffer and get code-size
1032:                                if (cur_prevtIdxs[b] < 0) {
1033:                                    cblen = cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]];
1034:                                    System.arraycopy(cur_cbs[b].data, 0, lbbuf,
1035:                                            lblen, cblen);
1036:                                } else {
1037:                                    cblen = cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]
1038:                                            - cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]];
1039:                                    System
1040:                                            .arraycopy(
1041:                                                    cur_cbs[b].data,
1042:                                                    cur_cbs[b].truncRates[cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]],
1043:                                                    lbbuf, lblen, cblen);
1044:                                }
1045:                                lblen += cblen;
1046:
1047:                                // Verifies if this code-block contains new ROI
1048:                                // information
1049:                                if (cur_cbs[b].nROIcoeff != 0
1050:                                        && (cur_prevtIdxs[b] == -1 || cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] <= cur_cbs[b].nROIcp - 1)) {
1051:                                    roiInPkt = true;
1052:                                    roiLen = lblen;
1053:                                }
1054:
1055:                                // Update truncation point
1056:                                cur_prevtIdxs[b] = cur_tIndx[b];
1057:                            }
1058:                        } // End loop on horizontal code-blocks
1059:                    } // End loop on vertical code-blocks
1060:                } // End loop on subbands
1061:
1062:                packetWritable = true;
1063:
1064:                // Must never happen
1065:                if (hbuf.getLength() == 0) {
1066:                    throw new Error(
1067:                            "You have found a bug in PktEncoder, method:"
1068:                                    + " encodePacket");
1069:                }
1070:
1071:                return hbuf;
1072:            }
1073:
1074:            /**
1075:             * Returns the buffer of the body of the last encoded packet. The length
1076:             * of the body can be retrieved with the getLastBodyLen() method. The
1077:             * length of the array returned by this method may be larger than the
1078:             * actual body length.
1079:             *
1080:             * @return The buffer of body of the last encoded packet.
1081:             *
1082:             * @exception IllegalArgumentException If no packet has been coded since
1083:             * last reset(), last restore(), or object creation.
1084:             *
1085:             * @see #getLastBodyLen
1086:             * */
1087:            public byte[] getLastBodyBuf() {
1088:                if (lbbuf == null) {
1089:                    throw new IllegalArgumentException();
1090:                }
1091:                return lbbuf;
1092:            }
1093:
1094:            /**
1095:             * Returns the length of the body of the last encoded packet, in
1096:             * bytes. The body itself can be retrieved with the getLastBodyBuf()
1097:             * method.
1098:             *
1099:             * @return The length of the body of last encoded packet, in bytes.
1100:             *
1101:             * @see #getLastBodyBuf
1102:             * */
1103:            public int getLastBodyLen() {
1104:                return lblen;
1105:            }
1106:
1107:            /**
1108:             * Saves the current state of this object. The last saved state
1109:             * can be restored with the restore() method.
1110:             *
1111:             * @see #restore
1112:             * */
1113:            public void save() {
1114:                int maxsbi, minsbi;
1115:
1116:                // Have we done any save yet?
1117:                if (bak_lblock == null) {
1118:                    // Allocate backup buffers
1119:                    bak_lblock = new int[ttIncl.length][][][][];
1120:                    bak_prevtIdxs = new int[ttIncl.length][][][][];
1121:                    for (int t = ttIncl.length - 1; t >= 0; t--) {
1122:                        bak_lblock[t] = new int[ttIncl[t].length][][][];
1123:                        bak_prevtIdxs[t] = new int[ttIncl[t].length][][][];
1124:                        for (int c = ttIncl[t].length - 1; c >= 0; c--) {
1125:                            bak_lblock[t][c] = new int[lblock[t][c].length][][];
1126:                            bak_prevtIdxs[t][c] = new int[ttIncl[t][c].length][][];
1127:                            for (int r = lblock[t][c].length - 1; r >= 0; r--) {
1128:                                bak_lblock[t][c][r] = new int[lblock[t][c][r].length][];
1129:                                bak_prevtIdxs[t][c][r] = new int[prevtIdxs[t][c][r].length][];
1130:                                minsbi = (r == 0) ? 0 : 1;
1131:                                maxsbi = (r == 0) ? 1 : 4;
1132:                                for (int s = minsbi; s < maxsbi; s++) {
1133:                                    bak_lblock[t][c][r][s] = new int[lblock[t][c][r][s].length];
1134:                                    bak_prevtIdxs[t][c][r][s] = new int[prevtIdxs[t][c][r][s].length];
1135:                                }
1136:                            }
1137:                        }
1138:                    }
1139:                }
1140:
1141:                //-- Save the data
1142:
1143:                // Use reference caches to minimize array access overhead
1144:                TagTreeEncoder ttIncl_t_c[][][], ttMaxBP_t_c[][][], ttIncl_t_c_r[][], ttMaxBP_t_c_r[][];
1145:                int lblock_t_c[][][], bak_lblock_t_c[][][], prevtIdxs_t_c_r[][], bak_prevtIdxs_t_c_r[][];
1146:
1147:                // Loop on tiles
1148:                for (int t = ttIncl.length - 1; t >= 0; t--) {
1149:                    // Loop on components
1150:                    for (int c = ttIncl[t].length - 1; c >= 0; c--) {
1151:                        // Initialize reference caches
1152:                        lblock_t_c = lblock[t][c];
1153:                        bak_lblock_t_c = bak_lblock[t][c];
1154:                        ttIncl_t_c = ttIncl[t][c];
1155:                        ttMaxBP_t_c = ttMaxBP[t][c];
1156:                        // Loop on resolution levels
1157:                        for (int r = lblock_t_c.length - 1; r >= 0; r--) {
1158:                            // Initialize reference caches
1159:                            ttIncl_t_c_r = ttIncl_t_c[r];
1160:                            ttMaxBP_t_c_r = ttMaxBP_t_c[r];
1161:                            prevtIdxs_t_c_r = prevtIdxs[t][c][r];
1162:                            bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r];
1163:
1164:                            // Loop on subbands
1165:                            minsbi = (r == 0) ? 0 : 1;
1166:                            maxsbi = (r == 0) ? 1 : 4;
1167:                            for (int s = minsbi; s < maxsbi; s++) {
1168:                                // Save 'lblock'
1169:                                System.arraycopy(lblock_t_c[r][s], 0,
1170:                                        bak_lblock_t_c[r][s], 0,
1171:                                        lblock_t_c[r][s].length);
1172:                                // Save 'prevtIdxs'
1173:                                System.arraycopy(prevtIdxs_t_c_r[s], 0,
1174:                                        bak_prevtIdxs_t_c_r[s], 0,
1175:                                        prevtIdxs_t_c_r[s].length);
1176:                            } // End loop on subbands
1177:
1178:                            // Loop on precincts
1179:                            for (int p = ppinfo[t][c][r].length - 1; p >= 0; p--) {
1180:                                if (p < ttIncl_t_c_r.length) {
1181:                                    // Loop on subbands
1182:                                    for (int s = minsbi; s < maxsbi; s++) {
1183:                                        ttIncl_t_c_r[p][s].save();
1184:                                        ttMaxBP_t_c_r[p][s].save();
1185:                                    } // End loop on subbands
1186:                                }
1187:                            } // End loop on precincts
1188:                        } // End loop on resolutions
1189:                    } // End loop on components
1190:                } // End loop on tiles
1191:
1192:                // Set the saved state
1193:                saved = true;
1194:            }
1195:
1196:            /**
1197:             * Restores the last saved state of this object. An
1198:             * IllegalArgumentException is thrown if no state has been saved.
1199:             *
1200:             * @see #save
1201:             * */
1202:            public void restore() {
1203:                int maxsbi, minsbi;
1204:
1205:                if (!saved) {
1206:                    throw new IllegalArgumentException();
1207:                }
1208:
1209:                // Invalidate last encoded body buffer
1210:                lbbuf = null;
1211:
1212:                //-- Restore tha data
1213:
1214:                // Use reference caches to minimize array access overhead
1215:                TagTreeEncoder ttIncl_t_c[][][], ttMaxBP_t_c[][][], ttIncl_t_c_r[][], ttMaxBP_t_c_r[][];
1216:                int lblock_t_c[][][], bak_lblock_t_c[][][], prevtIdxs_t_c_r[][], bak_prevtIdxs_t_c_r[][];
1217:
1218:                // Loop on tiles
1219:                for (int t = ttIncl.length - 1; t >= 0; t--) {
1220:                    // Loop on components
1221:                    for (int c = ttIncl[t].length - 1; c >= 0; c--) {
1222:                        // Initialize reference caches
1223:                        lblock_t_c = lblock[t][c];
1224:                        bak_lblock_t_c = bak_lblock[t][c];
1225:                        ttIncl_t_c = ttIncl[t][c];
1226:                        ttMaxBP_t_c = ttMaxBP[t][c];
1227:                        // Loop on resolution levels
1228:                        for (int r = lblock_t_c.length - 1; r >= 0; r--) {
1229:                            // Initialize reference caches
1230:                            ttIncl_t_c_r = ttIncl_t_c[r];
1231:                            ttMaxBP_t_c_r = ttMaxBP_t_c[r];
1232:                            prevtIdxs_t_c_r = prevtIdxs[t][c][r];
1233:                            bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r];
1234:
1235:                            // Loop on subbands
1236:                            minsbi = (r == 0) ? 0 : 1;
1237:                            maxsbi = (r == 0) ? 1 : 4;
1238:                            for (int s = minsbi; s < maxsbi; s++) {
1239:                                // Restore 'lblock'
1240:                                System.arraycopy(bak_lblock_t_c[r][s], 0,
1241:                                        lblock_t_c[r][s], 0,
1242:                                        lblock_t_c[r][s].length);
1243:                                // Restore 'prevtIdxs'
1244:                                System.arraycopy(bak_prevtIdxs_t_c_r[s], 0,
1245:                                        prevtIdxs_t_c_r[s], 0,
1246:                                        prevtIdxs_t_c_r[s].length);
1247:                            } // End loop on subbands
1248:
1249:                            // Loop on precincts
1250:                            for (int p = ppinfo[t][c][r].length - 1; p >= 0; p--) {
1251:                                if (p < ttIncl_t_c_r.length) {
1252:                                    // Loop on subbands
1253:                                    for (int s = minsbi; s < maxsbi; s++) {
1254:                                        ttIncl_t_c_r[p][s].restore();
1255:                                        ttMaxBP_t_c_r[p][s].restore();
1256:                                    } // End loop on subbands
1257:                                }
1258:                            } // End loop on precincts
1259:                        } // End loop on resolution levels
1260:                    } // End loop on components
1261:                } // End loop on tiles
1262:            }
1263:
1264:            /**
1265:             * Resets the state of the object to the initial state, as if the object
1266:             * was just created.
1267:             * */
1268:            public void reset() {
1269:                int maxsbi, minsbi;
1270:
1271:                // Invalidate save
1272:                saved = false;
1273:                // Invalidate last encoded body buffer
1274:                lbbuf = null;
1275:
1276:                // Reinitialize each element in the arrays
1277:
1278:                // Use reference caches to minimize array access overhead
1279:                TagTreeEncoder ttIncl_t_c[][][], ttMaxBP_t_c[][][], ttIncl_t_c_r[][], ttMaxBP_t_c_r[][];
1280:                int lblock_t_c[][][], prevtIdxs_t_c_r[][];
1281:
1282:                // Loop on tiles
1283:                for (int t = ttIncl.length - 1; t >= 0; t--) {
1284:                    // Loop on components
1285:                    for (int c = ttIncl[t].length - 1; c >= 0; c--) {
1286:                        // Initialize reference caches
1287:                        lblock_t_c = lblock[t][c];
1288:                        ttIncl_t_c = ttIncl[t][c];
1289:                        ttMaxBP_t_c = ttMaxBP[t][c];
1290:                        // Loop on resolution levels
1291:                        for (int r = lblock_t_c.length - 1; r >= 0; r--) {
1292:                            // Initialize reference caches
1293:                            ttIncl_t_c_r = ttIncl_t_c[r];
1294:                            ttMaxBP_t_c_r = ttMaxBP_t_c[r];
1295:                            prevtIdxs_t_c_r = prevtIdxs[t][c][r];
1296:
1297:                            // Loop on subbands
1298:                            minsbi = (r == 0) ? 0 : 1;
1299:                            maxsbi = (r == 0) ? 1 : 4;
1300:                            for (int s = minsbi; s < maxsbi; s++) {
1301:                                // Reset 'prevtIdxs'
1302:                                ArrayUtil.intArraySet(prevtIdxs_t_c_r[s], -1);
1303:                                // Reset 'lblock'
1304:                                ArrayUtil.intArraySet(lblock_t_c[r][s],
1305:                                        INIT_LBLOCK);
1306:                            } // End loop on subbands
1307:
1308:                            // Loop on precincts
1309:                            for (int p = ppinfo[t][c][r].length - 1; p >= 0; p--) {
1310:                                if (p < ttIncl_t_c_r.length) {
1311:                                    // Loop on subbands
1312:                                    for (int s = minsbi; s < maxsbi; s++) {
1313:                                        ttIncl_t_c_r[p][s].reset();
1314:                                        ttMaxBP_t_c_r[p][s].reset();
1315:                                    } // End loop on subbands
1316:                                }
1317:                            } // End loop on precincts
1318:                        } // End loop on resolution levels
1319:                    } // End loop on components
1320:                } // End loop on tiles
1321:            }
1322:
1323:            /**
1324:             * Returns true if the current packet is writable i.e. should be written.
1325:             * Returns false otherwise.
1326:             * */
1327:            public boolean isPacketWritable() {
1328:                return packetWritable;
1329:            }
1330:
1331:            /**
1332:             * Tells if there was ROI information in the last written packet
1333:             * */
1334:            public boolean isROIinPkt() {
1335:                return roiInPkt;
1336:            }
1337:
1338:            /** Gives the length to read in current packet body to get all ROI
1339:             * information */
1340:            public int getROILen() {
1341:                return roiLen;
1342:            }
1343:
1344:            /**
1345:             * Returns the parameters that are used in this class and implementing
1346:             * classes. It returns a 2D String array. Each of the 1D arrays is for a
1347:             * different option, and they have 3 elements. The first element is the
1348:             * option name, the second one is the synopsis, the third one is a long
1349:             * description of what the parameter is and the fourth is its default
1350:             * value. The synopsis or description may be 'null', in which case it is
1351:             * assumed that there is no synopsis or description of the option,
1352:             * respectively. Null may be returned if no options are supported.
1353:             *
1354:             * @return the options name, their synopsis and their explanation,
1355:             * or null if no options are supported.
1356:             * */
1357:            public static String[][] getParameterInfo() {
1358:                return pinfo;
1359:            }
1360:
1361:            /** 
1362:             * Returns information about a given precinct
1363:             * 
1364:             * @param t Tile index.
1365:             *
1366:             * @param c Component index.
1367:             *
1368:             * @param r Resolution level index.
1369:             *
1370:             * @param p Precinct index
1371:             * */
1372:            public PrecInfo getPrecInfo(int t, int c, int r, int p) {
1373:                return ppinfo[t][c][r][p];
1374:            }
1375:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.