Source Code Cross Referenced for FileBitstreamReaderAgent.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » jj2000 » j2k » codestream » reader » 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.reader 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: FileBitstreamReaderAgent.java,v $
0003:         * $Revision: 1.4 $
0004:         * $Date: 2006/10/05 01:10:31 $
0005:         * $State: Exp $
0006:         *
0007:         * Class:                   FileBitstreamReaderAgent
0008:         *
0009:         * Description:             Retrieve code-blocks codewords in the bit stream
0010:         *
0011:         *
0012:         *
0013:         * COPYRIGHT:
0014:         *
0015:         * This software module was originally developed by Raphaël Grosbois and
0016:         * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
0017:         * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
0018:         * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
0019:         * Centre France S.A) in the course of development of the JPEG2000
0020:         * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
0021:         * software module is an implementation of a part of the JPEG 2000
0022:         * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
0023:         * Systems AB and Canon Research Centre France S.A (collectively JJ2000
0024:         * Partners) agree not to assert against ISO/IEC and users of the JPEG
0025:         * 2000 Standard (Users) any of their rights under the copyright, not
0026:         * including other intellectual property rights, for this software module
0027:         * with respect to the usage by ISO/IEC and Users of this software module
0028:         * or modifications thereof for use in hardware or software products
0029:         * claiming conformance to the JPEG 2000 Standard. Those intending to use
0030:         * this software module in hardware or software products are advised that
0031:         * their use may infringe existing patents. The original developers of
0032:         * this software module, JJ2000 Partners and ISO/IEC assume no liability
0033:         * for use of this software module or modifications thereof. No license
0034:         * or right to this software module is granted for non JPEG 2000 Standard
0035:         * conforming products. JJ2000 Partners have full right to use this
0036:         * software module for his/her own purpose, assign or donate this
0037:         * software module to any third party and to inhibit third parties from
0038:         * using this software module for non JPEG 2000 Standard conforming
0039:         * products. This copyright notice must be included in all copies or
0040:         * derivative works of this software module.
0041:         *
0042:         * Copyright (c) 1999/2000 JJ2000 Partners.
0043:         * */
0044:        package jj2000.j2k.codestream.reader;
0045:
0046:        import java.awt.Point;
0047:
0048:        import jj2000.j2k.quantization.dequantizer.*;
0049:        import jj2000.j2k.wavelet.synthesis.*;
0050:        import jj2000.j2k.entropy.decoder.*;
0051:        import jj2000.j2k.codestream.*;
0052:        import jj2000.j2k.decoder.*;
0053:        import jj2000.j2k.entropy.*;
0054:        import jj2000.j2k.image.*;
0055:        import jj2000.j2k.util.*;
0056:        import jj2000.j2k.io.*;
0057:        import jj2000.j2k.*;
0058:
0059:        import java.util.*;
0060:        import java.io.*;
0061:        import javax.imageio.stream.ImageInputStream;
0062:        import javax.imageio.stream.MemoryCacheImageInputStream;
0063:
0064:        import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReadParamJava;
0065:
0066:        /**
0067:         * This class reads the bit stream (with the help of HeaderDecoder for tile
0068:         * headers and PktDecoder for packets header and body) and retrives location
0069:         * of all code-block's codewords.
0070:         *
0071:         * <P>Note: All tile-parts headers are read by the constructor whereas packets
0072:         * are processed when decoding related tile (when setTile method is called).
0073:         *
0074:         * <P>In parsing mode, the reader simulates a virtual layer-resolution
0075:         * progressive bit stream with the same truncation points in each code-block,
0076:         * whereas in truncation mode, only the first bytes are taken into account (it
0077:         * behaves like if it is a real truncated codestream).
0078:         *
0079:         * @see HeaderDecoder
0080:         * @see PktDecoder
0081:         * */
0082:        public class FileBitstreamReaderAgent extends BitstreamReaderAgent
0083:                implements  Markers, ProgressionType, StdEntropyCoderOptions {
0084:
0085:            /** Whether or not the last read Psot value was zero. Only the Psot in the
0086:             * last tile-part in the codestream can have such a value. */
0087:            private boolean isPsotEqualsZero = true;
0088:
0089:            /** Reference to the PktDecoder instance */
0090:            public PktDecoder pktDec;
0091:
0092:            /** Reference to the J2KImageReadParamJava instance */
0093:            private J2KImageReadParamJava j2krparam;
0094:
0095:            /** The RandomAccessIO where to get data from */
0096:            private RandomAccessIO in;
0097:
0098:            /** The number of tiles in the image */
0099:            private int nt;
0100:
0101:            /** Offset of the first packet in each tile-part in each tile */
0102:            private int[][] firstPackOff;
0103:
0104:            /**
0105:             * Returns the number of tile-part found for a given tile
0106:             *
0107:             * @param t Tile index
0108:             *
0109:             * */
0110:            public int getNumTileParts(int t) {
0111:                if (firstPackOff == null || firstPackOff[t] == null) {
0112:                    throw new Error("Tile " + t
0113:                            + " not found in input codestream.");
0114:                }
0115:                return firstPackOff[t].length;
0116:            }
0117:
0118:            /** Number of bytes allocated to each tile. In parsing mode, this number
0119:             * is related to the tile length in the codestream whereas in truncation
0120:             * mode all the rate is affected to the first tiles. */
0121:            private int[] nBytes;
0122:
0123:            /** Whether or not to print information found in codestream */
0124:            private boolean printInfo = false;
0125:
0126:            /**
0127:             * Backup of the number of bytes allocated to each tile. This array is
0128:             * used to restore the number of bytes to read in each tile when the
0129:             * codestream is read several times (for instance when decoding an R,G,B
0130:             * image to three output files)
0131:             * */
0132:            private int[] baknBytes;
0133:
0134:            /** Length of each tile-part (written in Psot) */
0135:            private int[][] tilePartLen;
0136:
0137:            /** Total length of each tile */
0138:            private int[] totTileLen;
0139:
0140:            /** Total length of tiles' header */
0141:            private int[] totTileHeadLen;
0142:
0143:            /** First tile part header length*/
0144:            private int firstTilePartHeadLen;
0145:
0146:            /** Total length of all tile parts in all tiles */
0147:            private double totAllTileLen;
0148:
0149:            /** Length of main header */
0150:            private int mainHeadLen;
0151:
0152:            /** Length of main and tile-parts headers */
0153:            private int headLen = 0;
0154:
0155:            /** Length of all tile-part headers */
0156:            private int[][] tilePartHeadLen;
0157:
0158:            /** Length of each packet head found in the tile */
0159:            private Vector pktHL;
0160:
0161:            /** True if truncation mode is used. False if parsing mode */
0162:            private boolean isTruncMode;
0163:
0164:            /** The number of tile-parts that remain to read */
0165:            private int remainingTileParts;
0166:
0167:            /** The number of tile-parts read so far for each tile */
0168:            private int[] tilePartsRead;
0169:
0170:            /** Thetotal  number of tile-parts read so far */
0171:            private int totTilePartsRead = 0;
0172:
0173:            /** The number of tile-parts in each tile */
0174:            private int[] tileParts;
0175:
0176:            /** The total number of tile-parts in each tile */
0177:            private int[] totTileParts;
0178:
0179:            /** The current tile part being used */
0180:            private int curTilePart;
0181:
0182:            /** The number of the tile-part in the codestream */
0183:            private int[][] tilePartNum;
0184:
0185:            /** Whether or not a EOC marker has been found instead of a SOT */
0186:            private boolean isEOCFound = false;
0187:
0188:            /** Reference to the HeaderInfo instance (used when reading SOT marker
0189:             * segments) */
0190:            private HeaderInfo hi;
0191:
0192:            /** Array containing info. for all the code-blocks:<br>
0193:             * - 1st dim: component index.<br>
0194:             * - 2nd dim: resolution level index.<br>
0195:             * - 3rd dim: subband index.<br>
0196:             * - 4th/5th dim: code-block index (vert. and horiz.).<br>
0197:             */
0198:            private CBlkInfo[][][][][] cbI;
0199:
0200:            /** Gets the reference to the CBlkInfo array */
0201:            public CBlkInfo[][][][][] getCBlkInfo() {
0202:                return cbI;
0203:            }
0204:
0205:            /** The maximum number of layers to decode for any code-block */
0206:            private int lQuit;
0207:
0208:            /** Whether or not to use only first progression order */
0209:            private boolean usePOCQuit = false;
0210:
0211:            /**
0212:             * Reads all tiles headers and keep offset of their first
0213:             * packet. Finally it calls the rate allocation method.
0214:             *
0215:             * @param hd HeaderDecoder of the codestream.
0216:             *
0217:             * @param ehs The input stream where to read bit-stream.
0218:             *
0219:             * @param decSpec The decoder specifications
0220:             *
0221:             * @param j2krparam The J2KImageReadParam instance created from the
0222:             * command-line arguments.
0223:             *
0224:             * @param cdstrInfo Whether or not to print information found in
0225:             * codestream.
0226:             *
0227:             * @see #allocateRate
0228:             * */
0229:            public FileBitstreamReaderAgent(HeaderDecoder hd,
0230:                    RandomAccessIO ehs, DecoderSpecs decSpec,
0231:                    J2KImageReadParamJava j2krparam, boolean cdstrInfo,
0232:                    HeaderInfo hi) throws IOException {
0233:                super (hd, decSpec);
0234:
0235:                this .j2krparam = j2krparam;
0236:                this .printInfo = cdstrInfo;
0237:                this .hi = hi;
0238:
0239:                String strInfo = printInfo ? "Codestream elements information in bytes "
0240:                        + "(offset, total length, header length):\n\n"
0241:                        : null;
0242:
0243:                // Check whether quit conditiosn used
0244:                //usePOCQuit = j2krparam.getPOCQuit();
0245:
0246:                // Get decoding rate
0247:                if (j2krparam.getDecodingRate() == Double.MAX_VALUE)
0248:                    tnbytes = Integer.MAX_VALUE;
0249:                else
0250:                    tnbytes = (int) (j2krparam.getDecodingRate()
0251:                            * hd.getMaxCompImgWidth() * hd
0252:                            .getMaxCompImgHeight()) / 8;
0253:                //isTruncMode = !j2krparam.getParsing();
0254:                isTruncMode = true;
0255:
0256:                // Check if quit conditions are being used
0257:                //int ncbQuit = j2krparam.getNCBQuit();
0258:                int ncbQuit = -1;
0259:                if (ncbQuit != -1 && !isTruncMode) {
0260:                    throw new Error(
0261:                            "Cannot use -parsing and -ncb_quit condition at "
0262:                                    + "the same time.");
0263:                }
0264:
0265:                //        lQuit = j2krparam.getLQuit();
0266:                lQuit = -1;
0267:
0268:                // initializations
0269:                nt = ntX * ntY;
0270:                in = ehs;
0271:                pktDec = new PktDecoder(decSpec, hd, ehs, this , isTruncMode,
0272:                        ncbQuit);
0273:
0274:                tileParts = new int[nt];
0275:                totTileParts = new int[nt];
0276:                totTileLen = new int[nt];
0277:                tilePartLen = new int[nt][];
0278:                tilePartNum = new int[nt][];
0279:                firstPackOff = new int[nt][];
0280:                tilePartsRead = new int[nt];
0281:                totTileHeadLen = new int[nt];
0282:                tilePartHeadLen = new int[nt][];
0283:                nBytes = new int[nt];
0284:                baknBytes = new int[nt];
0285:                hd.nTileParts = new int[nt];
0286:
0287:                this .isTruncMode = isTruncMode;
0288:
0289:                // Keeps main header's length, takes file format overhead into account
0290:                cdstreamStart = hd.mainHeadOff; // Codestream offset in the file
0291:                mainHeadLen = in.getPos() - cdstreamStart;
0292:                headLen = mainHeadLen;
0293:
0294:                // If ncb and lbody quit conditions are used, headers are not counted
0295:                if (ncbQuit == -1) {
0296:                    anbytes = mainHeadLen;
0297:                } else {
0298:                    anbytes = 0;
0299:                }
0300:
0301:                if (printInfo)
0302:                    strInfo += "Main header length    : " + cdstreamStart
0303:                            + ", " + mainHeadLen + ", " + mainHeadLen + "\n";
0304:
0305:                // If cannot even read the first tile-part
0306:                if (anbytes > tnbytes) {
0307:                    throw new Error("Requested bitrate is too small.");
0308:                }
0309:
0310:                // Initialize variables used when reading tile-part headers.
0311:                totAllTileLen = 0;
0312:                remainingTileParts = nt; // at least as many tile-parts as tiles
0313:                maxPos = lastPos = in.getPos();
0314:
0315:                // Update 'res' value according to the parameter and the main header.
0316:                if (j2krparam.getResolution() == -1) {
0317:                    targetRes = decSpec.dls.getMin();
0318:                } else {
0319:                    targetRes = j2krparam.getResolution();
0320:                    if (targetRes < 0) {
0321:                        throw new IllegalArgumentException(
0322:                                "Specified negative "
0323:                                        + "resolution level index: "
0324:                                        + targetRes);
0325:                    }
0326:                }
0327:
0328:                // Verify reduction in resolution level
0329:                int mdl = decSpec.dls.getMin();
0330:                if (targetRes > mdl) {
0331:                    FacilityManager
0332:                            .getMsgLogger()
0333:                            .printmsg(
0334:                                    MsgLogger.WARNING,
0335:                                    "Specified resolution level ("
0336:                                            + targetRes
0337:                                            + ") is larger"
0338:                                            + " than the maximum possible. Setting it to "
0339:                                            + mdl + " (maximum possible)");
0340:                    targetRes = mdl;
0341:                }
0342:
0343:                // Initialize tile part positions from TLM marker segment.
0344:                initTLM();
0345:            }
0346:
0347:            // An array of the positions of tile parts:
0348:            // - length of tilePartPositions is nt.
0349:            // - length of tilePartPositions[i] is totTileParts[i].
0350:            long[][] tilePartPositions = null;
0351:
0352:            //
0353:            // Initialize the tilePartPositions positions array if a TLM marker
0354:            // segment is present in the main header. If no such marker segment
0355:            // is present the array will remain null. This method rewinds to the
0356:            // start of the codestream and scans until the first SOT marker is
0357:            // encountered. Before return the stream is returned to its position
0358:            // when the method was invoked.
0359:            //
0360:            private void initTLM() throws IOException {
0361:                // Save the position to return to at the end of this method.
0362:                int savePos = in.getPos();
0363:
0364:                // Array to store contents of TLM segments. The first index is
0365:                // Ztlm. The contents of tlmSegments[i] is the bytes in the TLM
0366:                // segment with Ztlm == i after the Ztlm byte.
0367:                byte[][] tlmSegments = null;
0368:
0369:                // Number of TLM segments. The first numTLM elements of tlmSegments
0370:                // should be non-null if the segments are correct.
0371:                int numTLM = 0;
0372:
0373:                try {
0374:                    // Rewind to the start of the main header.
0375:                    in.seek(cdstreamStart + 2); // skip SOC
0376:
0377:                    // Loop over marker segments.
0378:                    short marker;
0379:                    while ((marker = in.readShort()) != SOT) {
0380:                        // Get the length (which includes the 2-byte length parameter).
0381:                        int markerLength = in.readUnsignedShort();
0382:
0383:                        // Process TLM segments.
0384:                        if (marker == TLM) {
0385:                            numTLM++;
0386:
0387:                            if (tlmSegments == null) {
0388:                                tlmSegments = new byte[256][]; // 0 <= Ztlm <= 255
0389:                            }
0390:
0391:                            // Save contents after Ztlm in array.
0392:                            int Ztlm = in.read();
0393:                            tlmSegments[Ztlm] = new byte[markerLength - 3];
0394:                            in
0395:                                    .readFully(tlmSegments[Ztlm], 0,
0396:                                            markerLength - 3);
0397:                        } else {
0398:                            in.skipBytes(markerLength - 2);
0399:                        }
0400:                    }
0401:                } catch (IOException e) {
0402:                    // Reset so that the TLM segments are not processed further.
0403:                    tlmSegments = null;
0404:                }
0405:
0406:                if (tlmSegments != null) {
0407:                    ArrayList[] tlmOffsets = null;
0408:
0409:                    // Tiles start after the main header.
0410:                    long tilePos = cdstreamStart + mainHeadLen;
0411:
0412:                    // Tile counter for when tile indexes are not included.
0413:                    int tileCounter = 0;
0414:
0415:                    for (int itlm = 0; itlm < numTLM; itlm++) {
0416:                        if (tlmSegments[itlm] == null) {
0417:                            // Null segment among first numTLM entries: error.
0418:                            tlmOffsets = null;
0419:                            break;
0420:                        } else if (tlmOffsets == null) {
0421:                            tlmOffsets = new ArrayList[nt];
0422:                        }
0423:
0424:                        // Create a stream.
0425:                        ByteArrayInputStream bais = new ByteArrayInputStream(
0426:                                tlmSegments[itlm]);
0427:                        ImageInputStream iis = new MemoryCacheImageInputStream(
0428:                                bais);
0429:
0430:                        try {
0431:                            int Stlm = iis.read();
0432:                            int ST = (Stlm >> 4) & 0x3;
0433:                            int SP = (Stlm >> 6) & 0x1;
0434:
0435:                            int tlmLength = tlmSegments[itlm].length;
0436:                            while (iis.getStreamPosition() < tlmLength) {
0437:                                int tileIndex = tileCounter;
0438:                                switch (ST) {
0439:                                case 1:
0440:                                    tileIndex = iis.read();
0441:                                    break;
0442:                                case 2:
0443:                                    tileIndex = iis.readUnsignedShort();
0444:                                }
0445:
0446:                                if (tlmOffsets[tileIndex] == null) {
0447:                                    tlmOffsets[tileIndex] = new ArrayList();
0448:                                }
0449:                                tlmOffsets[tileIndex].add(new Long(tilePos));
0450:
0451:                                long tileLength = 0L;
0452:                                switch (SP) {
0453:                                case 0:
0454:                                    tileLength = iis.readUnsignedShort();
0455:                                    break;
0456:                                case 1:
0457:                                    tileLength = iis.readUnsignedInt();
0458:                                    break;
0459:                                }
0460:
0461:                                tilePos += tileLength;
0462:
0463:                                if (ST == 0)
0464:                                    tileCounter++;
0465:                            }
0466:                        } catch (IOException e) {
0467:                            // XXX?
0468:                        }
0469:                    }
0470:
0471:                    if (tlmOffsets != null) {
0472:                        tilePartPositions = new long[nt][];
0473:                        for (int i = 0; i < nt; i++) {
0474:                            if (tlmOffsets[i] == null) {
0475:                                tilePartPositions = null;
0476:                                break;
0477:                            } else {
0478:                                ArrayList list = tlmOffsets[i];
0479:                                int count = list.size();
0480:                                tilePartPositions[i] = new long[count];
0481:                                long[] tpPos = tilePartPositions[i];
0482:                                for (int j = 0; j < count; j++) {
0483:                                    tpPos[j] = ((Long) list.get(j)).longValue();
0484:                                }
0485:                            }
0486:                        }
0487:                    }
0488:                }
0489:
0490:                in.seek(savePos);
0491:            }
0492:
0493:            int cdstreamStart = 0;
0494:            int t = 0, pos = -1, tp = 0, tptot = 0;
0495:            int tilePartStart = 0;
0496:            boolean rateReached = false;
0497:            int numtp = 0;
0498:            int maxTP = nt; // If maximum 1 tile part per tile specified
0499:            int lastPos = 0, maxPos = 0;
0500:
0501:            /**
0502:             * Read all tile-part headers of the requested tile. All tile-part
0503:             * headers prior to the last tile-part header of the current tile will
0504:             * also be read.
0505:             *
0506:             * @param tileNum The index of the tile for which to read tile-part
0507:             * headers.
0508:             */
0509:            private void initTile(int tileNum) throws IOException {
0510:                if (tilePartPositions == null)
0511:                    in.seek(lastPos);
0512:                String strInfo = "";
0513:                int ncbQuit = -1;
0514:                boolean isTilePartRead = false;
0515:                boolean isEOFEncountered = false;
0516:                try {
0517:                    int tpNum = 0;
0518:                    while (remainingTileParts != 0
0519:                            && (totTileParts[tileNum] == 0 || tilePartsRead[tileNum] < totTileParts[tileNum])) {
0520:                        isTilePartRead = true;
0521:
0522:                        if (tilePartPositions != null) {
0523:                            in.seek((int) tilePartPositions[tileNum][tpNum++]);
0524:                        }
0525:                        tilePartStart = in.getPos();
0526:
0527:                        // Read tile-part header
0528:                        try {
0529:                            t = readTilePartHeader();
0530:                            if (isEOCFound) { // Some tiles are missing but the
0531:                                // codestream is OK
0532:                                break;
0533:                            }
0534:                            tp = tilePartsRead[t];
0535:                            if (isPsotEqualsZero) { // Psot may equals zero for the
0536:                                // last tile-part: it is assumed that this tile-part
0537:                                // contain all data until EOC
0538:                                tilePartLen[t][tp] = in.length() - 2
0539:                                        - tilePartStart;
0540:                            }
0541:                        } catch (EOFException e) {
0542:                            firstPackOff[t][tp] = in.length();
0543:                            throw e;
0544:                        }
0545:
0546:                        pos = in.getPos();
0547:
0548:                        // In truncation mode, if target decoding rate is reached in
0549:                        // tile-part header, skips the tile-part and stop reading
0550:                        // unless the ncb and lbody quit condition is in use
0551:                        if (isTruncMode && ncbQuit == -1) {
0552:                            if ((pos - cdstreamStart) > tnbytes) {
0553:                                firstPackOff[t][tp] = in.length();
0554:                                rateReached = true;
0555:                                break;
0556:                            }
0557:                        }
0558:
0559:                        // Set tile part position and header length
0560:                        firstPackOff[t][tp] = pos;
0561:                        tilePartHeadLen[t][tp] = (pos - tilePartStart);
0562:
0563:                        if (printInfo)
0564:                            strInfo += "Tile-part " + tp + " of tile " + t
0565:                                    + " : " + tilePartStart + ", "
0566:                                    + tilePartLen[t][tp] + ", "
0567:                                    + tilePartHeadLen[t][tp] + "\n";
0568:
0569:                        // Update length counters
0570:                        totTileLen[t] += tilePartLen[t][tp];
0571:                        totTileHeadLen[t] += tilePartHeadLen[t][tp];
0572:                        totAllTileLen += tilePartLen[t][tp];
0573:                        if (isTruncMode) {
0574:                            if (anbytes + tilePartLen[t][tp] > tnbytes) {
0575:                                anbytes += tilePartHeadLen[t][tp];
0576:                                headLen += tilePartHeadLen[t][tp];
0577:                                rateReached = true;
0578:                                nBytes[t] += (tnbytes - anbytes);
0579:                                break;
0580:                            } else {
0581:                                anbytes += tilePartHeadLen[t][tp];
0582:                                headLen += tilePartHeadLen[t][tp];
0583:                                nBytes[t] += (tilePartLen[t][tp] - tilePartHeadLen[t][tp]);
0584:                            }
0585:                        } else {
0586:                            if (anbytes + tilePartHeadLen[t][tp] > tnbytes) {
0587:                                break;
0588:                            } else {
0589:                                anbytes += tilePartHeadLen[t][tp];
0590:                                headLen += tilePartHeadLen[t][tp];
0591:                            }
0592:                        }
0593:
0594:                        // If this is first tile-part, remember header length
0595:                        if (tptot == 0)
0596:                            firstTilePartHeadLen = tilePartHeadLen[t][tp];
0597:
0598:                        // Go to the beginning of next tile part
0599:                        tilePartsRead[t]++;
0600:                        int nextMarkerPos = tilePartStart + tilePartLen[t][tp];
0601:                        if (tilePartPositions == null) {
0602:                            in.seek(nextMarkerPos);
0603:                        }
0604:                        if (nextMarkerPos > maxPos) {
0605:                            maxPos = nextMarkerPos;
0606:                        }
0607:                        remainingTileParts--;
0608:                        maxTP--;
0609:                        tptot++;
0610:                        // If Psot of the current tile-part was equal to zero, it is
0611:                        // assumed that it contains all data until the EOC marker
0612:                        if (isPsotEqualsZero) {
0613:                            if (remainingTileParts != 0) {
0614:                                FacilityManager
0615:                                        .getMsgLogger()
0616:                                        .printmsg(
0617:                                                MsgLogger.WARNING,
0618:                                                "Some tile-parts have not "
0619:                                                        + "been found. The codestream may be corrupted.");
0620:                            }
0621:                            break;
0622:                        }
0623:                    }
0624:                } catch (EOFException e) {
0625:                    isEOFEncountered = true;
0626:
0627:                    if (printInfo) {
0628:                        FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
0629:                                strInfo);
0630:                    }
0631:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.WARNING,
0632:                            "Codestream truncated in tile " + t);
0633:
0634:                    // Set specified rate to end of file if valid
0635:                    int fileLen = in.length();
0636:                    if (fileLen < tnbytes) {
0637:                        tnbytes = fileLen;
0638:                        trate = tnbytes * 8f / hd.getMaxCompImgWidth()
0639:                                / hd.getMaxCompImgHeight();
0640:                    }
0641:                }
0642:
0643:                // If no tile-parts read then return.
0644:                if (!isTilePartRead)
0645:                    return;
0646:
0647:                /* XXX: BEGIN Updating the resolution here is logical when all tile-part
0648:                   headers are read as was the case with the original version of this
0649:                   class. With initTile() however the tiles could be read in random
0650:                   order so modifying the resolution value could cause unexpected
0651:                   results if a given tile-part has fewer levels than the main header
0652:                   indicated.
0653:                // Update 'res' value once all tile-part headers are read
0654:                if(j2krparam.getResolution()== -1) {
0655:                    targetRes = decSpec.dls.getMin();
0656:                } else {
0657:                        targetRes = j2krparam.getResolution();
0658:                        if(targetRes<0) {
0659:                            throw new
0660:                                IllegalArgumentException("Specified negative "+
0661:                                                         "resolution level index: "+
0662:                                                         targetRes);
0663:                        }
0664:                }
0665:
0666:                // Verify reduction in resolution level
0667:                int mdl = decSpec.dls.getMin();
0668:                if(targetRes>mdl) {
0669:                    FacilityManager.getMsgLogger().
0670:                        printmsg(MsgLogger.WARNING,
0671:                                 "Specified resolution level ("+targetRes+
0672:                                 ") is larger"+
0673:                                 " than the maximum possible. Setting it to "+
0674:                                 mdl +" (maximum possible)");
0675:                    targetRes = mdl;
0676:                }
0677:                XXX: END */
0678:
0679:                if (!isEOFEncountered) {
0680:                    if (printInfo) {
0681:                        FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
0682:                                strInfo);
0683:                    }
0684:
0685:                    if (remainingTileParts == 0) {
0686:                        // Check presence of EOC marker is decoding rate not reached or
0687:                        // if this marker has not been found yet
0688:                        if (!isEOCFound && !isPsotEqualsZero && !rateReached) {
0689:                            try {
0690:                                int savePos = in.getPos();
0691:                                in.seek(maxPos);
0692:                                if (in.readShort() != EOC) {
0693:                                    FacilityManager
0694:                                            .getMsgLogger()
0695:                                            .printmsg(
0696:                                                    MsgLogger.WARNING,
0697:                                                    "EOC marker not found. "
0698:                                                            + "Codestream is corrupted.");
0699:                                }
0700:                                in.seek(savePos);
0701:                            } catch (EOFException e) {
0702:                                FacilityManager.getMsgLogger().printmsg(
0703:                                        MsgLogger.WARNING,
0704:                                        "EOC marker is missing");
0705:                            }
0706:                        }
0707:                    }
0708:                }
0709:
0710:                // Bit-rate allocation
0711:                if (!isTruncMode) {
0712:                    allocateRate();
0713:                } else if (remainingTileParts == 0 && !isEOFEncountered) {
0714:                    // Take EOC into account if rate is not reached
0715:                    if (in.getPos() >= tnbytes)
0716:                        anbytes += 2;
0717:                }
0718:
0719:                if (tilePartPositions == null)
0720:                    lastPos = in.getPos();
0721:
0722:                // Backup nBytes
0723:                for (int tIdx = 0; tIdx < nt; tIdx++) {
0724:                    baknBytes[tIdx] = nBytes[tIdx];
0725:                    if (printInfo) {
0726:                        FacilityManager
0727:                                .getMsgLogger()
0728:                                .println(
0729:                                        ""
0730:                                                + hi
0731:                                                        .toStringTileHeader(
0732:                                                                tIdx,
0733:                                                                tilePartLen[tIdx].length),
0734:                                        2, 2);
0735:                    }
0736:                }
0737:            }
0738:
0739:            /**
0740:             * Allocates output bit-rate for each tile in parsing mode: The allocator
0741:             * simulates the truncation of a virtual layer-resolution progressive
0742:             * codestream.
0743:             * */
0744:            private void allocateRate() throws IOException {
0745:                int stopOff = tnbytes;
0746:
0747:                // In parsing mode, the bitrate is allocated related to each tile's
0748:                // length in the bit stream
0749:
0750:                // EOC marker's length
0751:                if (remainingTileParts == 0)
0752:                    anbytes += 2;
0753:
0754:                // If there are too few bytes to read the tile part headers throw an
0755:                // error
0756:                if (anbytes > stopOff) {
0757:                    throw new Error(
0758:                            "Requested bitrate is too small for parsing");
0759:                }
0760:
0761:                // Calculate bitrate for each tile
0762:                int rem = stopOff - anbytes;
0763:                int totnByte = rem;
0764:                for (int t = nt - 1; t > 0; t--) {
0765:                    rem -= nBytes[t] = (int) (totnByte * (totTileLen[t] / totAllTileLen));
0766:                }
0767:                nBytes[0] = rem;
0768:            }
0769:
0770:            /**
0771:             * Reads SOT marker segment of the tile-part header and calls related
0772:             * methods of the HeaderDecoder to read other markers segments. The
0773:             * tile-part header is entirely read when a SOD marker is encountered.
0774:             *
0775:             * @return The tile number of the tile part that was read
0776:             * */
0777:            private int readTilePartHeader() throws IOException {
0778:                HeaderInfo.SOT ms = hi.getNewSOT();
0779:
0780:                // SOT marker
0781:                short marker = in.readShort();
0782:                if (marker != SOT) {
0783:                    if (marker == EOC) {
0784:                        isEOCFound = true;
0785:                        return -1;
0786:                    } else {
0787:                        throw new CorruptedCodestreamException(
0788:                                "SOT tag not found " + "in tile-part start");
0789:                    }
0790:                }
0791:                isEOCFound = false;
0792:
0793:                // Lsot (shall equals 10)
0794:                int lsot = in.readUnsignedShort();
0795:                ms.lsot = lsot;
0796:                if (lsot != 10)
0797:                    throw new CorruptedCodestreamException("Wrong length for "
0798:                            + "SOT marker segment: " + lsot);
0799:
0800:                // Isot
0801:                int tile = in.readUnsignedShort();
0802:                ms.isot = tile;
0803:                if (tile > 65534) {
0804:                    throw new CorruptedCodestreamException(
0805:                            "Tile index too high in " + "tile-part.");
0806:                }
0807:
0808:                // Psot
0809:                int psot = in.readInt();
0810:                ms.psot = psot;
0811:                isPsotEqualsZero = (psot != 0) ? false : true;
0812:                if (psot < 0) {
0813:                    throw new NotImplementedError("Tile length larger "
0814:                            + "than maximum supported");
0815:                }
0816:                // TPsot
0817:                int tilePart = in.read();
0818:                ms.tpsot = tilePart;
0819:                if (tilePart != tilePartsRead[tile] || tilePart < 0
0820:                        || tilePart > 254) {
0821:                    throw new CorruptedCodestreamException(
0822:                            "Out of order tile-part");
0823:                }
0824:                // TNsot
0825:                int nrOfTileParts = in.read();
0826:                ms.tnsot = nrOfTileParts;
0827:                hi.sot.put("t" + tile + "_tp" + tilePart, ms);
0828:                if (nrOfTileParts == 0) { // The number of tile-part is not specified in
0829:                    // this tile-part header.
0830:
0831:                    // Assumes that there will be another tile-part in the codestream
0832:                    // that will indicate the number of tile-parts for this tile)
0833:                    int nExtraTp;
0834:                    if (tileParts[tile] == 0
0835:                            || tileParts[tile] == tilePartLen.length) {
0836:                        // Then there are two tile-parts (one is the current and the
0837:                        // other will indicate the number of tile-part for this tile)
0838:                        nExtraTp = 2;
0839:                        remainingTileParts += 1;
0840:                    } else {
0841:                        // There is already one scheduled extra tile-part. In this
0842:                        // case just add place for the current one
0843:                        nExtraTp = 1;
0844:                    }
0845:
0846:                    tileParts[tile] += nExtraTp;
0847:                    nrOfTileParts = tileParts[tile];
0848:                    FacilityManager
0849:                            .getMsgLogger()
0850:                            .printmsg(
0851:                                    MsgLogger.WARNING,
0852:                                    "Header of tile-part "
0853:                                            + tilePart
0854:                                            + " of tile "
0855:                                            + tile
0856:                                            + ", does not indicate the total"
0857:                                            + " number of tile-parts. Assuming that there are "
0858:                                            + nrOfTileParts
0859:                                            + " tile-parts for this tile.");
0860:
0861:                    // Increase and re-copy tilePartLen array
0862:                    int[] tmpA = tilePartLen[tile];
0863:                    tilePartLen[tile] = new int[nrOfTileParts];
0864:                    for (int i = 0; i < nrOfTileParts - nExtraTp; i++) {
0865:                        tilePartLen[tile][i] = tmpA[i];
0866:                    }
0867:                    // Increase and re-copy tilePartNum array
0868:                    tmpA = tilePartNum[tile];
0869:                    tilePartNum[tile] = new int[nrOfTileParts];
0870:                    for (int i = 0; i < nrOfTileParts - nExtraTp; i++) {
0871:                        tilePartNum[tile][i] = tmpA[i];
0872:                    }
0873:
0874:                    // Increase and re-copy firsPackOff array
0875:                    tmpA = firstPackOff[tile];
0876:                    firstPackOff[tile] = new int[nrOfTileParts];
0877:                    for (int i = 0; i < nrOfTileParts - nExtraTp; i++) {
0878:                        firstPackOff[tile][i] = tmpA[i];
0879:                    }
0880:
0881:                    // Increase and re-copy tilePartHeadLen array
0882:                    tmpA = tilePartHeadLen[tile];
0883:                    tilePartHeadLen[tile] = new int[nrOfTileParts];
0884:                    for (int i = 0; i < nrOfTileParts - nExtraTp; i++) {
0885:                        tilePartHeadLen[tile][i] = tmpA[i];
0886:                    }
0887:                } else { // The number of tile-parts is specified in the tile-part
0888:                    // header
0889:                    totTileParts[tile] = nrOfTileParts;
0890:
0891:                    // Check if it is consistant with what was found in previous
0892:                    // tile-part headers
0893:
0894:                    if (tileParts[tile] == 0) { // First tile-part: OK
0895:                        remainingTileParts += nrOfTileParts - 1;
0896:                        tileParts[tile] = nrOfTileParts;
0897:                        tilePartLen[tile] = new int[nrOfTileParts];
0898:                        tilePartNum[tile] = new int[nrOfTileParts];
0899:                        firstPackOff[tile] = new int[nrOfTileParts];
0900:                        tilePartHeadLen[tile] = new int[nrOfTileParts];
0901:                    } else if (tileParts[tile] > nrOfTileParts) {
0902:                        // Already found more tile-parts than signaled here
0903:                        throw new CorruptedCodestreamException(
0904:                                "Invalid number " + "of tile-parts in"
0905:                                        + " tile " + tile + ": "
0906:                                        + nrOfTileParts);
0907:                    } else { // Signaled number of tile-part fits with number of
0908:                        // previously found tile-parts
0909:                        remainingTileParts += nrOfTileParts - tileParts[tile];
0910:
0911:                        if (tileParts[tile] != nrOfTileParts) {
0912:
0913:                            // Increase and re-copy tilePartLen array
0914:                            int[] tmpA = tilePartLen[tile];
0915:                            tilePartLen[tile] = new int[nrOfTileParts];
0916:                            for (int i = 0; i < tileParts[tile] - 1; i++) {
0917:                                tilePartLen[tile][i] = tmpA[i];
0918:                            }
0919:
0920:                            // Increase and re-copy tilePartNum array
0921:                            tmpA = tilePartNum[tile];
0922:                            tilePartNum[tile] = new int[nrOfTileParts];
0923:                            for (int i = 0; i < tileParts[tile] - 1; i++) {
0924:                                tilePartNum[tile][i] = tmpA[i];
0925:                            }
0926:
0927:                            // Increase and re-copy firstPackOff array
0928:                            tmpA = firstPackOff[tile];
0929:                            firstPackOff[tile] = new int[nrOfTileParts];
0930:                            for (int i = 0; i < tileParts[tile] - 1; i++) {
0931:                                firstPackOff[tile][i] = tmpA[i];
0932:                            }
0933:
0934:                            // Increase and re-copy tilePartHeadLen array
0935:                            tmpA = tilePartHeadLen[tile];
0936:                            tilePartHeadLen[tile] = new int[nrOfTileParts];
0937:                            for (int i = 0; i < tileParts[tile] - 1; i++) {
0938:                                tilePartHeadLen[tile][i] = tmpA[i];
0939:                            }
0940:                        }
0941:                    }
0942:                }
0943:
0944:                // Other markers
0945:                hd.resetHeaderMarkers();
0946:                hd.nTileParts[tile] = nrOfTileParts;
0947:                // Decode and store the tile-part header (i.e. until a SOD marker is
0948:                // found)
0949:                do {
0950:                    hd.extractTilePartMarkSeg(in.readShort(), in, tile,
0951:                            tilePart);
0952:                } while ((hd.getNumFoundMarkSeg() & hd.SOD_FOUND) == 0);
0953:
0954:                // Read each marker segment previously found
0955:                hd.readFoundTilePartMarkSeg(tile, tilePart);
0956:
0957:                tilePartLen[tile][tilePart] = psot;
0958:
0959:                tilePartNum[tile][tilePart] = totTilePartsRead;
0960:                totTilePartsRead++;
0961:
0962:                // Add to list of which tile each successive tile-part belongs.
0963:                // This list is needed if there are PPM markers used
0964:                hd.setTileOfTileParts(tile);
0965:
0966:                return tile;
0967:
0968:            }
0969:
0970:            /**
0971:             * Reads packets of the current tile according to the
0972:             * layer-resolution-component-position progressiveness.
0973:             *
0974:             * @param lys Index of the first layer for each component and resolution.
0975:             *
0976:             * @param lye Index of the last layer.
0977:             *
0978:             * @param ress Index of the first resolution level.
0979:             *
0980:             * @param rese Index of the last resolution level.
0981:             *
0982:             * @param comps Index of the first component.
0983:             *
0984:             * @param compe Index of the last component.
0985:             *
0986:             * @return True if rate has been reached.
0987:             * */
0988:            private boolean readLyResCompPos(int[][] lys, int lye, int ress,
0989:                    int rese, int comps, int compe) throws IOException {
0990:
0991:                int minlys = 10000;
0992:                for (int c = comps; c < compe; c++) { //loop on components
0993:                    // Check if this component exists
0994:                    if (c >= mdl.length)
0995:                        continue;
0996:
0997:                    for (int r = ress; r < rese; r++) {//loop on resolution levels
0998:                        if (lys[c] != null && r < lys[c].length
0999:                                && lys[c][r] < minlys) {
1000:                            minlys = lys[c][r];
1001:                        }
1002:                    }
1003:                }
1004:
1005:                int t = getTileIdx();
1006:                int start;
1007:                boolean status = false;
1008:                int lastByte = firstPackOff[t][curTilePart]
1009:                        + tilePartLen[t][curTilePart] - 1
1010:                        - tilePartHeadLen[t][curTilePart];
1011:                int numLayers = ((Integer) decSpec.nls.getTileDef(t))
1012:                        .intValue();
1013:                int nPrec = 1;
1014:                int hlen, plen;
1015:                String strInfo = printInfo ? "Tile " + getTileIdx()
1016:                        + " (tile-part:" + curTilePart
1017:                        + "): offset, length, header length\n" : null;
1018:                boolean pph = false;
1019:                if (((Boolean) decSpec.pphs.getTileDef(t)).booleanValue()) {
1020:                    pph = true;
1021:                }
1022:                for (int l = minlys; l < lye; l++) { // loop on layers
1023:                    for (int r = ress; r < rese; r++) { // loop on resolution levels
1024:                        for (int c = comps; c < compe; c++) { // loop on components
1025:                            // Checks if component exists
1026:                            if (c >= mdl.length)
1027:                                continue;
1028:                            // Checks if resolution level exists
1029:                            if (r >= lys[c].length)
1030:                                continue;
1031:                            if (r > mdl[c])
1032:                                continue;
1033:                            // Checks if layer exists
1034:                            if (l < lys[c][r] || l >= numLayers)
1035:                                continue;
1036:
1037:                            nPrec = pktDec.getNumPrecinct(c, r);
1038:                            for (int p = 0; p < nPrec; p++) { // loop on precincts
1039:                                start = in.getPos();
1040:
1041:                                // If packed packet headers are used, there is no need
1042:                                // to check that there are bytes enough to read header
1043:                                if (pph) {
1044:                                    pktDec.readPktHead(l, r, c, p, cbI[c][r],
1045:                                            nBytes);
1046:                                }
1047:
1048:                                // If we are about to read outside of tile-part,
1049:                                // skip to next tile-part
1050:                                if (start > lastByte
1051:                                        && curTilePart < firstPackOff[t].length - 1) {
1052:                                    curTilePart++;
1053:                                    in.seek(firstPackOff[t][curTilePart]);
1054:                                    lastByte = in.getPos()
1055:                                            + tilePartLen[t][curTilePart] - 1
1056:                                            - tilePartHeadLen[t][curTilePart];
1057:                                }
1058:
1059:                                // Read SOP marker segment if necessary
1060:                                status = pktDec.readSOPMarker(nBytes, p, c, r);
1061:
1062:                                if (status) {
1063:                                    if (printInfo) {
1064:                                        FacilityManager.getMsgLogger()
1065:                                                .printmsg(MsgLogger.INFO,
1066:                                                        strInfo);
1067:                                    }
1068:                                    return true;
1069:                                }
1070:
1071:                                if (!pph) {
1072:                                    status = pktDec.readPktHead(l, r, c, p,
1073:                                            cbI[c][r], nBytes);
1074:                                }
1075:
1076:                                if (status) {
1077:                                    if (printInfo) {
1078:                                        FacilityManager.getMsgLogger()
1079:                                                .printmsg(MsgLogger.INFO,
1080:                                                        strInfo);
1081:                                    }
1082:                                    return true;
1083:                                }
1084:
1085:                                // Store packet's head length
1086:                                hlen = in.getPos() - start;
1087:                                pktHL.addElement(new Integer(hlen));
1088:
1089:                                // Reads packet's body
1090:                                status = pktDec.readPktBody(l, r, c, p,
1091:                                        cbI[c][r], nBytes);
1092:                                plen = in.getPos() - start;
1093:                                if (printInfo)
1094:                                    strInfo += " Pkt l=" + l + ",r=" + r
1095:                                            + ",c=" + c + ",p=" + p + ": "
1096:                                            + start + ", " + plen + ", " + hlen
1097:                                            + "\n";
1098:
1099:                                if (status) {
1100:                                    if (printInfo) {
1101:                                        FacilityManager.getMsgLogger()
1102:                                                .printmsg(MsgLogger.INFO,
1103:                                                        strInfo);
1104:                                    }
1105:                                    return true;
1106:                                }
1107:
1108:                            } // end loop on precincts
1109:                        } // end loop on components
1110:                    } // end loop on resolution levels
1111:                } // end loop on layers
1112:
1113:                if (printInfo) {
1114:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1115:                            strInfo);
1116:                }
1117:                return false; // Decoding rate was not reached
1118:            }
1119:
1120:            /**
1121:             * Reads packets of the current tile according to the
1122:             * resolution-layer-component-position progressiveness.
1123:             *
1124:             * @param lys Index of the first layer for each component and resolution.
1125:             *
1126:             * @param lye Index of the last layer.
1127:             *
1128:             * @param ress Index of the first resolution level.
1129:             *
1130:             * @param rese Index of the last resolution level.
1131:             *
1132:             * @param comps Index of the first component.
1133:             *
1134:             * @param compe Index of the last component.
1135:             *
1136:             * @return True if rate has been reached.
1137:             * */
1138:            private boolean readResLyCompPos(int lys[][], int lye, int ress,
1139:                    int rese, int comps, int compe) throws IOException {
1140:
1141:                int t = getTileIdx(); // Current tile index
1142:                boolean status = false; // True if decoding rate is reached when
1143:                int lastByte = firstPackOff[t][curTilePart]
1144:                        + tilePartLen[t][curTilePart] - 1
1145:                        - tilePartHeadLen[t][curTilePart];
1146:                int minlys = 10000;
1147:                for (int c = comps; c < compe; c++) { //loop on components
1148:                    // Check if this component exists
1149:                    if (c >= mdl.length)
1150:                        continue;
1151:
1152:                    for (int r = ress; r < rese; r++) {//loop on resolution levels
1153:                        if (r > mdl[c])
1154:                            continue;
1155:                        if (lys[c] != null && r < lys[c].length
1156:                                && lys[c][r] < minlys) {
1157:                            minlys = lys[c][r];
1158:                        }
1159:                    }
1160:                }
1161:
1162:                String strInfo = printInfo ? "Tile " + getTileIdx()
1163:                        + " (tile-part:" + curTilePart
1164:                        + "): offset, length, header length\n" : null;
1165:                int numLayers = ((Integer) decSpec.nls.getTileDef(t))
1166:                        .intValue();
1167:                boolean pph = false;
1168:                if (((Boolean) decSpec.pphs.getTileDef(t)).booleanValue()) {
1169:                    pph = true;
1170:                }
1171:                int nPrec = 1;
1172:                int start;
1173:                int hlen, plen;
1174:                for (int r = ress; r < rese; r++) { // loop on resolution levels
1175:                    for (int l = minlys; l < lye; l++) { // loop on layers
1176:                        for (int c = comps; c < compe; c++) { // loop on components
1177:                            // Checks if component exists
1178:                            if (c >= mdl.length)
1179:                                continue;
1180:                            // Checks if resolution level exists
1181:                            if (r > mdl[c])
1182:                                continue;
1183:                            if (r >= lys[c].length)
1184:                                continue;
1185:                            // Checks if layer exists
1186:                            if (l < lys[c][r] || l >= numLayers)
1187:                                continue;
1188:
1189:                            nPrec = pktDec.getNumPrecinct(c, r);
1190:
1191:                            for (int p = 0; p < nPrec; p++) { // loop on precincts
1192:                                start = in.getPos();
1193:
1194:                                // If packed packet headers are used, there is no need
1195:                                // to check that there are bytes enough to read header
1196:                                if (pph) {
1197:                                    pktDec.readPktHead(l, r, c, p, cbI[c][r],
1198:                                            nBytes);
1199:                                }
1200:
1201:                                // If we are about to read outside of tile-part,
1202:                                // skip to next tile-part
1203:                                if (start > lastByte
1204:                                        && curTilePart < firstPackOff[t].length - 1) {
1205:                                    curTilePart++;
1206:                                    in.seek(firstPackOff[t][curTilePart]);
1207:                                    lastByte = in.getPos()
1208:                                            + tilePartLen[t][curTilePart] - 1
1209:                                            - tilePartHeadLen[t][curTilePart];
1210:                                }
1211:
1212:                                // Read SOP marker segment if necessary
1213:                                status = pktDec.readSOPMarker(nBytes, p, c, r);
1214:
1215:                                if (status) {
1216:                                    if (printInfo) {
1217:                                        FacilityManager.getMsgLogger()
1218:                                                .printmsg(MsgLogger.INFO,
1219:                                                        strInfo);
1220:                                    }
1221:                                    return true;
1222:                                }
1223:
1224:                                if (!pph) {
1225:                                    status = pktDec.readPktHead(l, r, c, p,
1226:                                            cbI[c][r], nBytes);
1227:                                }
1228:
1229:                                if (status) {
1230:                                    if (printInfo) {
1231:                                        FacilityManager.getMsgLogger()
1232:                                                .printmsg(MsgLogger.INFO,
1233:                                                        strInfo);
1234:                                    }
1235:                                    // Output rate of EOF reached
1236:                                    return true;
1237:                                }
1238:
1239:                                // Store packet's head length
1240:                                hlen = in.getPos() - start;
1241:                                pktHL.addElement(new Integer(hlen));
1242:
1243:                                // Reads packet's body
1244:                                status = pktDec.readPktBody(l, r, c, p,
1245:                                        cbI[c][r], nBytes);
1246:                                plen = in.getPos() - start;
1247:                                if (printInfo)
1248:                                    strInfo += " Pkt l=" + l + ",r=" + r
1249:                                            + ",c=" + c + ",p=" + p + ": "
1250:                                            + start + ", " + plen + ", " + hlen
1251:                                            + "\n";
1252:
1253:                                if (status) {
1254:                                    if (printInfo) {
1255:                                        FacilityManager.getMsgLogger()
1256:                                                .printmsg(MsgLogger.INFO,
1257:                                                        strInfo);
1258:                                    }
1259:                                    // Output rate or EOF reached
1260:                                    return true;
1261:                                }
1262:
1263:                            } // end loop on precincts
1264:                        } // end loop on components
1265:                    } // end loop on layers
1266:                } // end loop on resolution levels
1267:
1268:                if (printInfo) {
1269:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1270:                            strInfo);
1271:                }
1272:                return false; // Decoding rate was not reached
1273:            }
1274:
1275:            /**
1276:             * Reads packets of the current tile according to the
1277:             * resolution-position-component-layer progressiveness.
1278:             *
1279:             * @param lys Index of the first layer for each component and resolution.
1280:             *
1281:             * @param lye Index of the last layer.
1282:             *
1283:             * @param ress Index of the first resolution level.
1284:             *
1285:             * @param rese Index of the last resolution level.
1286:             *
1287:             * @param comps Index of the first component.
1288:             *
1289:             * @param compe Index of the last component.
1290:             *
1291:             * @return True if rate has been reached.
1292:             * */
1293:            private boolean readResPosCompLy(int[][] lys, int lye, int ress,
1294:                    int rese, int comps, int compe) throws IOException {
1295:                // Computes current tile offset in the reference grid
1296:
1297:                Point nTiles = getNumTiles(null);
1298:                Point tileI = getTile(null);
1299:                int x0siz = hd.getImgULX();
1300:                int y0siz = hd.getImgULY();
1301:                int xsiz = x0siz + hd.getImgWidth();
1302:                int ysiz = y0siz + hd.getImgHeight();
1303:                int xt0siz = getTilePartULX();
1304:                int yt0siz = getTilePartULY();
1305:                int xtsiz = getNomTileWidth();
1306:                int ytsiz = getNomTileHeight();
1307:                int tx0 = (tileI.x == 0) ? x0siz : xt0siz + tileI.x * xtsiz;
1308:                int ty0 = (tileI.y == 0) ? y0siz : yt0siz + tileI.y * ytsiz;
1309:                int tx1 = (tileI.x != nTiles.x - 1) ? xt0siz + (tileI.x + 1)
1310:                        * xtsiz : xsiz;
1311:                int ty1 = (tileI.y != nTiles.y - 1) ? yt0siz + (tileI.y + 1)
1312:                        * ytsiz : ysiz;
1313:
1314:                // Get precinct information (number,distance between two consecutive
1315:                // precincts in the reference grid) in each component and resolution
1316:                // level
1317:                int t = getTileIdx(); // Current tile index
1318:                PrecInfo prec; // temporary variable
1319:                int p; // Current precinct index
1320:                int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
1321:                int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
1322:                int nPrec = 0; // Total number of found precincts
1323:                int[][] nextPrec = new int[compe][]; // Next precinct index in each
1324:                // component and resolution level
1325:                int minlys = 100000; // minimum layer start index of each component
1326:                int minx = tx1; // Horiz. offset of the second precinct in the
1327:                // reference grid
1328:                int miny = ty1; // Vert. offset of the second precinct in the
1329:                // reference grid.
1330:                int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
1331:                int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
1332:                Point numPrec;
1333:                for (int c = comps; c < compe; c++) { // components
1334:                    for (int r = ress; r < rese; r++) { // resolution levels
1335:                        if (c >= mdl.length)
1336:                            continue;
1337:                        if (r > mdl[c])
1338:                            continue;
1339:                        nextPrec[c] = new int[mdl[c] + 1];
1340:                        if (lys[c] != null && r < lys[c].length
1341:                                && lys[c][r] < minlys) {
1342:                            minlys = lys[c][r];
1343:                        }
1344:                        p = pktDec.getNumPrecinct(c, r) - 1;
1345:                        for (; p >= 0; p--) {
1346:                            prec = pktDec.getPrecInfo(c, r, p);
1347:                            if (prec.rgulx != tx0) {
1348:                                if (prec.rgulx < minx)
1349:                                    minx = prec.rgulx;
1350:                                if (prec.rgulx > maxx)
1351:                                    maxx = prec.rgulx;
1352:                            }
1353:                            if (prec.rguly != ty0) {
1354:                                if (prec.rguly < miny)
1355:                                    miny = prec.rguly;
1356:                                if (prec.rguly > maxy)
1357:                                    maxy = prec.rguly;
1358:                            }
1359:
1360:                            if (nPrec == 0) {
1361:                                gcd_x = prec.rgw;
1362:                                gcd_y = prec.rgh;
1363:                            } else {
1364:                                gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
1365:                                gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
1366:                            }
1367:                            nPrec++;
1368:                        } // precincts
1369:                    } // resolution levels
1370:                } // components
1371:
1372:                if (nPrec == 0) {
1373:                    throw new Error("Image cannot have no precinct");
1374:                }
1375:
1376:                int pyend = (maxy - miny) / gcd_y + 1;
1377:                int pxend = (maxx - minx) / gcd_x + 1;
1378:                int x, y;
1379:                int hlen, plen;
1380:                int start;
1381:                boolean status = false;
1382:                int lastByte = firstPackOff[t][curTilePart]
1383:                        + tilePartLen[t][curTilePart] - 1
1384:                        - tilePartHeadLen[t][curTilePart];
1385:                int numLayers = ((Integer) decSpec.nls.getTileDef(t))
1386:                        .intValue();
1387:                String strInfo = printInfo ? "Tile " + getTileIdx()
1388:                        + " (tile-part:" + curTilePart
1389:                        + "): offset, length, header length\n" : null;
1390:                boolean pph = false;
1391:                if (((Boolean) decSpec.pphs.getTileDef(t)).booleanValue()) {
1392:                    pph = true;
1393:                }
1394:                for (int r = ress; r < rese; r++) { // loop on resolution levels
1395:                    y = ty0;
1396:                    x = tx0;
1397:                    for (int py = 0; py <= pyend; py++) { // Vertical precincts
1398:                        for (int px = 0; px <= pxend; px++) { // Horiz. precincts
1399:                            for (int c = comps; c < compe; c++) { // Components
1400:                                if (c >= mdl.length)
1401:                                    continue;
1402:                                if (r > mdl[c])
1403:                                    continue;
1404:                                if (nextPrec[c][r] >= pktDec.getNumPrecinct(c,
1405:                                        r)) {
1406:                                    continue;
1407:                                }
1408:                                prec = pktDec.getPrecInfo(c, r, nextPrec[c][r]);
1409:                                if ((prec.rgulx != x) || (prec.rguly != y)) {
1410:                                    continue;
1411:                                }
1412:                                for (int l = minlys; l < lye; l++) { // layers
1413:                                    if (r >= lys[c].length)
1414:                                        continue;
1415:                                    if (l < lys[c][r] || l >= numLayers)
1416:                                        continue;
1417:
1418:                                    start = in.getPos();
1419:
1420:                                    // If packed packet headers are used, there is no
1421:                                    // need to check that there are bytes enough to
1422:                                    // read header
1423:                                    if (pph) {
1424:                                        pktDec.readPktHead(l, r, c,
1425:                                                nextPrec[c][r], cbI[c][r],
1426:                                                nBytes);
1427:                                    }
1428:                                    // If we are about to read outside of tile-part,
1429:                                    // skip to next tile-part
1430:                                    if (start > lastByte
1431:                                            && curTilePart < firstPackOff[t].length - 1) {
1432:                                        curTilePart++;
1433:                                        in.seek(firstPackOff[t][curTilePart]);
1434:                                        lastByte = in.getPos()
1435:                                                + tilePartLen[t][curTilePart]
1436:                                                - 1
1437:                                                - tilePartHeadLen[t][curTilePart];
1438:                                    }
1439:
1440:                                    // Read SOP marker segment if necessary
1441:                                    status = pktDec.readSOPMarker(nBytes,
1442:                                            nextPrec[c][r], c, r);
1443:
1444:                                    if (status) {
1445:                                        if (printInfo) {
1446:                                            FacilityManager.getMsgLogger()
1447:                                                    .printmsg(MsgLogger.INFO,
1448:                                                            strInfo);
1449:                                        }
1450:                                        return true;
1451:                                    }
1452:
1453:                                    if (!pph) {
1454:                                        status = pktDec.readPktHead(l, r, c,
1455:                                                nextPrec[c][r], cbI[c][r],
1456:                                                nBytes);
1457:                                    }
1458:
1459:                                    if (status) {
1460:                                        if (printInfo) {
1461:                                            FacilityManager.getMsgLogger()
1462:                                                    .printmsg(MsgLogger.INFO,
1463:                                                            strInfo);
1464:                                        }
1465:                                        return true;
1466:                                    }
1467:
1468:                                    // Store packet's head length
1469:                                    hlen = in.getPos() - start;
1470:                                    pktHL.addElement(new Integer(hlen));
1471:
1472:                                    // Reads packet's body
1473:                                    status = pktDec.readPktBody(l, r, c,
1474:                                            nextPrec[c][r], cbI[c][r], nBytes);
1475:                                    plen = in.getPos() - start;
1476:                                    if (printInfo)
1477:                                        strInfo += " Pkt l=" + l + ",r=" + r
1478:                                                + ",c=" + c + ",p="
1479:                                                + nextPrec[c][r] + ": " + start
1480:                                                + ", " + plen + ", " + hlen
1481:                                                + "\n";
1482:
1483:                                    if (status) {
1484:                                        if (printInfo) {
1485:                                            FacilityManager.getMsgLogger()
1486:                                                    .printmsg(MsgLogger.INFO,
1487:                                                            strInfo);
1488:                                        }
1489:                                        return true;
1490:                                    }
1491:                                } // layers
1492:                                nextPrec[c][r]++;
1493:                            } // Components
1494:                            if (px != pxend) {
1495:                                x = minx + px * gcd_x;
1496:                            } else {
1497:                                x = tx0;
1498:                            }
1499:                        } // Horizontal precincts
1500:                        if (py != pyend) {
1501:                            y = miny + py * gcd_y;
1502:                        } else {
1503:                            y = ty0;
1504:                        }
1505:                    } // Vertical precincts
1506:                } // end loop on resolution levels
1507:
1508:                if (printInfo) {
1509:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1510:                            strInfo);
1511:                }
1512:                return false; // Decoding rate was not reached
1513:            }
1514:
1515:            /**
1516:             * Reads packets of the current tile according to the
1517:             * position-component-resolution-layer progressiveness.
1518:             *
1519:             * @param lys Index of the first layer for each component and resolution.
1520:             *
1521:             * @param lye Index of the last layer.
1522:             *
1523:             * @param ress Index of the first resolution level.
1524:             *
1525:             * @param rese Index of the last resolution level.
1526:             *
1527:             * @param comps Index of the first component.
1528:             *
1529:             * @param compe Index of the last component.
1530:             *
1531:             * @return True if rate has been reached.
1532:             * */
1533:            private boolean readPosCompResLy(int[][] lys, int lye, int ress,
1534:                    int rese, int comps, int compe) throws IOException {
1535:                Point nTiles = getNumTiles(null);
1536:                Point tileI = getTile(null);
1537:                int x0siz = hd.getImgULX();
1538:                int y0siz = hd.getImgULY();
1539:                int xsiz = x0siz + hd.getImgWidth();
1540:                int ysiz = y0siz + hd.getImgHeight();
1541:                int xt0siz = getTilePartULX();
1542:                int yt0siz = getTilePartULY();
1543:                int xtsiz = getNomTileWidth();
1544:                int ytsiz = getNomTileHeight();
1545:                int tx0 = (tileI.x == 0) ? x0siz : xt0siz + tileI.x * xtsiz;
1546:                int ty0 = (tileI.y == 0) ? y0siz : yt0siz + tileI.y * ytsiz;
1547:                int tx1 = (tileI.x != nTiles.x - 1) ? xt0siz + (tileI.x + 1)
1548:                        * xtsiz : xsiz;
1549:                int ty1 = (tileI.y != nTiles.y - 1) ? yt0siz + (tileI.y + 1)
1550:                        * ytsiz : ysiz;
1551:
1552:                // Get precinct information (number,distance between two consecutive
1553:                // precincts in the reference grid) in each component and resolution
1554:                // level
1555:                int t = getTileIdx(); // Current tile index
1556:                PrecInfo prec; // temporary variable
1557:                int p; // Current precinct index
1558:                int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
1559:                int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
1560:                int nPrec = 0; // Total number of found precincts
1561:                int[][] nextPrec = new int[compe][]; // Next precinct index in each
1562:                // component and resolution level
1563:                int minlys = 100000; // minimum layer start index of each component
1564:                int minx = tx1; // Horiz. offset of the second precinct in the
1565:                // reference grid
1566:                int miny = ty1; // Vert. offset of the second precinct in the
1567:                // reference grid.
1568:                int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
1569:                int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
1570:                Point numPrec;
1571:                for (int c = comps; c < compe; c++) { // components
1572:                    for (int r = ress; r < rese; r++) { // resolution levels
1573:                        if (c >= mdl.length)
1574:                            continue;
1575:                        if (r > mdl[c])
1576:                            continue;
1577:                        nextPrec[c] = new int[mdl[c] + 1];
1578:                        if (lys[c] != null && r < lys[c].length
1579:                                && lys[c][r] < minlys) {
1580:                            minlys = lys[c][r];
1581:                        }
1582:                        p = pktDec.getNumPrecinct(c, r) - 1;
1583:                        for (; p >= 0; p--) {
1584:                            prec = pktDec.getPrecInfo(c, r, p);
1585:                            if (prec.rgulx != tx0) {
1586:                                if (prec.rgulx < minx)
1587:                                    minx = prec.rgulx;
1588:                                if (prec.rgulx > maxx)
1589:                                    maxx = prec.rgulx;
1590:                            }
1591:                            if (prec.rguly != ty0) {
1592:                                if (prec.rguly < miny)
1593:                                    miny = prec.rguly;
1594:                                if (prec.rguly > maxy)
1595:                                    maxy = prec.rguly;
1596:                            }
1597:
1598:                            if (nPrec == 0) {
1599:                                gcd_x = prec.rgw;
1600:                                gcd_y = prec.rgh;
1601:                            } else {
1602:                                gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
1603:                                gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
1604:                            }
1605:                            nPrec++;
1606:                        } // precincts
1607:                    } // resolution levels
1608:                } // components
1609:
1610:                if (nPrec == 0) {
1611:                    throw new Error("Image cannot have no precinct");
1612:                }
1613:
1614:                int pyend = (maxy - miny) / gcd_y + 1;
1615:                int pxend = (maxx - minx) / gcd_x + 1;
1616:                int hlen, plen;
1617:                int start;
1618:                boolean status = false;
1619:                int lastByte = firstPackOff[t][curTilePart]
1620:                        + tilePartLen[t][curTilePart] - 1
1621:                        - tilePartHeadLen[t][curTilePart];
1622:                int numLayers = ((Integer) decSpec.nls.getTileDef(t))
1623:                        .intValue();
1624:                String strInfo = printInfo ? "Tile " + getTileIdx()
1625:                        + " (tile-part:" + curTilePart
1626:                        + "): offset, length, header length\n" : null;
1627:                boolean pph = false;
1628:                if (((Boolean) decSpec.pphs.getTileDef(t)).booleanValue()) {
1629:                    pph = true;
1630:                }
1631:
1632:                int y = ty0;
1633:                int x = tx0;
1634:                for (int py = 0; py <= pyend; py++) { // Vertical precincts
1635:                    for (int px = 0; px <= pxend; px++) { // Horiz. precincts
1636:                        for (int c = comps; c < compe; c++) { // Components
1637:                            if (c >= mdl.length)
1638:                                continue;
1639:                            for (int r = ress; r < rese; r++) { // Resolution levels
1640:                                if (r > mdl[c])
1641:                                    continue;
1642:                                if (nextPrec[c][r] >= pktDec.getNumPrecinct(c,
1643:                                        r)) {
1644:                                    continue;
1645:                                }
1646:                                prec = pktDec.getPrecInfo(c, r, nextPrec[c][r]);
1647:                                if ((prec.rgulx != x) || (prec.rguly != y)) {
1648:                                    continue;
1649:                                }
1650:                                for (int l = minlys; l < lye; l++) { // Layers
1651:                                    if (r >= lys[c].length)
1652:                                        continue;
1653:                                    if (l < lys[c][r] || l >= numLayers)
1654:                                        continue;
1655:
1656:                                    start = in.getPos();
1657:
1658:                                    // If packed packet headers are used, there is no
1659:                                    // need to check that there are bytes enough to
1660:                                    // read header
1661:                                    if (pph) {
1662:                                        pktDec.readPktHead(l, r, c,
1663:                                                nextPrec[c][r], cbI[c][r],
1664:                                                nBytes);
1665:                                    }
1666:                                    // Read SOP marker segment if necessary
1667:                                    status = pktDec.readSOPMarker(nBytes,
1668:                                            nextPrec[c][r], c, r);
1669:
1670:                                    if (status) {
1671:                                        if (printInfo) {
1672:                                            FacilityManager.getMsgLogger()
1673:                                                    .printmsg(MsgLogger.INFO,
1674:                                                            strInfo);
1675:                                        }
1676:                                        return true;
1677:                                    }
1678:
1679:                                    if (!pph) {
1680:                                        status = pktDec.readPktHead(l, r, c,
1681:                                                nextPrec[c][r], cbI[c][r],
1682:                                                nBytes);
1683:                                    }
1684:
1685:                                    if (status) {
1686:                                        if (printInfo) {
1687:                                            FacilityManager.getMsgLogger()
1688:                                                    .printmsg(MsgLogger.INFO,
1689:                                                            strInfo);
1690:                                        }
1691:                                        return true;
1692:                                    }
1693:
1694:                                    // Store packet's head length
1695:                                    hlen = in.getPos() - start;
1696:                                    pktHL.addElement(new Integer(hlen));
1697:
1698:                                    // Reads packet's body
1699:                                    status = pktDec.readPktBody(l, r, c,
1700:                                            nextPrec[c][r], cbI[c][r], nBytes);
1701:                                    plen = in.getPos() - start;
1702:                                    if (printInfo)
1703:                                        strInfo += " Pkt l=" + l + ",r=" + r
1704:                                                + ",c=" + c + ",p="
1705:                                                + nextPrec[c][r] + ": " + start
1706:                                                + ", " + plen + ", " + hlen
1707:                                                + "\n";
1708:
1709:                                    if (status) {
1710:                                        if (printInfo) {
1711:                                            FacilityManager.getMsgLogger()
1712:                                                    .printmsg(MsgLogger.INFO,
1713:                                                            strInfo);
1714:                                        }
1715:                                        return true;
1716:                                    }
1717:
1718:                                } // layers
1719:                                nextPrec[c][r]++;
1720:                            } // Resolution levels
1721:                        } // Components
1722:                        if (px != pxend) {
1723:                            x = minx + px * gcd_x;
1724:                        } else {
1725:                            x = tx0;
1726:                        }
1727:                    } // Horizontal precincts
1728:                    if (py != pyend) {
1729:                        y = miny + py * gcd_y;
1730:                    } else {
1731:                        y = ty0;
1732:                    }
1733:                } // Vertical precincts
1734:
1735:                if (printInfo) {
1736:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1737:                            strInfo);
1738:                }
1739:                return false; // Decoding rate was not reached
1740:            }
1741:
1742:            /**
1743:             * Reads packets of the current tile according to the
1744:             * component-position-resolution-layer progressiveness.
1745:             *
1746:             * @param lys Index of the first layer for each component and resolution.
1747:             *
1748:             * @param lye Index of the last layer.
1749:             *
1750:             * @param ress Index of the first resolution level.
1751:             *
1752:             * @param rese Index of the last resolution level.
1753:             *
1754:             * @param comps Index of the first component.
1755:             *
1756:             * @param compe Index of the last component.
1757:             *
1758:             * @return True if rate has been reached.
1759:             * */
1760:            private boolean readCompPosResLy(int lys[][], int lye, int ress,
1761:                    int rese, int comps, int compe) throws IOException {
1762:                Point nTiles = getNumTiles(null);
1763:                Point tileI = getTile(null);
1764:                int x0siz = hd.getImgULX();
1765:                int y0siz = hd.getImgULY();
1766:                int xsiz = x0siz + hd.getImgWidth();
1767:                int ysiz = y0siz + hd.getImgHeight();
1768:                int xt0siz = getTilePartULX();
1769:                int yt0siz = getTilePartULY();
1770:                int xtsiz = getNomTileWidth();
1771:                int ytsiz = getNomTileHeight();
1772:                int tx0 = (tileI.x == 0) ? x0siz : xt0siz + tileI.x * xtsiz;
1773:                int ty0 = (tileI.y == 0) ? y0siz : yt0siz + tileI.y * ytsiz;
1774:                int tx1 = (tileI.x != nTiles.x - 1) ? xt0siz + (tileI.x + 1)
1775:                        * xtsiz : xsiz;
1776:                int ty1 = (tileI.y != nTiles.y - 1) ? yt0siz + (tileI.y + 1)
1777:                        * ytsiz : ysiz;
1778:
1779:                // Get precinct information (number,distance between two consecutive
1780:                // precincts in the reference grid) in each component and resolution
1781:                // level
1782:                int t = getTileIdx(); // Current tile index
1783:                PrecInfo prec; // temporary variable
1784:                int p; // Current precinct index
1785:                int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid
1786:                int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid
1787:                int nPrec = 0; // Total number of found precincts
1788:                int[][] nextPrec = new int[compe][]; // Next precinct index in each
1789:                // component and resolution level
1790:                int minlys = 100000; // minimum layer start index of each component
1791:                int minx = tx1; // Horiz. offset of the second precinct in the
1792:                // reference grid
1793:                int miny = ty1; // Vert. offset of the second precinct in the
1794:                // reference grid.
1795:                int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid
1796:                int maxy = ty0; // Max. vert. offset of precincts in the ref. grid
1797:                Point numPrec;
1798:                for (int c = comps; c < compe; c++) { // components
1799:                    for (int r = ress; r < rese; r++) { // resolution levels
1800:                        if (c >= mdl.length)
1801:                            continue;
1802:                        if (r > mdl[c])
1803:                            continue;
1804:                        nextPrec[c] = new int[mdl[c] + 1];
1805:                        if (lys[c] != null && r < lys[c].length
1806:                                && lys[c][r] < minlys) {
1807:                            minlys = lys[c][r];
1808:                        }
1809:                        p = pktDec.getNumPrecinct(c, r) - 1;
1810:                        for (; p >= 0; p--) {
1811:                            prec = pktDec.getPrecInfo(c, r, p);
1812:                            if (prec.rgulx != tx0) {
1813:                                if (prec.rgulx < minx)
1814:                                    minx = prec.rgulx;
1815:                                if (prec.rgulx > maxx)
1816:                                    maxx = prec.rgulx;
1817:                            }
1818:                            if (prec.rguly != ty0) {
1819:                                if (prec.rguly < miny)
1820:                                    miny = prec.rguly;
1821:                                if (prec.rguly > maxy)
1822:                                    maxy = prec.rguly;
1823:                            }
1824:
1825:                            if (nPrec == 0) {
1826:                                gcd_x = prec.rgw;
1827:                                gcd_y = prec.rgh;
1828:                            } else {
1829:                                gcd_x = MathUtil.gcd(gcd_x, prec.rgw);
1830:                                gcd_y = MathUtil.gcd(gcd_y, prec.rgh);
1831:                            }
1832:                            nPrec++;
1833:                        } // precincts
1834:                    } // resolution levels
1835:                } // components
1836:
1837:                if (nPrec == 0) {
1838:                    throw new Error("Image cannot have no precinct");
1839:                }
1840:
1841:                int pyend = (maxy - miny) / gcd_y + 1;
1842:                int pxend = (maxx - minx) / gcd_x + 1;
1843:                int hlen, plen;
1844:                int start;
1845:                boolean status = false;
1846:                int lastByte = firstPackOff[t][curTilePart]
1847:                        + tilePartLen[t][curTilePart] - 1
1848:                        - tilePartHeadLen[t][curTilePart];
1849:                int numLayers = ((Integer) decSpec.nls.getTileDef(t))
1850:                        .intValue();
1851:                String strInfo = printInfo ? "Tile " + getTileIdx()
1852:                        + " (tile-part:" + curTilePart
1853:                        + "): offset, length, header length\n" : null;
1854:                boolean pph = false;
1855:                if (((Boolean) decSpec.pphs.getTileDef(t)).booleanValue()) {
1856:                    pph = true;
1857:                }
1858:
1859:                int x, y;
1860:                for (int c = comps; c < compe; c++) { // components
1861:                    if (c >= mdl.length)
1862:                        continue;
1863:                    y = ty0;
1864:                    x = tx0;
1865:                    for (int py = 0; py <= pyend; py++) { // Vertical precincts
1866:                        for (int px = 0; px <= pxend; px++) { // Horiz. precincts
1867:                            for (int r = ress; r < rese; r++) { // Resolution levels
1868:                                if (r > mdl[c])
1869:                                    continue;
1870:                                if (nextPrec[c][r] >= pktDec.getNumPrecinct(c,
1871:                                        r)) {
1872:                                    continue;
1873:                                }
1874:                                prec = pktDec.getPrecInfo(c, r, nextPrec[c][r]);
1875:                                if ((prec.rgulx != x) || (prec.rguly != y)) {
1876:                                    continue;
1877:                                }
1878:
1879:                                for (int l = minlys; l < lye; l++) { // Layers
1880:                                    if (r >= lys[c].length)
1881:                                        continue;
1882:                                    if (l < lys[c][r])
1883:                                        continue;
1884:
1885:                                    start = in.getPos();
1886:
1887:                                    // If packed packet headers are used, there is no
1888:                                    // need to check that there are bytes enough to
1889:                                    // read header
1890:                                    if (pph) {
1891:                                        pktDec.readPktHead(l, r, c,
1892:                                                nextPrec[c][r], cbI[c][r],
1893:                                                nBytes);
1894:                                    }
1895:                                    // If we are about to read outside of tile-part,
1896:                                    // skip to next tile-part
1897:                                    if (start > lastByte
1898:                                            && curTilePart < firstPackOff[t].length - 1) {
1899:                                        curTilePart++;
1900:                                        in.seek(firstPackOff[t][curTilePart]);
1901:                                        lastByte = in.getPos()
1902:                                                + tilePartLen[t][curTilePart]
1903:                                                - 1
1904:                                                - tilePartHeadLen[t][curTilePart];
1905:                                    }
1906:
1907:                                    // Read SOP marker segment if necessary
1908:                                    status = pktDec.readSOPMarker(nBytes,
1909:                                            nextPrec[c][r], c, r);
1910:
1911:                                    if (status) {
1912:                                        if (printInfo) {
1913:                                            FacilityManager.getMsgLogger()
1914:                                                    .printmsg(MsgLogger.INFO,
1915:                                                            strInfo);
1916:                                        }
1917:                                        return true;
1918:                                    }
1919:
1920:                                    if (!pph) {
1921:                                        status = pktDec.readPktHead(l, r, c,
1922:                                                nextPrec[c][r], cbI[c][r],
1923:                                                nBytes);
1924:                                    }
1925:
1926:                                    if (status) {
1927:                                        if (printInfo) {
1928:                                            FacilityManager.getMsgLogger()
1929:                                                    .printmsg(MsgLogger.INFO,
1930:                                                            strInfo);
1931:                                        }
1932:                                        return true;
1933:                                    }
1934:
1935:                                    // Store packet's head length
1936:                                    hlen = in.getPos() - start;
1937:                                    pktHL.addElement(new Integer(hlen));
1938:
1939:                                    // Reads packet's body
1940:                                    status = pktDec.readPktBody(l, r, c,
1941:                                            nextPrec[c][r], cbI[c][r], nBytes);
1942:                                    plen = in.getPos() - start;
1943:                                    if (printInfo)
1944:                                        strInfo += " Pkt l=" + l + ",r=" + r
1945:                                                + ",c=" + c + ",p="
1946:                                                + nextPrec[c][r] + ": " + start
1947:                                                + ", " + plen + ", " + hlen
1948:                                                + "\n";
1949:
1950:                                    if (status) {
1951:                                        if (printInfo) {
1952:                                            FacilityManager.getMsgLogger()
1953:                                                    .printmsg(MsgLogger.INFO,
1954:                                                            strInfo);
1955:                                        }
1956:                                        return true;
1957:                                    }
1958:
1959:                                } // layers
1960:                                nextPrec[c][r]++;
1961:                            } // Resolution levels
1962:                            if (px != pxend) {
1963:                                x = minx + px * gcd_x;
1964:                            } else {
1965:                                x = tx0;
1966:                            }
1967:                        } // Horizontal precincts
1968:                        if (py != pyend) {
1969:                            y = miny + py * gcd_y;
1970:                        } else {
1971:                            y = ty0;
1972:                        }
1973:                    } // Vertical precincts
1974:                } // components
1975:
1976:                if (printInfo) {
1977:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1978:                            strInfo);
1979:                }
1980:                return false; // Decoding rate was not reached
1981:            }
1982:
1983:            /**
1984:             * Finish initialization of members for specified tile, reads packets head
1985:             * of each tile and keeps location of each code-block's codewords. The
1986:             * last 2 tasks are done by calling specific methods of PktDecoder.
1987:             *
1988:             * <p>Then, if a parsing output rate is defined, it keeps information of
1989:             * first layers only. This operation simulates a creation of a
1990:             * layer-resolution-component progressive bit-stream which will be next
1991:             * truncated and decoded.</p>
1992:             *
1993:             * @param t Tile index
1994:             *
1995:             * @see PktDecoder
1996:             * */
1997:            private void readTilePkts(int t) throws IOException {
1998:                pktHL = new Vector();
1999:
2000:                int oldNBytes = nBytes[t];
2001:
2002:                // Number of layers
2003:                int nl = ((Integer) decSpec.nls.getTileDef(t)).intValue();
2004:
2005:                // If packed packet headers was used, get the packet headers for this
2006:                // tile
2007:                if (((Boolean) decSpec.pphs.getTileDef(t)).booleanValue()) {
2008:                    // Gets packed headers as separate input stream
2009:                    ByteArrayInputStream pphbais = hd.getPackedPktHead(t);
2010:
2011:                    // Restarts PktDecoder instance
2012:                    cbI = pktDec.restart(nc, mdl, nl, cbI, true, pphbais);
2013:                } else {
2014:                    // Restarts PktDecoder instance
2015:                    cbI = pktDec.restart(nc, mdl, nl, cbI, false, null);
2016:                }
2017:
2018:                // Reads packets of the tile according to the progression order
2019:                int[][] pocSpec = ((int[][]) decSpec.pcs.getTileDef(t));
2020:                int nChg = (pocSpec == null) ? 1 : pocSpec.length;
2021:
2022:                // Create an array containing information about changes (progression
2023:                // order type, layers index start, layer index end, resolution level
2024:                // start, resolution level end, component index start, component index
2025:                // end). There is one row per progresion order
2026:                int[][] change = new int[nChg][6];
2027:                int idx = 0; // Index of the current progression order
2028:
2029:                change[0][1] = 0; // layer start
2030:
2031:                if (pocSpec == null) {
2032:                    change[idx][0] = ((Integer) decSpec.pos.getTileDef(t))
2033:                            .intValue();
2034:                    // Progression type found in COx marker segments
2035:                    change[idx][1] = nl; // Layer index end
2036:                    change[idx][2] = 0; // resolution level start
2037:                    change[idx][3] = decSpec.dls.getMaxInTile(t) + 1; // res. level end
2038:                    change[idx][4] = 0; // Component index start
2039:                    change[idx][5] = nc; // Component index end
2040:                } else {
2041:                    for (idx = 0; idx < nChg; idx++) {
2042:                        change[idx][0] = pocSpec[idx][5];
2043:                        change[idx][1] = pocSpec[idx][2]; // layer end
2044:                        change[idx][2] = pocSpec[idx][0]; // res. lev. start
2045:                        change[idx][3] = pocSpec[idx][3]; // res. lev. end
2046:                        change[idx][4] = pocSpec[idx][1]; // Comp. index start
2047:                        change[idx][5] = pocSpec[idx][4]; // Comp. index end
2048:                    }
2049:                }
2050:
2051:                // Seeks to the first packet of the first tile-part
2052:                try {
2053:                    // If in truncation mode, the first tile-part may be beyond the
2054:                    // target decoding rate. In this case, the offset of the first
2055:                    // packet is not defined.
2056:                    if (isTruncMode && firstPackOff == null
2057:                            || firstPackOff[t] == null) {
2058:                        return;
2059:                    }
2060:                    in.seek(firstPackOff[t][0]);
2061:                } catch (EOFException e) {
2062:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.WARNING,
2063:                            "Codestream truncated in tile " + t);
2064:                    return;
2065:                }
2066:
2067:                curTilePart = 0;
2068:
2069:                // Start and end indexes for layers, resolution levels and components.
2070:                int lye, ress, rese, comps, compe;
2071:                boolean status = false;
2072:                int nb = nBytes[t];
2073:                int[][] lys = new int[nc][];
2074:                for (int c = 0; c < nc; c++) {
2075:                    lys[c] = new int[((Integer) decSpec.dls
2076:                            .getTileCompVal(t, c)).intValue() + 1];
2077:                }
2078:
2079:                try {
2080:                    for (int chg = 0; chg < nChg; chg++) {
2081:
2082:                        lye = change[chg][1];
2083:                        ress = change[chg][2];
2084:                        rese = change[chg][3];
2085:                        comps = change[chg][4];
2086:                        compe = change[chg][5];
2087:
2088:                        switch (change[chg][0]) {
2089:                        case LY_RES_COMP_POS_PROG:
2090:                            status = readLyResCompPos(lys, lye, ress, rese,
2091:                                    comps, compe);
2092:                            break;
2093:                        case RES_LY_COMP_POS_PROG:
2094:                            status = readResLyCompPos(lys, lye, ress, rese,
2095:                                    comps, compe);
2096:                            break;
2097:                        case RES_POS_COMP_LY_PROG:
2098:                            status = readResPosCompLy(lys, lye, ress, rese,
2099:                                    comps, compe);
2100:                            break;
2101:                        case POS_COMP_RES_LY_PROG:
2102:                            status = readPosCompResLy(lys, lye, ress, rese,
2103:                                    comps, compe);
2104:                            break;
2105:                        case COMP_POS_RES_LY_PROG:
2106:                            status = readCompPosResLy(lys, lye, ress, rese,
2107:                                    comps, compe);
2108:                            break;
2109:                        default:
2110:                            throw new IllegalArgumentException(
2111:                                    "Not recognized " + "progression type");
2112:                        }
2113:
2114:                        // Update next first layer index
2115:                        for (int c = comps; c < compe; c++) {
2116:                            if (c >= lys.length)
2117:                                continue;
2118:                            for (int r = ress; r < rese; r++) {
2119:                                if (r >= lys[c].length)
2120:                                    continue;
2121:                                lys[c][r] = lye;
2122:                            }
2123:                        }
2124:
2125:                        if (status || usePOCQuit) {
2126:                            break;
2127:                        }
2128:                    }
2129:                } catch (EOFException e) {
2130:                    // Should never happen. Truncated codestream are normally found by
2131:                    // the class constructor
2132:                    throw e;
2133:                }
2134:
2135:                // In truncation mode, update the number of read bytes
2136:                if (isTruncMode) {
2137:                    anbytes += nb - nBytes[t];
2138:
2139:                    // If truncation rate is reached
2140:                    if (status) {
2141:                        nBytes[t] = 0;
2142:                    }
2143:                } else if (nBytes[t] < (totTileLen[t] - totTileHeadLen[t])) {
2144:                    // In parsing mode, if there is not enough rate to entirely read the
2145:                    // tile. Then, parses the bit stream so as to create a virtual
2146:                    // layer-resolution-component progressive bit stream that will be
2147:                    // truncated and decoded afterwards.
2148:                    CBlkInfo cb;
2149:
2150:                    // Systematicaly reject all remaining code-blocks if one
2151:                    // code-block, at least, is refused.
2152:                    boolean reject;
2153:                    // Stop reading any data from the bit stream
2154:                    boolean stopCount = false;
2155:                    // Length of each packet's head (in an array)
2156:                    int[] pktHeadLen = new int[pktHL.size()];
2157:                    for (int i = pktHL.size() - 1; i >= 0; i--) {
2158:                        pktHeadLen[i] = ((Integer) pktHL.elementAt(i))
2159:                                .intValue();
2160:                    }
2161:
2162:                    // Parse each code-block, layer per layer until nBytes[t] is
2163:                    // reached
2164:                    reject = false;
2165:                    for (int l = 0; l < nl; l++) { // layers
2166:                        if (cbI == null)
2167:                            continue;
2168:                        int nc = cbI.length;
2169:
2170:                        int mres = 0;
2171:                        for (int c = 0; c < nc; c++) {
2172:                            if (cbI[c] != null && cbI[c].length > mres)
2173:                                mres = cbI[c].length;
2174:                        }
2175:                        for (int r = 0; r < mres; r++) { // resolutions
2176:
2177:                            int msub = 0;
2178:                            for (int c = 0; c < nc; c++) {
2179:                                if (cbI[c] != null && cbI[c][r] != null
2180:                                        && cbI[c][r].length > msub)
2181:                                    msub = cbI[c][r].length;
2182:                            }
2183:                            for (int s = 0; s < msub; s++) { // subbands
2184:                                // Only LL subband resolution level 0
2185:                                if (r == 0 && s != 0) {
2186:                                    continue;
2187:                                } else if (r != 0 && s == 0) {
2188:                                    // No LL subband in resolution level > 0
2189:                                    continue;
2190:                                }
2191:
2192:                                int mnby = 0;
2193:                                for (int c = 0; c < nc; c++) {
2194:                                    if (cbI[c] != null && cbI[c][r] != null
2195:                                            && cbI[c][r][s] != null
2196:                                            && cbI[c][r][s].length > mnby)
2197:                                        mnby = cbI[c][r][s].length;
2198:                                }
2199:                                for (int m = 0; m < mnby; m++) {
2200:
2201:                                    int mnbx = 0;
2202:                                    for (int c = 0; c < nc; c++) {
2203:                                        if (cbI[c] != null
2204:                                                && cbI[c][r] != null
2205:                                                && cbI[c][r][s] != null
2206:                                                && cbI[c][r][s][m] != null
2207:                                                && cbI[c][r][s][m].length > mnbx)
2208:                                            mnbx = cbI[c][r][s][m].length;
2209:                                    }
2210:                                    for (int n = 0; n < mnbx; n++) {
2211:
2212:                                        for (int c = 0; c < nc; c++) {
2213:
2214:                                            if (cbI[c] == null
2215:                                                    || cbI[c][r] == null
2216:                                                    || cbI[c][r][s] == null
2217:                                                    || cbI[c][r][s][m] == null
2218:                                                    || cbI[c][r][s][m][n] == null) {
2219:                                                continue;
2220:                                            }
2221:                                            cb = cbI[c][r][s][m][n];
2222:
2223:                                            // If no code-block has been refused until
2224:                                            // now
2225:                                            if (!reject) {
2226:                                                // Rate is to low to allow reading of
2227:                                                // packet's head
2228:                                                if (nBytes[t] < pktHeadLen[cb.pktIdx[l]]) {
2229:                                                    // Stop parsing
2230:                                                    stopCount = true;
2231:                                                    // Reject all next
2232:                                                    // code-blocks
2233:                                                    reject = true;
2234:                                                } else {
2235:                                                    // Rate is enough to read packet's
2236:                                                    // head
2237:                                                    if (!stopCount) {
2238:                                                        //If parsing was not stopped
2239:                                                        //Takes into account packet's
2240:                                                        //head length
2241:                                                        nBytes[t] -= pktHeadLen[cb.pktIdx[l]];
2242:                                                        anbytes += pktHeadLen[cb.pktIdx[l]];
2243:                                                        // Set packet's head length to
2244:                                                        // 0, so that it won't be
2245:                                                        // taken into account next
2246:                                                        // time
2247:                                                        pktHeadLen[cb.pktIdx[l]] = 0;
2248:                                                    }
2249:                                                }
2250:                                            }
2251:                                            // Code-block has no data in this layer
2252:                                            if (cb.len[l] == 0) {
2253:                                                continue;
2254:                                            }
2255:
2256:                                            // Accepts code-block if length is enough,
2257:                                            // if this code-block was not refused in a
2258:                                            // previous layer and if no code-block was
2259:                                            // refused in current component
2260:                                            if (cb.len[l] < nBytes[t]
2261:                                                    && !reject) {
2262:                                                nBytes[t] -= cb.len[l];
2263:                                                anbytes += cb.len[l];
2264:                                            } else {
2265:                                                // Refuses code-block
2266:                                                // Forgets code-block's data
2267:                                                cb.len[l] = cb.off[l] = cb.ntp[l] = 0;
2268:                                                // Refuses all other code-block in
2269:                                                // current and next component
2270:                                                reject = true;
2271:                                            }
2272:
2273:                                        } // End loop on components
2274:                                    } // End loop on horiz. code-blocks
2275:                                } // End loop on vert. code-blocks
2276:                            } // End loop on subbands
2277:                        } // End loop on resolutions
2278:                    } // End loop on layers
2279:                } else {
2280:                    // No parsing for this tile, adds tile's body to the total
2281:                    // number of read bytes.
2282:                    anbytes += totTileLen[t] - totTileHeadLen[t];
2283:                    if (t < getNumTiles() - 1) {
2284:                        nBytes[t + 1] += nBytes[t]
2285:                                - (totTileLen[t] - totTileHeadLen[t]);
2286:                    }
2287:                }
2288:
2289:                // In this method nBytes[t] might be changed.  This change will affect
2290:                // to decode this tile next time.  So cache the old nByte[t] and
2291:                // recover it here.  -- Qinghuai Gao
2292:                nBytes[t] = oldNBytes;
2293:            }
2294:
2295:            /**
2296:             * Changes the current tile, given the new indexes. An
2297:             * IllegalArgumentException is thrown if the indexes do not correspond to
2298:             * a valid tile.
2299:             *
2300:             * @param x The horizontal indexes the tile.
2301:             *
2302:             * @param y The vertical indexes of the new tile.
2303:             * */
2304:            public void setTile(int x, int y) {
2305:
2306:                int i; // counter
2307:                // Check validity of tile indexes
2308:                if (x < 0 || y < 0 || x >= ntX || y >= ntY) {
2309:                    throw new IllegalArgumentException();
2310:                }
2311:                int t = (y * ntX + x);
2312:                try {
2313:                    initTile(t);
2314:                } catch (IOException ioe) {
2315:                    // XXX Do something!
2316:                }
2317:
2318:                // Reset number of read bytes if needed
2319:                if (t == 0) {
2320:                    anbytes = headLen;
2321:                    if (!isTruncMode) {
2322:                        anbytes += 2;
2323:                    }
2324:                    // Restore values of nBytes
2325:                    for (int tIdx = 0; tIdx < nt; tIdx++) {
2326:                        nBytes[tIdx] = baknBytes[tIdx];
2327:                    }
2328:                }
2329:
2330:                // Set the new current tile
2331:                ctX = x;
2332:                ctY = y;
2333:                // Calculate tile relative points
2334:                int ctox = (x == 0) ? ax : px + x * ntW;
2335:                int ctoy = (y == 0) ? ay : py + y * ntH;
2336:                for (i = nc - 1; i >= 0; i--) {
2337:                    culx[i] = (ctox + hd.getCompSubsX(i) - 1)
2338:                            / hd.getCompSubsX(i);
2339:                    culy[i] = (ctoy + hd.getCompSubsY(i) - 1)
2340:                            / hd.getCompSubsY(i);
2341:                    offX[i] = (px + x * ntW + hd.getCompSubsX(i) - 1)
2342:                            / hd.getCompSubsX(i);
2343:                    offY[i] = (py + y * ntH + hd.getCompSubsY(i) - 1)
2344:                            / hd.getCompSubsY(i);
2345:                }
2346:
2347:                // Initialize subband tree and number of resolution levels
2348:                subbTrees = new SubbandSyn[nc];
2349:                mdl = new int[nc];
2350:                derived = new boolean[nc];
2351:                params = new StdDequantizerParams[nc];
2352:                gb = new int[nc];
2353:
2354:                for (int c = 0; c < nc; c++) {
2355:                    derived[c] = decSpec.qts.isDerived(t, c);
2356:                    params[c] = (StdDequantizerParams) decSpec.qsss
2357:                            .getTileCompVal(t, c);
2358:                    gb[c] = ((Integer) decSpec.gbs.getTileCompVal(t, c))
2359:                            .intValue();
2360:                    mdl[c] = ((Integer) decSpec.dls.getTileCompVal(t, c))
2361:                            .intValue();
2362:
2363:                    subbTrees[c] = new SubbandSyn(
2364:                            getTileCompWidth(t, c, mdl[c]), getTileCompHeight(
2365:                                    t, c, mdl[c]), getResULX(c, mdl[c]),
2366:                            getResULY(c, mdl[c]), mdl[c], decSpec.wfs
2367:                                    .getHFilters(t, c), decSpec.wfs
2368:                                    .getVFilters(t, c));
2369:                    initSubbandsFields(c, subbTrees[c]);
2370:                }
2371:
2372:                // Read tile's packets
2373:                try {
2374:                    readTilePkts(t);
2375:                } catch (IOException e) {
2376:                    e.printStackTrace();
2377:                    throw new Error("IO Error when reading tile " + x + " x "
2378:                            + y);
2379:                }
2380:            }
2381:
2382:            /**
2383:             * Advances to the next tile, in standard scan-line order (by rows
2384:             * then columns). An NoNextElementException is thrown if the
2385:             * current tile is the last one (i.e. there is no next tile).
2386:             * */
2387:            public void nextTile() {
2388:                if (ctX == ntX - 1 && ctY == ntY - 1) { // Already at last tile
2389:                    throw new NoNextElementException();
2390:                } else if (ctX < ntX - 1) { // If not at end of current tile line
2391:                    setTile(ctX + 1, ctY);
2392:                } else { // Go to first tile at next line
2393:                    setTile(0, ctY + 1);
2394:                }
2395:            }
2396:
2397:            /**
2398:             * Returns the specified coded code-block, for the specified component, in
2399:             * the current tile. The first layer to return is indicated by 'fl'. The
2400:             * number of layers that is returned depends on 'nl' and the amount of
2401:             * available data.
2402:             *
2403:             * <p>The argument 'fl' is to be used by subsequent calls to this method
2404:             * for the same code-block. In this way supplemental data can be retrieved
2405:             * at a later time. The fact that data from more than one layer can be
2406:             * returned means that several packets from the same code-block, of the
2407:             * same component, and the same tile, have been concatenated.</p>
2408:             *
2409:             * <p>The returned compressed code-block can have its progressive
2410:             * attribute set. If this attribute is set it means that more data can be
2411:             * obtained by subsequent calls to this method (subject to transmission
2412:             * delays, etc). If the progressive attribute is not set it means that the
2413:             * returned data is all the data that can be obtained for the specified
2414:             * code-block.</p>
2415:             *
2416:             * <p>The compressed code-block is uniquely specified by the current tile,
2417:             * the component (identified by 'c'), the subband (indentified by 'sb')
2418:             * and the code-block vertical and horizontal indexes 'n' and 'm'.</p>
2419:             *
2420:             * <p>The 'ulx' and 'uly' members of the returned 'DecLyrdCBlk' object
2421:             * contain the coordinates of the top-left corner of the block, with
2422:             * respect to the tile, not the subband.</p>
2423:             *
2424:             * @param c The index of the component, from 0 to N-1.
2425:             *
2426:             * @param m The vertical index of the code-block to return, in the
2427:             * specified subband.
2428:             *
2429:             * @param n The horizontal index of the code-block to return, in the
2430:             * specified subband.
2431:             *
2432:             * @param sb The subband in whic the requested code-block is.
2433:             *
2434:             * @param fl The first layer to return.
2435:             *
2436:             * @param nl The number of layers to return, if negative all available
2437:             * layers are returned, starting at 'fl'.
2438:             *
2439:             * @param ccb If not null this object is used to return the compressed
2440:             * code-block. If null a new object is created and returned. If the data
2441:             * array in ccb is not null then it can be reused to return the compressed
2442:             * data.
2443:             * @return The compressed code-block, with a certain number of layers
2444:             * determined by the available data and 'nl'.
2445:             * */
2446:            public DecLyrdCBlk getCodeBlock(int c, int m, int n, SubbandSyn sb,
2447:                    int fl, int nl, DecLyrdCBlk ccb) {
2448:
2449:                int t = getTileIdx();
2450:                CBlkInfo rcb; // requested code-block
2451:                int r = sb.resLvl; // Resolution level
2452:                int s = sb.sbandIdx; // Subband index
2453:                int tpidx;
2454:                int passtype;
2455:
2456:                // Number of layers
2457:                int numLayers = ((Integer) decSpec.nls.getTileDef(t))
2458:                        .intValue();
2459:                int options = ((Integer) decSpec.ecopts.getTileCompVal(t, c))
2460:                        .intValue();
2461:                if (nl < 0) {
2462:                    nl = numLayers - fl + 1;
2463:                }
2464:
2465:                // If the l quit condition is used, Make sure that no layer
2466:                // after lquit is returned
2467:                if (lQuit != -1 && fl + nl > lQuit) {
2468:                    nl = lQuit - fl;
2469:                }
2470:
2471:                // Check validity of resquested resolution level (according to the
2472:                // "-res" option).
2473:                int maxdl = getSynSubbandTree(t, c).resLvl;
2474:                /* XXX Suppress error check for speed performance reasons.
2475:                if(r>targetRes+maxdl-decSpec.dls.getMin()) {
2476:                    throw new Error("JJ2000 error: requesting a code-block "+
2477:                                    "disallowed by the '-res' option.");
2478:                }
2479:                 */
2480:
2481:                // Check validity of all the arguments
2482:                try {
2483:                    rcb = cbI[c][r][s][m][n];
2484:
2485:                    if (fl < 1 || fl > numLayers || fl + nl - 1 > numLayers) {
2486:                        throw new IllegalArgumentException();
2487:                    }
2488:                } catch (ArrayIndexOutOfBoundsException e) {
2489:                    throw new IllegalArgumentException("Code-block (t:" + t
2490:                            + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m
2491:                            + "x" + +n + ") not found in codestream");
2492:                } catch (NullPointerException e) {
2493:                    throw new IllegalArgumentException("Code-block (t:" + t
2494:                            + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m
2495:                            + "x" + n + ") not found in bit stream");
2496:                }
2497:
2498:                // Create DecLyrdCBlk object if necessary
2499:                if (ccb == null) {
2500:                    ccb = new DecLyrdCBlk();
2501:                }
2502:                ccb.m = m;
2503:                ccb.n = n;
2504:                ccb.nl = 0;
2505:                ccb.dl = 0;
2506:                ccb.nTrunc = 0;
2507:
2508:                if (rcb == null) {
2509:                    // This code-block was skipped when reading. Returns no data
2510:                    ccb.skipMSBP = 0;
2511:                    ccb.prog = false;
2512:                    ccb.w = ccb.h = ccb.ulx = ccb.uly = 0;
2513:                    return ccb;
2514:                }
2515:
2516:                // ccb initialization
2517:                ccb.skipMSBP = rcb.msbSkipped;
2518:                ccb.ulx = rcb.ulx;
2519:                ccb.uly = rcb.uly;
2520:                ccb.w = rcb.w;
2521:                ccb.h = rcb.h;
2522:                ccb.ftpIdx = 0;
2523:
2524:                // Search for index of first truncation point (first layer where
2525:                // length of data is not zero)
2526:                int l = 0;
2527:                while ((l < rcb.len.length) && (rcb.len[l] == 0)) {
2528:                    ccb.ftpIdx += rcb.ntp[l];
2529:                    l++;
2530:                }
2531:
2532:                // Calculate total length, number of included layer and number of
2533:                // truncation points
2534:                for (l = fl - 1; l < fl + nl - 1; l++) {
2535:                    ccb.nl++;
2536:                    ccb.dl += rcb.len[l];
2537:                    ccb.nTrunc += rcb.ntp[l];
2538:                }
2539:
2540:                // Calculate number of terminated segments
2541:                int nts;
2542:                if ((options & OPT_TERM_PASS) != 0) {
2543:                    // Regular termination in use One segment per pass
2544:                    // (i.e. truncation point)
2545:                    nts = ccb.nTrunc - ccb.ftpIdx;
2546:                } else if ((options & OPT_BYPASS) != 0) {
2547:                    // Selective arithmetic coding bypass mode in use, but no regular
2548:                    // termination: 1 segment upto the end of the last pass of the 4th
2549:                    // most significant bit-plane, and, in each following bit-plane,
2550:                    // one segment upto the end of the 2nd pass and one upto the end
2551:                    // of the 3rd pass.
2552:
2553:                    if (ccb.nTrunc <= FIRST_BYPASS_PASS_IDX) {
2554:                        nts = 1;
2555:                    } else {
2556:                        nts = 1;
2557:                        // Adds one for each terminated pass
2558:                        for (tpidx = ccb.ftpIdx; tpidx < ccb.nTrunc; tpidx++) {
2559:                            if (tpidx >= FIRST_BYPASS_PASS_IDX - 1) {
2560:                                passtype = (tpidx + NUM_EMPTY_PASSES_IN_MS_BP)
2561:                                        % NUM_PASSES;
2562:                                if (passtype == 1 || passtype == 2) {
2563:                                    // lazy pass just before MQ pass or MQ pass just
2564:                                    // before lazy pass => terminated
2565:                                    nts++;
2566:                                }
2567:                            }
2568:                        }
2569:                    }
2570:                } else {
2571:                    // Nothing special in use, just one terminated segment
2572:                    nts = 1;
2573:                }
2574:
2575:                // ccb.data creation
2576:                if (ccb.data == null || ccb.data.length < ccb.dl) {
2577:                    ccb.data = new byte[ccb.dl];
2578:                }
2579:
2580:                // ccb.tsLengths creation
2581:                if (nts > 1
2582:                        && (ccb.tsLengths == null || ccb.tsLengths.length < nts)) {
2583:                    ccb.tsLengths = new int[nts];
2584:                } else if (nts > 1
2585:                        && (options & (OPT_BYPASS | OPT_TERM_PASS)) == OPT_BYPASS) {
2586:                    ArrayUtil.intArraySet(ccb.tsLengths, 0);
2587:                }
2588:
2589:                // Fill ccb with compressed data
2590:                int dataIdx = -1;
2591:                tpidx = ccb.ftpIdx;
2592:                int ctp = ccb.ftpIdx; // Cumulative number of truncation
2593:                // point for the current layer layer
2594:                int tsidx = 0;
2595:                int j;
2596:
2597:                for (l = fl - 1; l < fl + nl - 1; l++) {
2598:                    ctp += rcb.ntp[l];
2599:                    // No data in this layer
2600:                    if (rcb.len[l] == 0)
2601:                        continue;
2602:
2603:                    // Read data
2604:                    // NOTE: we should never get an EOFException here since all
2605:                    // data is checked to be within the file.
2606:                    try {
2607:                        in.seek(rcb.off[l]);
2608:                        in.readFully(ccb.data, dataIdx + 1, rcb.len[l]);
2609:                        dataIdx += rcb.len[l];
2610:                    } catch (IOException e) {
2611:                        JJ2KExceptionHandler.handleException(e);
2612:                    }
2613:
2614:                    // Get the terminated segment lengths, if any
2615:                    if (nts == 1)
2616:                        continue;
2617:                    if ((options & OPT_TERM_PASS) != 0) {
2618:                        // Regular termination => each pass is terminated
2619:                        for (j = 0; tpidx < ctp; j++, tpidx++) {
2620:                            if (rcb.segLen[l] != null) {
2621:                                ccb.tsLengths[tsidx++] = rcb.segLen[l][j];
2622:                            } else { // Only one terminated segment in packet
2623:                                ccb.tsLengths[tsidx++] = rcb.len[l];
2624:                            }
2625:                        }
2626:                    } else {
2627:                        // Lazy coding without regular termination
2628:                        for (j = 0; tpidx < ctp; tpidx++) {
2629:                            if (tpidx >= FIRST_BYPASS_PASS_IDX - 1) {
2630:                                passtype = (tpidx + NUM_EMPTY_PASSES_IN_MS_BP)
2631:                                        % NUM_PASSES;
2632:                                if (passtype != 0) {
2633:                                    // lazy pass just before MQ pass or MQ
2634:                                    // pass just before lazy pass =>
2635:                                    // terminated
2636:                                    if (rcb.segLen[l] != null) {
2637:                                        ccb.tsLengths[tsidx++] += rcb.segLen[l][j++];
2638:                                        rcb.len[l] -= rcb.segLen[l][j - 1];
2639:                                    } else { // Only one terminated segment in packet
2640:                                        ccb.tsLengths[tsidx++] += rcb.len[l];
2641:                                        rcb.len[l] = 0;
2642:                                    }
2643:                                }
2644:
2645:                            }
2646:                        }
2647:
2648:                        // Last length in packet always in (either terminated segment
2649:                        // or contribution to terminated segment)
2650:                        if (rcb.segLen[l] != null && j < rcb.segLen[l].length) {
2651:                            ccb.tsLengths[tsidx] += rcb.segLen[l][j];
2652:                            rcb.len[l] -= rcb.segLen[l][j];
2653:                        } else { // Only one terminated segment in packet
2654:                            if (tsidx < nts) {
2655:                                ccb.tsLengths[tsidx] += rcb.len[l];
2656:                                rcb.len[l] = 0;
2657:                            }
2658:                        }
2659:                    }
2660:                }
2661:                if (nts == 1 && ccb.tsLengths != null) {
2662:                    ccb.tsLengths[0] = ccb.dl;
2663:                }
2664:
2665:                // Set the progressive flag
2666:                int lastlayer = fl + nl - 1;
2667:                if (lastlayer < numLayers - 1) {
2668:                    for (l = lastlayer + 1; l < numLayers; l++) {
2669:                        // It remains data for this code-block in the bit stream
2670:                        if (rcb.len[l] != 0) {
2671:                            ccb.prog = true;
2672:                        }
2673:                    }
2674:                }
2675:
2676:                return ccb;
2677:            }
2678:
2679:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.