Source Code Cross Referenced for HeaderDecoder.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: HeaderDecoder.java,v $
0003:         * $Revision: 1.2 $
0004:         * $Date: 2006/09/28 00:55:20 $
0005:         * $State: Exp $
0006:         *
0007:         * Class:                   HeaderDecoder
0008:         *
0009:         * Description:             Reads main and tile-part headers.
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.quantization.*;
0052:        import jj2000.j2k.codestream.*;
0053:        import jj2000.j2k.wavelet.*;
0054:        import jj2000.j2k.entropy.*;
0055:        import jj2000.j2k.decoder.*;
0056:        import jj2000.j2k.image.*;
0057:        import jj2000.j2k.util.*;
0058:        import jj2000.j2k.roi.*;
0059:        import jj2000.j2k.io.*;
0060:        import jj2000.j2k.*;
0061:
0062:        import java.io.*;
0063:        import java.util.*;
0064:
0065:        //import colorspace.*;
0066:        //import icc.*;
0067:
0068:        import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReadParamJava;
0069:
0070:        /**
0071:         * This class reads Main and Tile-part headers from the codestream. It is
0072:         * created by the run() method of the Decoder instance.
0073:         *
0074:         * <p>A marker segment includes a marker and eventually marker segment
0075:         * parameters. It is designed by the three letters code of the marker
0076:         * associated with the marker segment. JPEG 2000 part 1 defines 6 types of
0077:         * markers:
0078:         *
0079:         * <ul>
0080:         * <li> Delimiting : SOC,SOT (read in FileBitstreamReaderAgent),SOD,EOC
0081:         * (read in FileBitstreamReaderAgent).</li> <li> Fixed information: SIZ.</li>
0082:         *
0083:         * <li> Functional: COD,COC,RGN,QCD,QCC,POC.</li> <li> In bit-stream:
0084:         * SOP,EPH.</li>
0085:         *
0086:         * <li> Pointer: TLM,PLM,PLT,PPM,PPT.</li>
0087:         *
0088:         * <li> Informational: CRG,COM.</li>
0089:         * </ul>
0090:         *
0091:         * <p>The main header is read when the constructor is called whereas tile-part
0092:         * headers are read when the FileBitstreamReaderAgent instance is created. The
0093:         * reading is done in 2 passes:
0094:         *
0095:         * <ul>
0096:         * <li>All marker segments are buffered and their corresponding flag is
0097:         * activated (extractMainMarkSeg and extractTilePartMarkSeg methods).</li>
0098:         *
0099:         * <li>Buffered marker segment are analyzed in a logical way and
0100:         * specifications are stored in appropriate member of DecoderSpecs instance
0101:         * (readFoundMainMarkSeg and readFoundTilePartMarkSeg methods).</li>
0102:         * </ul>
0103:         *
0104:         * <p>Whenever a marker segment is not recognized a warning message is
0105:         * displayed and its length parameter is used to skip it.
0106:         *
0107:         * @see DecoderSpecs
0108:         * @see Decoder
0109:         * @see FileBitstreamReaderAgent
0110:         * */
0111:        public class HeaderDecoder implements  ProgressionType, Markers,
0112:                StdEntropyCoderOptions {
0113:
0114:            /** The prefix for header decoder options: 'H' */
0115:            public final static char OPT_PREFIX = 'H';
0116:
0117:            /** The list of parameters that is accepted for quantization. Options
0118:             * for quantization start with 'Q'. */
0119:            private final static String[][] pinfo = null;
0120:
0121:            /** The reference to the HeaderInfo instance holding the information found
0122:             * in headers */
0123:            private HeaderInfo hi;
0124:
0125:            /** Current header information in a string */
0126:            private String hdStr = "";
0127:
0128:            /** The J2KImageReadParamJava instance of the decoder */
0129:            private J2KImageReadParamJava j2krparam;
0130:
0131:            /** The number of tiles within the image */
0132:            private int nTiles;
0133:
0134:            /** The number of tile parts per tile */
0135:            public int[] nTileParts;
0136:
0137:            /** Used to store which markers have been already read, by using flag
0138:             * bits. The different markers are marked with XXX_FOUND flags, such as
0139:             * SIZ_FOUND */
0140:            private int nfMarkSeg = 0;
0141:
0142:            /** Counts number of COC markers found in the header */
0143:            private int nCOCMarkSeg = 0;
0144:
0145:            /** Counts number of QCC markers found in the header */
0146:            private int nQCCMarkSeg = 0;
0147:
0148:            /** Counts number of COM markers found in the header */
0149:            private int nCOMMarkSeg = 0;
0150:
0151:            /** Counts number of RGN markers found in the header */
0152:            private int nRGNMarkSeg = 0;
0153:
0154:            /** Counts number of PPM markers found in the header */
0155:            private int nPPMMarkSeg = 0;
0156:
0157:            /** Counts number of PPT markers found in the header */
0158:            private int[][] nPPTMarkSeg = null;
0159:
0160:            /** Flag bit for SIZ marker segment found */
0161:            private static final int SIZ_FOUND = 1;
0162:
0163:            /** Flag bit for COD marker segment found */
0164:            private static final int COD_FOUND = 1 << 1;
0165:
0166:            /** Flag bit for COC marker segment found */
0167:            private static final int COC_FOUND = 1 << 2;
0168:
0169:            /** Flag bit for QCD marker segment found */
0170:            private static final int QCD_FOUND = 1 << 3;
0171:
0172:            /** Flag bit for TLM marker segment found */
0173:            private static final int TLM_FOUND = 1 << 4;
0174:
0175:            /** Flag bit for PLM marker segment found */
0176:            private static final int PLM_FOUND = 1 << 5;
0177:
0178:            /** Flag bit for SOT marker segment found */
0179:            private static final int SOT_FOUND = 1 << 6;
0180:
0181:            /** Flag bit for PLT marker segment found */
0182:            private static final int PLT_FOUND = 1 << 7;
0183:
0184:            /** Flag bit for QCC marker segment found */
0185:            private static final int QCC_FOUND = 1 << 8;
0186:
0187:            /** Flag bit for RGN marker segment found */
0188:            private static final int RGN_FOUND = 1 << 9;
0189:
0190:            /** Flag bit for POC marker segment found */
0191:            private static final int POC_FOUND = 1 << 10;
0192:
0193:            /** Flag bit for COM marker segment found */
0194:            private static final int COM_FOUND = 1 << 11;
0195:
0196:            /** Flag bit for SOD marker segment found */
0197:            public static final int SOD_FOUND = 1 << 13;
0198:
0199:            /** Flag bit for SOD marker segment found */
0200:            public static final int PPM_FOUND = 1 << 14;
0201:
0202:            /** Flag bit for SOD marker segment found */
0203:            public static final int PPT_FOUND = 1 << 15;
0204:
0205:            /** Flag bit for CRG marker segment found */
0206:            public static final int CRG_FOUND = 1 << 16;
0207:
0208:            /** The reset mask for new tiles */
0209:            private static final int TILE_RESET = ~(PLM_FOUND | SIZ_FOUND | RGN_FOUND);
0210:
0211:            /** HashTable used to store marker segment byte buffers */
0212:            private Hashtable ht = null;
0213:
0214:            /** The number of components in the image */
0215:            private int nComp;
0216:
0217:            /** The horizontal code-block partition origin */
0218:            private int cb0x = -1;
0219:
0220:            /** The vertical code-block partition origin */
0221:            private int cb0y = -1;
0222:
0223:            /** The decoder specifications */
0224:            private DecoderSpecs decSpec;
0225:
0226:            /** Is the precinct partition used */
0227:            boolean precinctPartitionIsUsed;
0228:
0229:            /** The offset of the main header in the input stream */
0230:            public int mainHeadOff;
0231:
0232:            /** Vector containing info as to which tile each tilepart belong */
0233:            public Vector tileOfTileParts;
0234:
0235:            /** Array containing the Nppm and Ippm fields of the PPM marker segments*/
0236:            private byte[][] pPMMarkerData;
0237:
0238:            /** Array containing the Ippm fields of the PPT marker segments */
0239:            private byte[][][][] tilePartPkdPktHeaders;
0240:
0241:            /** The packed packet headers if the PPM or PPT markers are used */
0242:            private ByteArrayOutputStream[] pkdPktHeaders;
0243:
0244:            /** 
0245:             * Return the maximum height among all components 
0246:             *
0247:             * @return Maximum component height
0248:             * */
0249:            public int getMaxCompImgHeight() {
0250:                return hi.siz.getMaxCompHeight();
0251:            }
0252:
0253:            /** 
0254:             * Return the maximum width among all components 
0255:             *
0256:             * @return Maximum component width
0257:             * */
0258:            public int getMaxCompImgWidth() {
0259:                return hi.siz.getMaxCompWidth();
0260:            }
0261:
0262:            /**
0263:             * Returns the image width in the reference grid.
0264:             *
0265:             * @return The image width in the reference grid
0266:             * */
0267:            public final int getImgWidth() {
0268:                return hi.siz.xsiz - hi.siz.x0siz;
0269:            }
0270:
0271:            /**
0272:             * Returns the image height in the reference grid.
0273:             *
0274:             * @return The image height in the reference grid
0275:             * */
0276:            public final int getImgHeight() {
0277:                return hi.siz.ysiz - hi.siz.y0siz;
0278:            }
0279:
0280:            /**
0281:             * Return the horizontal upper-left coordinate of the image in the
0282:             * reference grid.
0283:             *
0284:             * @return The horizontal coordinate of the image origin.
0285:             * */
0286:            public final int getImgULX() {
0287:                return hi.siz.x0siz;
0288:            }
0289:
0290:            /**
0291:             * Return the vertical upper-left coordinate of the image in the reference
0292:             * grid.
0293:             *
0294:             * @return The vertical coordinate of the image origin.
0295:             * */
0296:            public final int getImgULY() {
0297:                return hi.siz.y0siz;
0298:            }
0299:
0300:            /**
0301:             * Returns the nominal width of the tiles in the reference grid.
0302:             *
0303:             * @return The nominal tile width, in the reference grid.
0304:             * */
0305:            public final int getNomTileWidth() {
0306:                return hi.siz.xtsiz;
0307:            }
0308:
0309:            /**
0310:             * Returns the nominal width of the tiles in the reference grid.
0311:             *
0312:             * @return The nominal tile width, in the reference grid.
0313:             * */
0314:            public final int getNomTileHeight() {
0315:                return hi.siz.ytsiz;
0316:            }
0317:
0318:            /**
0319:             * Returns the tiling origin, referred to as '(Px,Py)' in the 'ImgData'
0320:             * interface.
0321:             *
0322:             * @param co If not null this object is used to return the information. If
0323:             * null a new one is created and returned.
0324:             *
0325:             * @return The coordinate of the tiling origin, in the canvas system, on
0326:             * the reference grid.
0327:             *
0328:             * @see jj2000.j2k.image.ImgData
0329:             * */
0330:            public final Point getTilingOrigin(Point co) {
0331:                if (co != null) {
0332:                    co.x = hi.siz.xt0siz;
0333:                    co.y = hi.siz.yt0siz;
0334:                    return co;
0335:                } else {
0336:                    return new Point(hi.siz.xt0siz, hi.siz.yt0siz);
0337:                }
0338:            }
0339:
0340:            /**
0341:             * Returns true if the original data of the specified component was
0342:             * signed. If the data was not signed a level shift has to be applied at
0343:             * the end of the decompression chain.
0344:             *
0345:             * @param c The index of the component
0346:             *
0347:             * @return True if the original image component was signed.
0348:             * */
0349:            public final boolean isOriginalSigned(int c) {
0350:                return hi.siz.isOrigSigned(c);
0351:            }
0352:
0353:            /**
0354:             * Returns the original bitdepth of the specified component.
0355:             *
0356:             * @param c The index of the component
0357:             *
0358:             * @return The bitdepth of the component
0359:             * */
0360:            public final int getOriginalBitDepth(int c) {
0361:                return hi.siz.getOrigBitDepth(c);
0362:            }
0363:
0364:            /**
0365:             * Returns the number of components in the image.
0366:             *
0367:             * @return The number of components in the image.
0368:             * */
0369:            public final int getNumComps() {
0370:                return nComp;
0371:            }
0372:
0373:            /**
0374:             * Returns the component sub-sampling factor, with respect to the
0375:             * reference grid, along the horizontal direction for the specified
0376:             * component.
0377:             *
0378:             * @param c The index of the component
0379:             *
0380:             * @return The component sub-sampling factor X-wise.
0381:             * */
0382:            public final int getCompSubsX(int c) {
0383:                return hi.siz.xrsiz[c];
0384:            }
0385:
0386:            /**
0387:             * Returns the component sub-sampling factor, with respect to the
0388:             * reference grid, along the vertical direction for the specified
0389:             * component.
0390:             *
0391:             * @param c The index of the component
0392:             *
0393:             * @return The component sub-sampling factor Y-wise.
0394:             * */
0395:            public final int getCompSubsY(int c) {
0396:                return hi.siz.yrsiz[c];
0397:            }
0398:
0399:            /**
0400:             * Returns the dequantizer parameters. Dequantizer parameters normally are
0401:             * the quantization step sizes, see DequantizerParams.
0402:             *
0403:             * @param src The source of data for the dequantizer.
0404:             *
0405:             * @param rb The number of range bits for each component. Must be
0406:             * the number of range bits of the mixed components.
0407:             *
0408:             * @param decSpec2 The DecoderSpecs instance after any image manipulation.
0409:             *
0410:             * @return The dequantizer
0411:             * */
0412:            public final Dequantizer createDequantizer(CBlkQuantDataSrcDec src,
0413:                    int rb[], DecoderSpecs decSpec2) {
0414:                return new StdDequantizer(src, rb, decSpec2);
0415:            }
0416:
0417:            /**
0418:             * Returns the horizontal code-block partition origin.Allowable values are
0419:             * 0 and 1, nothing else.
0420:             * */
0421:            public final int getCbULX() {
0422:                return cb0x;
0423:            }
0424:
0425:            /**
0426:             * Returns the vertical code-block partition origin. Allowable values are
0427:             * 0 and 1, nothing else.
0428:             * */
0429:            public final int getCbULY() {
0430:                return cb0y;
0431:            }
0432:
0433:            /**
0434:             * Returns the precinct partition width for the specified tile-component
0435:             * and resolution level.
0436:             *
0437:             * @param c the component index
0438:             *
0439:             * @param t the tile index
0440:             *
0441:             * @param rl the resolution level
0442:             *
0443:             * @return The precinct partition width for the specified tile-component
0444:             * and resolution level
0445:             * */
0446:            public final int getPPX(int t, int c, int rl) {
0447:                return decSpec.pss.getPPX(t, c, rl);
0448:            }
0449:
0450:            /**
0451:             * Returns the precinct partition height for the specified component, tile
0452:             * and resolution level.
0453:             *
0454:             * @param c the component
0455:             *
0456:             * @param t the tile index
0457:             *
0458:             * @param rl the resolution level
0459:             *
0460:             * @return The precinct partition height for the specified component,
0461:             * tile and resolution level
0462:             * */
0463:            public final int getPPY(int t, int c, int rl) {
0464:                return decSpec.pss.getPPY(t, c, rl);
0465:            }
0466:
0467:            /**
0468:             * Returns the boolean used to know if the precinct partition is used
0469:             **/
0470:            public final boolean precinctPartitionUsed() {
0471:                return precinctPartitionIsUsed;
0472:            }
0473:
0474:            /**
0475:             * Reads a wavelet filter from the codestream and returns the filter
0476:             * object that implements it.
0477:             *
0478:             * @param ehs The encoded header stream from where to read the info
0479:             *
0480:             * @param filtIdx Int array of one element to return the type of the
0481:             * wavelet filter.
0482:             * */
0483:            private SynWTFilter readFilter(DataInputStream ehs, int[] filtIdx)
0484:                    throws IOException {
0485:                int kid; // the filter id
0486:
0487:                kid = filtIdx[0] = ehs.readUnsignedByte();
0488:                if (kid >= (1 << 7)) {
0489:                    throw new NotImplementedError(
0490:                            "Custom filters not supported");
0491:                }
0492:                // Return filter based on ID
0493:                switch (kid) {
0494:                case FilterTypes.W9X7:
0495:                    return new SynWTFilterFloatLift9x7();
0496:                case FilterTypes.W5X3:
0497:                    return new SynWTFilterIntLift5x3();
0498:                default:
0499:                    throw new CorruptedCodestreamException(
0500:                            "Specified wavelet filter " + "not"
0501:                                    + " JPEG 2000 part I " + "compliant");
0502:                }
0503:            }
0504:
0505:            /**
0506:             * Checks that the marker segment length is correct. 
0507:             *
0508:             * @param ehs The encoded header stream
0509:             *
0510:             * @param str The string identifying the marker, such as "SIZ marker"
0511:             *
0512:             * @exception IOException If an I/O error occurs
0513:             * */
0514:            public void checkMarkerLength(DataInputStream ehs, String str)
0515:                    throws IOException {
0516:                if (ehs.available() != 0) {
0517:                    FacilityManager.getMsgLogger().printmsg(MsgLogger.WARNING,
0518:                            str + " length was short, attempting to resync.");
0519:                }
0520:            }
0521:
0522:            /**
0523:             * Reads the SIZ marker segment and realigns the codestream at the point
0524:             * where the next marker segment should be found. 
0525:             *
0526:             * <p>SIZ is a fixed information marker segment containing informations
0527:             * about image and tile sizes. It is required in the main header
0528:             * immediately after SOC.</p>
0529:             *
0530:             * @param ehs The encoded header stream
0531:             *
0532:             * @exception IOException If an I/O error occurs while reading from the
0533:             * encoded header stream
0534:             * */
0535:            private void readSIZ(DataInputStream ehs) throws IOException {
0536:                HeaderInfo.SIZ ms = hi.getNewSIZ();
0537:                hi.siz = ms;
0538:
0539:                // Read the length of SIZ marker segment (Lsiz)
0540:                ms.lsiz = ehs.readUnsignedShort();
0541:
0542:                // Read the capability of the codestream (Rsiz)
0543:                ms.rsiz = ehs.readUnsignedShort();
0544:                if (ms.rsiz > 2) {
0545:                    throw new Error(
0546:                            "Codestream capabiities not JPEG 2000 - Part I"
0547:                                    + " compliant");
0548:                }
0549:
0550:                // Read image size
0551:                ms.xsiz = ehs.readInt();
0552:                ms.ysiz = ehs.readInt();
0553:                if (ms.xsiz <= 0 || ms.ysiz <= 0) {
0554:                    throw new IOException(
0555:                            "JJ2000 does not support images whose "
0556:                                    + "width and/or height not in the "
0557:                                    + "range: 1 -- (2^31)-1");
0558:                }
0559:
0560:                // Read image offset
0561:                ms.x0siz = ehs.readInt();
0562:                ms.y0siz = ehs.readInt();
0563:                if (ms.x0siz < 0 || ms.y0siz < 0) {
0564:                    throw new IOException(
0565:                            "JJ2000 does not support images offset "
0566:                                    + "not in the range: 0 -- (2^31)-1");
0567:                }
0568:
0569:                // Read size of tile
0570:                ms.xtsiz = ehs.readInt();
0571:                ms.ytsiz = ehs.readInt();
0572:                if (ms.xtsiz <= 0 || ms.ytsiz <= 0) {
0573:                    throw new IOException(
0574:                            "JJ2000 does not support tiles whose "
0575:                                    + "width and/or height are not in  "
0576:                                    + "the range: 1 -- (2^31)-1");
0577:                }
0578:
0579:                // Read upper-left tile offset
0580:                ms.xt0siz = ehs.readInt();
0581:                ms.yt0siz = ehs.readInt();
0582:                if (ms.xt0siz < 0 || ms.yt0siz < 0) {
0583:                    throw new IOException(
0584:                            "JJ2000 does not support tiles whose "
0585:                                    + "offset is not in  "
0586:                                    + "the range: 0 -- (2^31)-1");
0587:                }
0588:
0589:                // Read number of components and initialize related arrays
0590:                nComp = ms.csiz = ehs.readUnsignedShort();
0591:                if (nComp < 1 || nComp > 16384) {
0592:                    throw new IllegalArgumentException(
0593:                            "Number of component out of " + "range 1--16384: "
0594:                                    + nComp);
0595:                }
0596:
0597:                ms.ssiz = new int[nComp];
0598:                ms.xrsiz = new int[nComp];
0599:                ms.yrsiz = new int[nComp];
0600:
0601:                // Read bit-depth and down-sampling factors of each component
0602:                for (int i = 0; i < nComp; i++) {
0603:                    ms.ssiz[i] = ehs.readUnsignedByte();
0604:                    ms.xrsiz[i] = ehs.readUnsignedByte();
0605:                    ms.yrsiz[i] = ehs.readUnsignedByte();
0606:                }
0607:
0608:                // Check marker length
0609:                checkMarkerLength(ehs, "SIZ marker");
0610:
0611:                // Create needed ModuleSpec
0612:                nTiles = ms.getNumTiles();
0613:
0614:                // Finish initialization of decSpec
0615:                decSpec = new DecoderSpecs(nTiles, nComp);
0616:            }
0617:
0618:            /** 
0619:             * Reads a CRG marker segment and checks its length. CRG is an
0620:             * informational marker segment that allows specific registration of
0621:             * components with respect to each other.
0622:             *
0623:             * @param ehs The encoded header stream
0624:             * */
0625:            private void readCRG(DataInputStream ehs) throws IOException {
0626:                HeaderInfo.CRG ms = hi.getNewCRG();
0627:                hi.crg = ms;
0628:
0629:                ms.lcrg = ehs.readUnsignedShort();
0630:                ms.xcrg = new int[nComp];
0631:                ms.ycrg = new int[nComp];
0632:
0633:                FacilityManager
0634:                        .getMsgLogger()
0635:                        .printmsg(
0636:                                MsgLogger.WARNING,
0637:                                "Information in CRG marker segment "
0638:                                        + "not taken into account. This may affect the display "
0639:                                        + "of the decoded image.");
0640:                for (int c = 0; c < nComp; c++) {
0641:                    ms.xcrg[c] = ehs.readUnsignedShort();
0642:                    ms.ycrg[c] = ehs.readUnsignedShort();
0643:                }
0644:
0645:                // Check marker length
0646:                checkMarkerLength(ehs, "CRG marker");
0647:            }
0648:
0649:            /**
0650:             * Reads a COM marker segments and realigns the bit stream at the point
0651:             * where the next marker segment should be found. COM is an informational
0652:             * marker segment that allows to include unstructured data in the main and
0653:             * tile-part headers.
0654:             *
0655:             * @param ehs The encoded header stream
0656:             *
0657:             * @param mainh Flag indicating whether or not this marker segment is read
0658:             * from the main header.
0659:             *
0660:             * @param tileIdx The index of the current tile
0661:             *
0662:             * @param comIdx Occurence of this COM marker in eith main or tile-part
0663:             * header 
0664:             * 
0665:             * @exception IOException If an I/O error occurs while reading from the
0666:             * encoded header stream
0667:             * */
0668:            private void readCOM(DataInputStream ehs, boolean mainh,
0669:                    int tileIdx, int comIdx) throws IOException {
0670:                HeaderInfo.COM ms = hi.getNewCOM();
0671:
0672:                // Read length of COM field
0673:                ms.lcom = ehs.readUnsignedShort();
0674:
0675:                // Read the registration value of the COM marker segment
0676:                ms.rcom = ehs.readUnsignedShort();
0677:                switch (ms.rcom) {
0678:                case RCOM_GEN_USE:
0679:                    ms.ccom = new byte[ms.lcom - 4];
0680:                    for (int i = 0; i < ms.lcom - 4; i++) {
0681:                        ms.ccom[i] = ehs.readByte();
0682:                    }
0683:                    break;
0684:                default:
0685:                    // --- Unknown or unsupported markers ---
0686:                    // (skip them and see if we can get way with it)
0687:                    FacilityManager
0688:                            .getMsgLogger()
0689:                            .printmsg(
0690:                                    MsgLogger.WARNING,
0691:                                    "COM marker registered as 0x"
0692:                                            + Integer.toHexString(ms.rcom)
0693:                                            + " unknown, ignoring (this might crash the "
0694:                                            + "decoder or decode a quality degraded or even "
0695:                                            + "useless image)");
0696:                    ehs.skipBytes(ms.lcom - 4); //Ignore this field for the moment
0697:                    break;
0698:                }
0699:
0700:                if (mainh) {
0701:                    hi.com.put("main_" + comIdx, ms);
0702:                } else {
0703:                    hi.com.put("t" + tileIdx + "_" + comIdx, ms);
0704:                }
0705:
0706:                // Check marker length
0707:                checkMarkerLength(ehs, "COM marker");
0708:            }
0709:
0710:            /**
0711:             * Reads a QCD marker segment and realigns the codestream at the point
0712:             * where the next marker should be found. QCD is a functional marker
0713:             * segment that describes the quantization default.
0714:             * 
0715:             * @param ehs The encoded stream.
0716:             *
0717:             * @param mainh Flag indicating whether or not this marker segment is read
0718:             * from the main header.
0719:             *
0720:             * @param tileIdx The index of the current tile
0721:             *
0722:             * @param tpIdx Tile-part index
0723:             *
0724:             * @exception IOException If an I/O error occurs while reading from the
0725:             * encoded header stream.
0726:             * */
0727:            private void readQCD(DataInputStream ehs, boolean mainh,
0728:                    int tileIdx, int tpIdx) throws IOException {
0729:                StdDequantizerParams qParms;
0730:                int guardBits;
0731:                int[][] exp;
0732:                float[][] nStep = null;
0733:                HeaderInfo.QCD ms = hi.getNewQCD();
0734:
0735:                // Lqcd (length of QCD field)
0736:                ms.lqcd = ehs.readUnsignedShort();
0737:
0738:                // Sqcd (quantization style)
0739:                ms.sqcd = ehs.readUnsignedByte();
0740:
0741:                guardBits = ms.getNumGuardBits();
0742:                int qType = ms.getQuantType();
0743:
0744:                if (mainh) {
0745:                    hi.qcd.put("main", ms);
0746:                    // If the main header is being read set default value of
0747:                    // dequantization spec
0748:                    switch (qType) {
0749:                    case SQCX_NO_QUANTIZATION:
0750:                        decSpec.qts.setDefault("reversible");
0751:                        break;
0752:                    case SQCX_SCALAR_DERIVED:
0753:                        decSpec.qts.setDefault("derived");
0754:                        break;
0755:                    case SQCX_SCALAR_EXPOUNDED:
0756:                        decSpec.qts.setDefault("expounded");
0757:                        break;
0758:                    default:
0759:                        throw new CorruptedCodestreamException("Unknown or "
0760:                                + "unsupported " + "quantization style "
0761:                                + "in Sqcd field, QCD " + "marker main header");
0762:                    }
0763:                } else {
0764:                    hi.qcd.put("t" + tileIdx, ms);
0765:                    // If the tile header is being read set default value of
0766:                    // dequantization spec for tile
0767:                    switch (qType) {
0768:                    case SQCX_NO_QUANTIZATION:
0769:                        decSpec.qts.setTileDef(tileIdx, "reversible");
0770:                        break;
0771:                    case SQCX_SCALAR_DERIVED:
0772:                        decSpec.qts.setTileDef(tileIdx, "derived");
0773:                        break;
0774:                    case SQCX_SCALAR_EXPOUNDED:
0775:                        decSpec.qts.setTileDef(tileIdx, "expounded");
0776:                        break;
0777:                    default:
0778:                        throw new CorruptedCodestreamException("Unknown or "
0779:                                + "unsupported " + "quantization style "
0780:                                + "in Sqcd field, QCD " + "marker, tile header");
0781:                    }
0782:                }
0783:
0784:                qParms = new StdDequantizerParams();
0785:
0786:                if (qType == SQCX_NO_QUANTIZATION) {
0787:                    int maxrl = (mainh ? ((Integer) decSpec.dls.getDefault())
0788:                            .intValue() : ((Integer) decSpec.dls
0789:                            .getTileDef(tileIdx)).intValue());
0790:                    int i, j, rl;
0791:                    int minb, maxb, hpd;
0792:                    int tmp;
0793:
0794:                    exp = qParms.exp = new int[maxrl + 1][];
0795:                    ms.spqcd = new int[maxrl + 1][4];
0796:
0797:                    for (rl = 0; rl <= maxrl; rl++) { // Loop on resolution levels
0798:                        // Find the number of subbands in the resolution level
0799:                        if (rl == 0) { // Only the LL subband
0800:                            minb = 0;
0801:                            maxb = 1;
0802:                        } else {
0803:                            // Dyadic decomposition
0804:                            hpd = 1;
0805:
0806:                            // Adapt hpd to resolution level
0807:                            if (hpd > maxrl - rl) {
0808:                                hpd -= maxrl - rl;
0809:                            } else {
0810:                                hpd = 1;
0811:                            }
0812:                            // Determine max and min subband index
0813:                            minb = 1 << ((hpd - 1) << 1); // minb = 4^(hpd-1)
0814:                            maxb = 1 << (hpd << 1); // maxb = 4^hpd
0815:                        }
0816:                        // Allocate array for subbands in resolution level
0817:                        exp[rl] = new int[maxb];
0818:
0819:                        for (j = minb; j < maxb; j++) {
0820:                            tmp = ms.spqcd[rl][j] = ehs.readUnsignedByte();
0821:                            exp[rl][j] = (tmp >> SQCX_EXP_SHIFT)
0822:                                    & SQCX_EXP_MASK;
0823:                        }
0824:                    }// end for rl
0825:                } else {
0826:                    int maxrl = (qType == SQCX_SCALAR_DERIVED) ? 0
0827:                            : (mainh ? ((Integer) decSpec.dls.getDefault())
0828:                                    .intValue() : ((Integer) decSpec.dls
0829:                                    .getTileDef(tileIdx)).intValue());
0830:                    int i, j, rl;
0831:                    int minb, maxb, hpd;
0832:                    int tmp;
0833:
0834:                    exp = qParms.exp = new int[maxrl + 1][];
0835:                    nStep = qParms.nStep = new float[maxrl + 1][];
0836:                    ms.spqcd = new int[maxrl + 1][4];
0837:
0838:                    for (rl = 0; rl <= maxrl; rl++) { // Loop on resolution levels
0839:                        // Find the number of subbands in the resolution level
0840:                        if (rl == 0) { // Only the LL subband
0841:                            minb = 0;
0842:                            maxb = 1;
0843:                        } else {
0844:                            // Dyadic decomposition
0845:                            hpd = 1;
0846:
0847:                            // Adapt hpd to resolution level
0848:                            if (hpd > maxrl - rl) {
0849:                                hpd -= maxrl - rl;
0850:                            } else {
0851:                                hpd = 1;
0852:                            }
0853:                            // Determine max and min subband index
0854:                            minb = 1 << ((hpd - 1) << 1); // minb = 4^(hpd-1)
0855:                            maxb = 1 << (hpd << 1); // maxb = 4^hpd
0856:                        }
0857:                        // Allocate array for subbands in resolution level
0858:                        exp[rl] = new int[maxb];
0859:                        nStep[rl] = new float[maxb];
0860:
0861:                        for (j = minb; j < maxb; j++) {
0862:                            tmp = ms.spqcd[rl][j] = ehs.readUnsignedShort();
0863:                            exp[rl][j] = (tmp >> 11) & 0x1f;
0864:                            // NOTE: the formula below does not support more than 5
0865:                            // bits for the exponent, otherwise (-1<<exp) might
0866:                            // overflow (the - is used to be able to represent 2**31)
0867:                            nStep[rl][j] = (-1f - ((float) (tmp & 0x07ff))
0868:                                    / (1 << 11))
0869:                                    / (-1 << exp[rl][j]);
0870:                        }
0871:                    }// end for rl
0872:                } // end if (qType != SQCX_NO_QUANTIZATION)
0873:
0874:                // Fill qsss, gbs
0875:                if (mainh) {
0876:                    decSpec.qsss.setDefault(qParms);
0877:                    decSpec.gbs.setDefault(new Integer(guardBits));
0878:                } else {
0879:                    decSpec.qsss.setTileDef(tileIdx, qParms);
0880:                    decSpec.gbs.setTileDef(tileIdx, new Integer(guardBits));
0881:                }
0882:
0883:                // Check marker length
0884:                checkMarkerLength(ehs, "QCD marker");
0885:            }
0886:
0887:            /**
0888:             * Reads a QCC marker segment and realigns the codestream at the point
0889:             * where the next marker should be found. QCC is a functional marker
0890:             * segment that describes the quantization of one component.
0891:             * 
0892:             * @param ehs The encoded stream.
0893:             *
0894:             * @param mainh Flag indicating whether or not this marker segment is read
0895:             * from the main header.
0896:             *
0897:             * @param tileIdx The index of the current tile
0898:             *
0899:             * @param tpIdx Tile-part index
0900:             *
0901:             * @exception IOException If an I/O error occurs while reading from the
0902:             * encoded header stream.
0903:             * */
0904:            private void readQCC(DataInputStream ehs, boolean mainh,
0905:                    int tileIdx, int tpIdx) throws IOException {
0906:                int cComp; // current component
0907:                int tmp;
0908:                StdDequantizerParams qParms;
0909:                int[][] expC;
0910:                float[][] nStepC = null;
0911:                HeaderInfo.QCC ms = hi.getNewQCC();
0912:
0913:                // Lqcc (length of QCC field)
0914:                ms.lqcc = ehs.readUnsignedShort();
0915:
0916:                // Cqcc
0917:                if (nComp < 257) {
0918:                    cComp = ms.cqcc = ehs.readUnsignedByte();
0919:                } else {
0920:                    cComp = ms.cqcc = ehs.readUnsignedShort();
0921:                }
0922:                if (cComp >= nComp) {
0923:                    throw new CorruptedCodestreamException("Invalid component "
0924:                            + "index in QCC marker");
0925:                }
0926:
0927:                // Sqcc (quantization style)
0928:                ms.sqcc = ehs.readUnsignedByte();
0929:                int guardBits = ms.getNumGuardBits();
0930:                int qType = ms.getQuantType();
0931:
0932:                if (mainh) {
0933:                    hi.qcc.put("main_c" + cComp, ms);
0934:                    // If main header is being read, set default for component in all
0935:                    // tiles
0936:                    switch (qType) {
0937:                    case SQCX_NO_QUANTIZATION:
0938:                        decSpec.qts.setCompDef(cComp, "reversible");
0939:                        break;
0940:                    case SQCX_SCALAR_DERIVED:
0941:                        decSpec.qts.setCompDef(cComp, "derived");
0942:                        break;
0943:                    case SQCX_SCALAR_EXPOUNDED:
0944:                        decSpec.qts.setCompDef(cComp, "expounded");
0945:                        break;
0946:                    default:
0947:                        throw new CorruptedCodestreamException("Unknown or "
0948:                                + "unsupported " + "quantization style "
0949:                                + "in Sqcd field, QCD " + "marker, main header");
0950:                    }
0951:                } else {
0952:                    hi.qcc.put("t" + tileIdx + "_c" + cComp, ms);
0953:                    // If tile header is being read, set value for component in
0954:                    // this tiles
0955:                    switch (qType) {
0956:                    case SQCX_NO_QUANTIZATION:
0957:                        decSpec.qts
0958:                                .setTileCompVal(tileIdx, cComp, "reversible");
0959:                        break;
0960:                    case SQCX_SCALAR_DERIVED:
0961:                        decSpec.qts.setTileCompVal(tileIdx, cComp, "derived");
0962:                        break;
0963:                    case SQCX_SCALAR_EXPOUNDED:
0964:                        decSpec.qts.setTileCompVal(tileIdx, cComp, "expounded");
0965:                        break;
0966:                    default:
0967:                        throw new CorruptedCodestreamException("Unknown or "
0968:                                + "unsupported " + "quantization style "
0969:                                + "in Sqcd field, QCD " + "marker, main header");
0970:                    }
0971:                }
0972:
0973:                // Decode all dequantizer params
0974:                qParms = new StdDequantizerParams();
0975:
0976:                if (qType == SQCX_NO_QUANTIZATION) {
0977:                    int maxrl = (mainh ? ((Integer) decSpec.dls
0978:                            .getCompDef(cComp)).intValue()
0979:                            : ((Integer) decSpec.dls.getTileCompVal(tileIdx,
0980:                                    cComp)).intValue());
0981:                    int i, j, rl;
0982:                    int minb, maxb, hpd;
0983:
0984:                    expC = qParms.exp = new int[maxrl + 1][];
0985:                    ms.spqcc = new int[maxrl + 1][4];
0986:
0987:                    for (rl = 0; rl <= maxrl; rl++) { // Loop on resolution levels
0988:                        // Find the number of subbands in the resolution level
0989:                        if (rl == 0) { // Only the LL subband
0990:                            minb = 0;
0991:                            maxb = 1;
0992:                        } else {
0993:                            // Dyadic decomposition
0994:                            hpd = 1;
0995:
0996:                            // Adapt hpd to resolution level
0997:                            if (hpd > maxrl - rl) {
0998:                                hpd -= maxrl - rl;
0999:                            } else {
1000:                                hpd = 1;
1001:                            }
1002:                            // Determine max and min subband index
1003:                            minb = 1 << ((hpd - 1) << 1); // minb = 4^(hpd-1)
1004:                            maxb = 1 << (hpd << 1); // maxb = 4^hpd
1005:                        }
1006:                        // Allocate array for subbands in resolution level
1007:                        expC[rl] = new int[maxb];
1008:
1009:                        for (j = minb; j < maxb; j++) {
1010:                            tmp = ms.spqcc[rl][j] = ehs.readUnsignedByte();
1011:                            expC[rl][j] = (tmp >> SQCX_EXP_SHIFT)
1012:                                    & SQCX_EXP_MASK;
1013:                        }
1014:                    }// end for rl
1015:                } else {
1016:                    int maxrl = (qType == SQCX_SCALAR_DERIVED) ? 0
1017:                            : (mainh ? ((Integer) decSpec.dls.getCompDef(cComp))
1018:                                    .intValue()
1019:                                    : ((Integer) decSpec.dls.getTileCompVal(
1020:                                            tileIdx, cComp)).intValue());
1021:                    int i, j, rl;
1022:                    int minb, maxb, hpd;
1023:
1024:                    nStepC = qParms.nStep = new float[maxrl + 1][];
1025:                    expC = qParms.exp = new int[maxrl + 1][];
1026:                    ms.spqcc = new int[maxrl + 1][4];
1027:
1028:                    for (rl = 0; rl <= maxrl; rl++) { // Loop on resolution levels
1029:                        // Find the number of subbands in the resolution level
1030:                        if (rl == 0) { // Only the LL subband
1031:                            minb = 0;
1032:                            maxb = 1;
1033:                        } else {
1034:                            // Dyadic decomposition
1035:                            hpd = 1;
1036:
1037:                            // Adapt hpd to resolution level
1038:                            if (hpd > maxrl - rl) {
1039:                                hpd -= maxrl - rl;
1040:                            } else {
1041:                                hpd = 1;
1042:                            }
1043:                            // Determine max and min subband index
1044:                            minb = 1 << ((hpd - 1) << 1); // minb = 4^(hpd-1)
1045:                            maxb = 1 << (hpd << 1); // maxb = 4^hpd
1046:                        }
1047:                        // Allocate array for subbands in resolution level
1048:                        expC[rl] = new int[maxb];
1049:                        nStepC[rl] = new float[maxb];
1050:
1051:                        for (j = minb; j < maxb; j++) {
1052:                            tmp = ms.spqcc[rl][j] = ehs.readUnsignedShort();
1053:                            expC[rl][j] = (tmp >> 11) & 0x1f;
1054:                            // NOTE: the formula below does not support more than 5
1055:                            // bits for the exponent, otherwise (-1<<exp) might
1056:                            // overflow (the - is used to be able to represent 2**31)
1057:                            nStepC[rl][j] = (-1f - ((float) (tmp & 0x07ff))
1058:                                    / (1 << 11))
1059:                                    / (-1 << expC[rl][j]);
1060:                        }
1061:                    }// end for rl
1062:                } // end if (qType != SQCX_NO_QUANTIZATION)
1063:
1064:                // Fill qsss, gbs
1065:                if (mainh) {
1066:                    decSpec.qsss.setCompDef(cComp, qParms);
1067:                    decSpec.gbs.setCompDef(cComp, new Integer(guardBits));
1068:                } else {
1069:                    decSpec.qsss.setTileCompVal(tileIdx, cComp, qParms);
1070:                    decSpec.gbs.setTileCompVal(tileIdx, cComp, new Integer(
1071:                            guardBits));
1072:                }
1073:
1074:                // Check marker length
1075:                checkMarkerLength(ehs, "QCC marker");
1076:            }
1077:
1078:            /**
1079:             * Reads a COD marker segment and realigns the codestream where the next
1080:             * marker should be found. 
1081:             *
1082:             * @param ehs The encoder header stream.
1083:             *
1084:             * @param mainh Flag indicating whether or not this marker segment is read
1085:             * from the main header.
1086:             *
1087:             * @param tileIdx The index of the current tile
1088:             *
1089:             * @param tpIdx Tile-part index
1090:             *
1091:             * @exception IOException If an I/O error occurs while reading from the
1092:             * encoder header stream
1093:             * */
1094:            private void readCOD(DataInputStream ehs, boolean mainh,
1095:                    int tileIdx, int tpIdx) throws IOException {
1096:                int cstyle; // The block style
1097:                SynWTFilter hfilters[], vfilters[];
1098:                int l;
1099:                Integer cblk[];
1100:                String errMsg;
1101:                boolean sopUsed = false;
1102:                boolean ephUsed = false;
1103:                HeaderInfo.COD ms = hi.getNewCOD();
1104:
1105:                // Lcod (marker length)
1106:                ms.lcod = ehs.readUnsignedShort();
1107:
1108:                // Scod (block style)
1109:                // We only support wavelet transformed data
1110:                cstyle = ms.scod = ehs.readUnsignedByte();
1111:
1112:                if ((cstyle & SCOX_PRECINCT_PARTITION) != 0) {
1113:                    precinctPartitionIsUsed = true;
1114:                    // Remove flag
1115:                    cstyle &= ~(SCOX_PRECINCT_PARTITION);
1116:                } else {
1117:                    precinctPartitionIsUsed = false;
1118:                }
1119:
1120:                // SOP markers
1121:                if (mainh) {
1122:                    hi.cod.put("main", ms);
1123:
1124:                    if ((cstyle & SCOX_USE_SOP) != 0) {
1125:                        // SOP markers are used
1126:                        decSpec.sops.setDefault(new Boolean("true"));
1127:                        sopUsed = true;
1128:                        // Remove flag
1129:                        cstyle &= ~(SCOX_USE_SOP);
1130:                    } else {
1131:                        // SOP markers are not used
1132:                        decSpec.sops.setDefault(new Boolean("false"));
1133:                    }
1134:                } else {
1135:                    hi.cod.put("t" + tileIdx, ms);
1136:
1137:                    if ((cstyle & SCOX_USE_SOP) != 0) {
1138:                        // SOP markers are used
1139:                        decSpec.sops.setTileDef(tileIdx, new Boolean("true"));
1140:                        sopUsed = true;
1141:                        // Remove flag
1142:                        cstyle &= ~(SCOX_USE_SOP);
1143:                    } else {
1144:                        // SOP markers are not used
1145:                        decSpec.sops.setTileDef(tileIdx, new Boolean("false"));
1146:                    }
1147:                }
1148:
1149:                // EPH markers
1150:                if (mainh) {
1151:                    if ((cstyle & SCOX_USE_EPH) != 0) {
1152:                        // EPH markers are used
1153:                        decSpec.ephs.setDefault(new Boolean("true"));
1154:                        ephUsed = true;
1155:                        // Remove flag
1156:                        cstyle &= ~(SCOX_USE_EPH);
1157:                    } else {
1158:                        // EPH markers are not used
1159:                        decSpec.ephs.setDefault(new Boolean("false"));
1160:                    }
1161:                } else {
1162:                    if ((cstyle & SCOX_USE_EPH) != 0) {
1163:                        // EPH markers are used
1164:                        decSpec.ephs.setTileDef(tileIdx, new Boolean("true"));
1165:                        ephUsed = true;
1166:                        // Remove flag
1167:                        cstyle &= ~(SCOX_USE_EPH);
1168:                    } else {
1169:                        // EPH markers are not used
1170:                        decSpec.ephs.setTileDef(tileIdx, new Boolean("false"));
1171:                    }
1172:                }
1173:
1174:                // Code-block partition origin
1175:                if ((cstyle & (SCOX_HOR_CB_PART | SCOX_VER_CB_PART)) != 0) {
1176:                    FacilityManager
1177:                            .getMsgLogger()
1178:                            .printmsg(
1179:                                    MsgLogger.WARNING,
1180:                                    "Code-block partition origin "
1181:                                            + "different from (0,0). This is defined in JPEG 2000"
1182:                                            + " part 2 and may not be supported by all JPEG "
1183:                                            + "2000 decoders.");
1184:                }
1185:                if ((cstyle & SCOX_HOR_CB_PART) != 0) {
1186:                    if (cb0x != -1 && cb0x == 0) {
1187:                        throw new IllegalArgumentException(
1188:                                "Code-block partition "
1189:                                        + "origin redefined in new"
1190:                                        + " COD marker segment. Not"
1191:                                        + " supported by JJ2000");
1192:                    }
1193:                    cb0x = 1;
1194:                    cstyle &= ~(SCOX_HOR_CB_PART);
1195:                } else {
1196:                    if (cb0x != -1 && cb0x == 1) {
1197:                        throw new IllegalArgumentException(
1198:                                "Code-block partition "
1199:                                        + "origin redefined in new"
1200:                                        + " COD marker segment. Not"
1201:                                        + " supported by JJ2000");
1202:                    }
1203:                    cb0x = 0;
1204:                }
1205:                if ((cstyle & SCOX_VER_CB_PART) != 0) {
1206:                    if (cb0y != -1 && cb0y == 0) {
1207:                        throw new IllegalArgumentException(
1208:                                "Code-block partition "
1209:                                        + "origin redefined in new"
1210:                                        + " COD marker segment. Not"
1211:                                        + " supported by JJ2000");
1212:                    }
1213:                    cb0y = 1;
1214:                    cstyle &= ~(SCOX_VER_CB_PART);
1215:                } else {
1216:                    if (cb0y != -1 && cb0y == 1) {
1217:                        throw new IllegalArgumentException(
1218:                                "Code-block partition "
1219:                                        + "origin redefined in new"
1220:                                        + " COD marker segment. Not"
1221:                                        + " supported by JJ2000");
1222:                    }
1223:                    cb0y = 0;
1224:                }
1225:
1226:                // SGcod
1227:                // Read the progressive order
1228:                ms.sgcod_po = ehs.readUnsignedByte();
1229:
1230:                // Read the number of layers
1231:                ms.sgcod_nl = ehs.readUnsignedShort();
1232:                if (ms.sgcod_nl <= 0 || ms.sgcod_nl > 65535) {
1233:                    throw new CorruptedCodestreamException(
1234:                            "Number of layers out of " + "range: 1--65535");
1235:                }
1236:
1237:                // Multiple component transform
1238:                ms.sgcod_mct = ehs.readUnsignedByte();
1239:
1240:                // SPcod
1241:                // decomposition levels
1242:                int mrl = ms.spcod_ndl = ehs.readUnsignedByte();
1243:                if (mrl > 32) {
1244:                    throw new CorruptedCodestreamException(
1245:                            "Number of decomposition "
1246:                                    + "levels out of range: " + "0--32");
1247:                }
1248:
1249:                // Read the code-blocks dimensions
1250:                cblk = new Integer[2];
1251:                ms.spcod_cw = ehs.readUnsignedByte();
1252:                cblk[0] = new Integer(1 << (ms.spcod_cw + 2));
1253:                if (cblk[0].intValue() < StdEntropyCoderOptions.MIN_CB_DIM
1254:                        || cblk[0].intValue() > StdEntropyCoderOptions.MAX_CB_DIM) {
1255:                    errMsg = "Non-valid code-block width in SPcod field, "
1256:                            + "COD marker";
1257:                    throw new CorruptedCodestreamException(errMsg);
1258:                }
1259:                ms.spcod_ch = ehs.readUnsignedByte();
1260:                cblk[1] = new Integer(1 << (ms.spcod_ch + 2));
1261:                if (cblk[1].intValue() < StdEntropyCoderOptions.MIN_CB_DIM
1262:                        || cblk[1].intValue() > StdEntropyCoderOptions.MAX_CB_DIM) {
1263:                    errMsg = "Non-valid code-block height in SPcod field, "
1264:                            + "COD marker";
1265:                    throw new CorruptedCodestreamException(errMsg);
1266:                }
1267:                if ((cblk[0].intValue() * cblk[1].intValue()) > StdEntropyCoderOptions.MAX_CB_AREA) {
1268:                    errMsg = "Non-valid code-block area in SPcod field, "
1269:                            + "COD marker";
1270:                    throw new CorruptedCodestreamException(errMsg);
1271:                }
1272:                if (mainh) {
1273:                    decSpec.cblks.setDefault(cblk);
1274:                } else {
1275:                    decSpec.cblks.setTileDef(tileIdx, cblk);
1276:                }
1277:
1278:                // Style of the code-block coding passes
1279:                int ecOptions = ms.spcod_cs = ehs.readUnsignedByte();
1280:                if ((ecOptions & ~(OPT_BYPASS | OPT_RESET_MQ | OPT_TERM_PASS
1281:                        | OPT_VERT_STR_CAUSAL | OPT_PRED_TERM | OPT_SEG_SYMBOLS)) != 0) {
1282:                    throw new CorruptedCodestreamException(
1283:                            "Unknown \"code-block "
1284:                                    + "style\" in SPcod field, "
1285:                                    + "COD marker: 0x"
1286:                                    + Integer.toHexString(ecOptions));
1287:                }
1288:
1289:                // Read wavelet filter for tile or image
1290:                hfilters = new SynWTFilter[1];
1291:                vfilters = new SynWTFilter[1];
1292:                hfilters[0] = readFilter(ehs, ms.spcod_t);
1293:                vfilters[0] = hfilters[0];
1294:
1295:                // Fill the filter spec
1296:                // If this is the main header, set the default value, if it is the
1297:                // tile header, set default for this tile 
1298:                SynWTFilter[][] hvfilters = new SynWTFilter[2][];
1299:                hvfilters[0] = hfilters;
1300:                hvfilters[1] = vfilters;
1301:
1302:                // Get precinct partition sizes
1303:                Vector v[] = new Vector[2];
1304:                v[0] = new Vector();
1305:                v[1] = new Vector();
1306:                int val = PRECINCT_PARTITION_DEF_SIZE;
1307:                if (!precinctPartitionIsUsed) {
1308:                    Integer w, h;
1309:                    w = new Integer(1 << (val & 0x000F));
1310:                    v[0].addElement(w);
1311:                    h = new Integer(1 << (((val & 0x00F0) >> 4)));
1312:                    v[1].addElement(h);
1313:                } else {
1314:                    ms.spcod_ps = new int[mrl + 1];
1315:                    for (int rl = mrl; rl >= 0; rl--) {
1316:                        Integer w, h;
1317:                        val = ms.spcod_ps[mrl - rl] = ehs.readUnsignedByte();
1318:                        w = new Integer(1 << (val & 0x000F));
1319:                        v[0].insertElementAt(w, 0);
1320:                        h = new Integer(1 << (((val & 0x00F0) >> 4)));
1321:                        v[1].insertElementAt(h, 0);
1322:                    }
1323:                }
1324:                if (mainh) {
1325:                    decSpec.pss.setDefault(v);
1326:                } else {
1327:                    decSpec.pss.setTileDef(tileIdx, v);
1328:                }
1329:                precinctPartitionIsUsed = true;
1330:
1331:                // Check marker length
1332:                checkMarkerLength(ehs, "COD marker");
1333:
1334:                // Store specifications in decSpec
1335:                if (mainh) {
1336:                    decSpec.wfs.setDefault(hvfilters);
1337:                    decSpec.dls.setDefault(new Integer(mrl));
1338:                    decSpec.ecopts.setDefault(new Integer(ecOptions));
1339:                    decSpec.cts.setDefault(new Integer(ms.sgcod_mct));
1340:                    decSpec.nls.setDefault(new Integer(ms.sgcod_nl));
1341:                    decSpec.pos.setDefault(new Integer(ms.sgcod_po));
1342:                } else {
1343:                    decSpec.wfs.setTileDef(tileIdx, hvfilters);
1344:                    decSpec.dls.setTileDef(tileIdx, new Integer(mrl));
1345:                    decSpec.ecopts.setTileDef(tileIdx, new Integer(ecOptions));
1346:                    decSpec.cts.setTileDef(tileIdx, new Integer(ms.sgcod_mct));
1347:                    decSpec.nls.setTileDef(tileIdx, new Integer(ms.sgcod_nl));
1348:                    decSpec.pos.setTileDef(tileIdx, new Integer(ms.sgcod_po));
1349:                }
1350:            }
1351:
1352:            /**
1353:             * Reads the COC marker segment and realigns the codestream where the next
1354:             * marker should be found.
1355:             *
1356:             * @param ehs The encoder header stream.
1357:             *
1358:             * @param mainh Flag indicating whether or not this marker segment is read
1359:             * from the main header.
1360:             *
1361:             * @param tileIdx The index of the current tile
1362:             *
1363:             * @param tpIdx Tile-part index
1364:             *
1365:             * @exception IOException If an I/O error occurs while reading from the
1366:             * encoder header stream
1367:             * */
1368:            private void readCOC(DataInputStream ehs, boolean mainh,
1369:                    int tileIdx, int tpIdx) throws IOException {
1370:                int cComp; // current component
1371:                SynWTFilter hfilters[], vfilters[];
1372:                int tmp, l;
1373:                int ecOptions;
1374:                Integer cblk[];
1375:                String errMsg;
1376:                HeaderInfo.COC ms = hi.getNewCOC();
1377:
1378:                // Lcoc (marker length)
1379:                ms.lcoc = ehs.readUnsignedShort();
1380:
1381:                // Ccoc
1382:                if (nComp < 257) {
1383:                    cComp = ms.ccoc = ehs.readUnsignedByte();
1384:                } else {
1385:                    cComp = ms.ccoc = ehs.readUnsignedShort();
1386:                }
1387:                if (cComp >= nComp) {
1388:                    throw new CorruptedCodestreamException(
1389:                            "Invalid component index " + "in QCC marker");
1390:                }
1391:
1392:                // Scoc (block style)
1393:                int cstyle = ms.scoc = ehs.readUnsignedByte();
1394:                if ((cstyle & SCOX_PRECINCT_PARTITION) != 0) {
1395:                    precinctPartitionIsUsed = true;
1396:                    // Remove flag
1397:                    cstyle &= ~(SCOX_PRECINCT_PARTITION);
1398:                } else {
1399:                    precinctPartitionIsUsed = false;
1400:                }
1401:
1402:                // SPcoc
1403:
1404:                // decomposition levels
1405:                int mrl = ms.spcoc_ndl = ehs.readUnsignedByte();
1406:
1407:                // Read the code-blocks dimensions
1408:                cblk = new Integer[2];
1409:                ms.spcoc_cw = ehs.readUnsignedByte();
1410:                cblk[0] = new Integer(1 << (ms.spcoc_cw + 2));
1411:                if (cblk[0].intValue() < StdEntropyCoderOptions.MIN_CB_DIM
1412:                        || cblk[0].intValue() > StdEntropyCoderOptions.MAX_CB_DIM) {
1413:                    errMsg = "Non-valid code-block width in SPcod field, "
1414:                            + "COC marker";
1415:                    throw new CorruptedCodestreamException(errMsg);
1416:                }
1417:                ms.spcoc_ch = ehs.readUnsignedByte();
1418:                cblk[1] = new Integer(1 << (ms.spcoc_ch + 2));
1419:                if (cblk[1].intValue() < StdEntropyCoderOptions.MIN_CB_DIM
1420:                        || cblk[1].intValue() > StdEntropyCoderOptions.MAX_CB_DIM) {
1421:                    errMsg = "Non-valid code-block height in SPcod field, "
1422:                            + "COC marker";
1423:                    throw new CorruptedCodestreamException(errMsg);
1424:                }
1425:                if ((cblk[0].intValue() * cblk[1].intValue()) > StdEntropyCoderOptions.MAX_CB_AREA) {
1426:                    errMsg = "Non-valid code-block area in SPcod field, "
1427:                            + "COC marker";
1428:                    throw new CorruptedCodestreamException(errMsg);
1429:                }
1430:                if (mainh) {
1431:                    decSpec.cblks.setCompDef(cComp, cblk);
1432:                } else {
1433:                    decSpec.cblks.setTileCompVal(tileIdx, cComp, cblk);
1434:                }
1435:
1436:                // Read entropy block mode options
1437:                // NOTE: currently OPT_SEG_SYMBOLS is not included here
1438:                ecOptions = ms.spcoc_cs = ehs.readUnsignedByte();
1439:                if ((ecOptions & ~(OPT_BYPASS | OPT_RESET_MQ | OPT_TERM_PASS
1440:                        | OPT_VERT_STR_CAUSAL | OPT_PRED_TERM | OPT_SEG_SYMBOLS)) != 0) {
1441:                    throw new CorruptedCodestreamException(
1442:                            "Unknown \"code-block "
1443:                                    + "context\" in SPcoc field, "
1444:                                    + "COC marker: 0x"
1445:                                    + Integer.toHexString(ecOptions));
1446:                }
1447:
1448:                // Read wavelet filter for tile or image
1449:                hfilters = new SynWTFilter[1];
1450:                vfilters = new SynWTFilter[1];
1451:                hfilters[0] = readFilter(ehs, ms.spcoc_t);
1452:                vfilters[0] = hfilters[0];
1453:
1454:                // Fill the filter spec
1455:                // If this is the main header, set the default value, if it is the
1456:                // tile header, set default for this tile 
1457:                SynWTFilter[][] hvfilters = new SynWTFilter[2][];
1458:                hvfilters[0] = hfilters;
1459:                hvfilters[1] = vfilters;
1460:
1461:                // Get precinct partition sizes
1462:                Vector v[] = new Vector[2];
1463:                v[0] = new Vector();
1464:                v[1] = new Vector();
1465:                int val = PRECINCT_PARTITION_DEF_SIZE;
1466:                if (!precinctPartitionIsUsed) {
1467:                    Integer w, h;
1468:                    w = new Integer(1 << (val & 0x000F));
1469:                    v[0].addElement(w);
1470:                    h = new Integer(1 << (((val & 0x00F0) >> 4)));
1471:                    v[1].addElement(h);
1472:                } else {
1473:                    ms.spcoc_ps = new int[mrl + 1];
1474:                    for (int rl = mrl; rl >= 0; rl--) {
1475:                        Integer w, h;
1476:                        val = ms.spcoc_ps[rl] = ehs.readUnsignedByte();
1477:                        w = new Integer(1 << (val & 0x000F));
1478:                        v[0].insertElementAt(w, 0);
1479:                        h = new Integer(1 << (((val & 0x00F0) >> 4)));
1480:                        v[1].insertElementAt(h, 0);
1481:                    }
1482:                }
1483:                if (mainh) {
1484:                    decSpec.pss.setCompDef(cComp, v);
1485:                } else {
1486:                    decSpec.pss.setTileCompVal(tileIdx, cComp, v);
1487:                }
1488:                precinctPartitionIsUsed = true;
1489:
1490:                // Check marker length
1491:                checkMarkerLength(ehs, "COD marker");
1492:
1493:                if (mainh) {
1494:                    hi.coc.put("main_c" + cComp, ms);
1495:                    decSpec.wfs.setCompDef(cComp, hvfilters);
1496:                    decSpec.dls.setCompDef(cComp, new Integer(mrl));
1497:                    decSpec.ecopts.setCompDef(cComp, new Integer(ecOptions));
1498:                } else {
1499:                    hi.coc.put("t" + tileIdx + "_c" + cComp, ms);
1500:                    decSpec.wfs.setTileCompVal(tileIdx, cComp, hvfilters);
1501:                    decSpec.dls
1502:                            .setTileCompVal(tileIdx, cComp, new Integer(mrl));
1503:                    decSpec.ecopts.setTileCompVal(tileIdx, cComp, new Integer(
1504:                            ecOptions));
1505:                }
1506:            }
1507:
1508:            /** 
1509:             * Reads the POC marker segment and realigns the codestream where the next
1510:             * marker should be found.
1511:             *
1512:             * @param ehs The encoder header stream.
1513:             *
1514:             * @param mainh Flag indicating whether or not this marker segment is read
1515:             * from the main header.
1516:             *
1517:             * @param t The index of the current tile
1518:             *
1519:             * @param tpIdx Tile-part index
1520:             *
1521:             * @exception IOException If an I/O error occurs while reading from the
1522:             * encoder header stream
1523:             * */
1524:            private void readPOC(DataInputStream ehs, boolean mainh, int t,
1525:                    int tpIdx) throws IOException {
1526:
1527:                boolean useShort = (nComp >= 256) ? true : false;
1528:                int tmp;
1529:                int nOldChg = 0;
1530:                HeaderInfo.POC ms;
1531:                if (mainh || hi.poc.get("t" + t) == null) {
1532:                    ms = hi.getNewPOC();
1533:                } else {
1534:                    ms = (HeaderInfo.POC) hi.poc.get("t" + t);
1535:                    nOldChg = ms.rspoc.length;
1536:                }
1537:
1538:                // Lpoc
1539:                ms.lpoc = ehs.readUnsignedShort();
1540:
1541:                // Compute the number of new progression changes
1542:                // newChg = (lpoc - Lpoc(2)) / (RSpoc(1) + CSpoc(2) +
1543:                //  LYEpoc(2) + REpoc(1) + CEpoc(2) + Ppoc (1) )
1544:                int newChg = (ms.lpoc - 2) / (5 + (useShort ? 4 : 2));
1545:                int ntotChg = nOldChg + newChg;
1546:
1547:                int[][] change;
1548:                if (nOldChg != 0) {
1549:                    // Creates new arrays
1550:                    change = new int[ntotChg][6];
1551:                    int[] tmprspoc = new int[ntotChg];
1552:                    int[] tmpcspoc = new int[ntotChg];
1553:                    int[] tmplyepoc = new int[ntotChg];
1554:                    int[] tmprepoc = new int[ntotChg];
1555:                    int[] tmpcepoc = new int[ntotChg];
1556:                    int[] tmpppoc = new int[ntotChg];
1557:
1558:                    // Copy old values
1559:                    int[][] prevChg = (int[][]) decSpec.pcs.getTileDef(t);
1560:                    for (int chg = 0; chg < nOldChg; chg++) {
1561:                        change[chg] = prevChg[chg];
1562:                        tmprspoc[chg] = ms.rspoc[chg];
1563:                        tmpcspoc[chg] = ms.cspoc[chg];
1564:                        tmplyepoc[chg] = ms.lyepoc[chg];
1565:                        tmprepoc[chg] = ms.repoc[chg];
1566:                        tmpcepoc[chg] = ms.cepoc[chg];
1567:                        tmpppoc[chg] = ms.ppoc[chg];
1568:                    }
1569:                    ms.rspoc = tmprspoc;
1570:                    ms.cspoc = tmpcspoc;
1571:                    ms.lyepoc = tmplyepoc;
1572:                    ms.repoc = tmprepoc;
1573:                    ms.cepoc = tmpcepoc;
1574:                    ms.ppoc = tmpppoc;
1575:                } else {
1576:                    change = new int[newChg][6];
1577:                    ms.rspoc = new int[newChg];
1578:                    ms.cspoc = new int[newChg];
1579:                    ms.lyepoc = new int[newChg];
1580:                    ms.repoc = new int[newChg];
1581:                    ms.cepoc = new int[newChg];
1582:                    ms.ppoc = new int[newChg];
1583:                }
1584:
1585:                for (int chg = nOldChg; chg < ntotChg; chg++) {
1586:                    // RSpoc
1587:                    change[chg][0] = ms.rspoc[chg] = ehs.readUnsignedByte();
1588:
1589:                    // CSpoc
1590:                    if (useShort) {
1591:                        change[chg][1] = ms.cspoc[chg] = ehs
1592:                                .readUnsignedShort();
1593:                    } else {
1594:                        change[chg][1] = ms.cspoc[chg] = ehs.readUnsignedByte();
1595:                    }
1596:
1597:                    // LYEpoc
1598:                    change[chg][2] = ms.lyepoc[chg] = ehs.readUnsignedShort();
1599:                    if (change[chg][2] < 1) {
1600:                        throw new CorruptedCodestreamException(
1601:                                "LYEpoc value must be greater than 1 in POC marker "
1602:                                        + "segment of tile " + t
1603:                                        + ", tile-part " + tpIdx);
1604:                    }
1605:
1606:                    // REpoc
1607:                    change[chg][3] = ms.repoc[chg] = ehs.readUnsignedByte();
1608:                    if (change[chg][3] <= change[chg][0]) {
1609:                        throw new CorruptedCodestreamException(
1610:                                "REpoc value must be greater than RSpoc in POC marker "
1611:                                        + "segment of tile " + t
1612:                                        + ", tile-part " + tpIdx);
1613:                    }
1614:
1615:                    // CEpoc
1616:                    if (useShort) {
1617:                        change[chg][4] = ms.cepoc[chg] = ehs
1618:                                .readUnsignedShort();
1619:                    } else {
1620:                        tmp = ms.cepoc[chg] = ehs.readUnsignedByte();
1621:                        if (tmp == 0) {
1622:                            change[chg][4] = 0;
1623:                        } else {
1624:                            change[chg][4] = tmp;
1625:                        }
1626:                    }
1627:                    if (change[chg][4] <= change[chg][1]) {
1628:                        throw new CorruptedCodestreamException(
1629:                                "CEpoc value must be greater than CSpoc in POC marker "
1630:                                        + "segment of tile " + t
1631:                                        + ", tile-part " + tpIdx);
1632:                    }
1633:
1634:                    // Ppoc
1635:                    change[chg][5] = ms.ppoc[chg] = ehs.readUnsignedByte();
1636:                }
1637:
1638:                // Check marker length
1639:                checkMarkerLength(ehs, "POC marker");
1640:
1641:                // Register specifications
1642:                if (mainh) {
1643:                    hi.poc.put("main", ms);
1644:                    decSpec.pcs.setDefault(change);
1645:                } else {
1646:                    hi.poc.put("t" + t, ms);
1647:                    decSpec.pcs.setTileDef(t, change);
1648:                }
1649:            }
1650:
1651:            /**
1652:             * Reads TLM marker segment and realigns the codestream where the next
1653:             * marker should be found. Informations stored in these fields are
1654:             * currently NOT taken into account.
1655:             *
1656:             * @param ehs The encoder header stream.
1657:             *
1658:             * @exception IOException If an I/O error occurs while reading from the
1659:             * encoder header stream
1660:             * */
1661:            private void readTLM(DataInputStream ehs) throws IOException {
1662:                int length;
1663:
1664:                length = ehs.readUnsignedShort();
1665:                //Ignore all informations contained
1666:                ehs.skipBytes(length - 2);
1667:
1668:                FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1669:                        "Skipping unsupported TLM marker");
1670:            }
1671:
1672:            /**
1673:             * Reads PLM marker segment and realigns the codestream where the next
1674:             * marker should be found. Informations stored in these fields are
1675:             * currently not taken into account.
1676:             *
1677:             * @param ehs The encoder header stream.
1678:             *
1679:             * @exception IOException If an I/O error occurs while reading from the
1680:             * encoder header stream
1681:             * */
1682:            private void readPLM(DataInputStream ehs) throws IOException {
1683:                int length;
1684:
1685:                length = ehs.readUnsignedShort();
1686:                //Ignore all informations contained
1687:                ehs.skipBytes(length - 2);
1688:
1689:                FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1690:                        "Skipping unsupported PLM marker");
1691:            }
1692:
1693:            /**
1694:             * Reads the PLT fields and realigns the codestream where the next marker
1695:             * should be found. Informations stored in these fields are currently NOT
1696:             * taken into account.
1697:             *
1698:             * @param ehs The encoder header stream.
1699:             *
1700:             * @exception IOException If an I/O error occurs while reading from the
1701:             * encoder header stream
1702:             * */
1703:            private void readPLTFields(DataInputStream ehs) throws IOException {
1704:                int length;
1705:
1706:                length = ehs.readUnsignedShort();
1707:                //Ignore all informations contained
1708:                ehs.skipBytes(length - 2);
1709:
1710:                FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,
1711:                        "Skipping unsupported PLT marker");
1712:            }
1713:
1714:            /**
1715:             * Reads the RGN marker segment of the codestream header.
1716:             *
1717:             * <p>May be used in tile or main header. If used in main header, it
1718:             * refers to the maxshift value of a component in all tiles. When used in
1719:             * tile header, only the particular tile-component is affected.</p>
1720:             *
1721:             * @param ehs The encoder header stream.
1722:             *
1723:             * @param mainh Flag indicating whether or not this marker segment is read
1724:             * from the main header.
1725:             *
1726:             * @param tileIdx The index of the current tile
1727:             *
1728:             * @param tpIdx Tile-part index
1729:             *
1730:             * @exception IOException If an I/O error occurs while reading from the
1731:             * encoder header stream
1732:             * */
1733:            private void readRGN(DataInputStream ehs, boolean mainh,
1734:                    int tileIdx, int tpIdx) throws IOException {
1735:                int comp; // ROI component
1736:                int i; // loop variable
1737:                int tempComp; // Component for
1738:                HeaderInfo.RGN ms = hi.getNewRGN();
1739:
1740:                // Lrgn (marker length)
1741:                ms.lrgn = ehs.readUnsignedShort();
1742:
1743:                // Read component
1744:                ms.crgn = comp = (nComp < 257) ? ehs.readUnsignedByte() : ehs
1745:                        .readUnsignedShort();
1746:                if (comp >= nComp) {
1747:                    throw new CorruptedCodestreamException("Invalid component "
1748:                            + "index in RGN marker" + comp);
1749:                }
1750:
1751:                // Read type of RGN.(Srgn) 
1752:                ms.srgn = ehs.readUnsignedByte();
1753:
1754:                // Check that we can handle it.
1755:                if (ms.srgn != SRGN_IMPLICIT)
1756:                    throw new CorruptedCodestreamException(
1757:                            "Unknown or unsupported "
1758:                                    + "Srgn parameter in ROI " + "marker");
1759:
1760:                if (decSpec.rois == null) { // No maxshift spec defined
1761:                    // Create needed ModuleSpec
1762:                    decSpec.rois = new MaxShiftSpec(nTiles, nComp,
1763:                            ModuleSpec.SPEC_TYPE_TILE_COMP, "null");
1764:                }
1765:
1766:                // SPrgn
1767:                ms.sprgn = ehs.readUnsignedByte();
1768:
1769:                if (mainh) {
1770:                    hi.rgn.put("main_c" + comp, ms);
1771:                    decSpec.rois.setCompDef(comp, new Integer(ms.sprgn));
1772:                } else {
1773:                    hi.rgn.put("t" + tileIdx + "_c" + comp, ms);
1774:                    decSpec.rois.setTileCompVal(tileIdx, comp, new Integer(
1775:                            ms.sprgn));
1776:                }
1777:
1778:                // Check marker length
1779:                checkMarkerLength(ehs, "RGN marker");
1780:            }
1781:
1782:            /**
1783:             * Reads the PPM marker segment of the main header.
1784:             *
1785:             * @param ehs The encoder header stream.
1786:             *
1787:             * @exception IOException If an I/O error occurs while reading from the
1788:             * encoder header stream
1789:             * */
1790:            private void readPPM(DataInputStream ehs) throws IOException {
1791:                int curMarkSegLen;
1792:                int i, indx, len, off;
1793:                int remSegLen;
1794:                byte[] b;
1795:
1796:                // If first time readPPM method is called allocate arrays for packed
1797:                // packet data
1798:                if (pPMMarkerData == null) {
1799:                    pPMMarkerData = new byte[nPPMMarkSeg][];
1800:                    tileOfTileParts = new Vector();
1801:                    decSpec.pphs.setDefault(new Boolean(true));
1802:                }
1803:
1804:                // Lppm (marker length)
1805:                curMarkSegLen = ehs.readUnsignedShort();
1806:                remSegLen = curMarkSegLen - 3;
1807:
1808:                // Zppm (index of PPM marker)
1809:                indx = ehs.readUnsignedByte();
1810:
1811:                // Read Nppm and Ippm data 
1812:                pPMMarkerData[indx] = new byte[remSegLen];
1813:                ehs.read(pPMMarkerData[indx], 0, remSegLen);
1814:
1815:                // Check marker length
1816:                checkMarkerLength(ehs, "PPM marker");
1817:            }
1818:
1819:            /**
1820:             * Teads the PPT marker segment of the main header.
1821:             *
1822:             * @param ehs The encoder header stream.
1823:             *
1824:             * @param tile The tile to which the current tile part belongs
1825:             *
1826:             * @param tpIdx Tile-part index
1827:             *
1828:             * @exception IOException If an I/O error occurs while reading from the
1829:             * encoder header stream
1830:             * */
1831:            private void readPPT(DataInputStream ehs, int tile, int tpIdx)
1832:                    throws IOException {
1833:                int curMarkSegLen;
1834:                int indx, len = 0;
1835:                byte[] temp;
1836:
1837:                if (tilePartPkdPktHeaders == null) {
1838:                    tilePartPkdPktHeaders = new byte[nTiles][][][];
1839:                }
1840:
1841:                if (tilePartPkdPktHeaders[tile] == null) {
1842:                    tilePartPkdPktHeaders[tile] = new byte[nTileParts[tile]][][];
1843:                }
1844:
1845:                if (tilePartPkdPktHeaders[tile][tpIdx] == null) {
1846:                    tilePartPkdPktHeaders[tile][tpIdx] = new byte[nPPTMarkSeg[tile][tpIdx]][];
1847:                }
1848:
1849:                // Lppt (marker length)
1850:                curMarkSegLen = ehs.readUnsignedShort();
1851:
1852:                // Zppt (index of PPT marker)
1853:                indx = ehs.readUnsignedByte();
1854:
1855:                // Ippt (packed packet headers)
1856:                temp = new byte[curMarkSegLen - 3];
1857:                ehs.read(temp);
1858:                tilePartPkdPktHeaders[tile][tpIdx][indx] = temp;
1859:
1860:                // Check marker length
1861:                checkMarkerLength(ehs, "PPT marker");
1862:
1863:                decSpec.pphs.setTileDef(tile, new Boolean(true));
1864:            }
1865:
1866:            /** 
1867:             * This method extract a marker segment from the main header and stores it
1868:             * into a byte buffer for the second pass. The marker segment is first
1869:             * identified. Then its flag is activated. Finally, its content is
1870:             * buffered into a byte array stored in an hashTable.
1871:             *
1872:             * <p>If the marker is not recognized, it prints a warning and skips it
1873:             * according to its length.</p>
1874:             *
1875:             * <p>SIZ marker segment shall be the first encountered marker segment.</p>
1876:             *
1877:             * @param marker The marker segment to process
1878:             *
1879:             * @param ehs The encoded header stream
1880:             * */
1881:            private void extractMainMarkSeg(short marker, RandomAccessIO ehs)
1882:                    throws IOException {
1883:                if (nfMarkSeg == 0) { // First non-delimiting marker of the header
1884:                    // JPEG 2000 part 1 specify that it must be SIZ
1885:                    if (marker != SIZ) {
1886:                        throw new CorruptedCodestreamException(
1887:                                "First marker after " + "SOC " + "must be SIZ "
1888:                                        + Integer.toHexString(marker));
1889:                    }
1890:                }
1891:
1892:                String htKey = ""; // Name used as a key for the hash-table
1893:                if (ht == null) {
1894:                    ht = new Hashtable();
1895:                }
1896:
1897:                switch (marker) {
1898:                case SIZ:
1899:                    if ((nfMarkSeg & SIZ_FOUND) != 0) {
1900:                        throw new CorruptedCodestreamException(
1901:                                "More than one SIZ marker "
1902:                                        + "segment found in main " + "header");
1903:                    }
1904:                    nfMarkSeg |= SIZ_FOUND;
1905:                    htKey = "SIZ";
1906:                    break;
1907:                case SOD:
1908:                    throw new CorruptedCodestreamException(
1909:                            "SOD found in main header");
1910:                case EOC:
1911:                    throw new CorruptedCodestreamException(
1912:                            "EOC found in main header");
1913:                case SOT:
1914:                    if ((nfMarkSeg & SOT_FOUND) != 0) {
1915:                        throw new CorruptedCodestreamException(
1916:                                "More than one SOT " + "marker "
1917:                                        + "found right after " + "main "
1918:                                        + "or tile header");
1919:                    }
1920:                    nfMarkSeg |= SOT_FOUND;
1921:                    return;
1922:                case COD:
1923:                    if ((nfMarkSeg & COD_FOUND) != 0) {
1924:                        throw new CorruptedCodestreamException(
1925:                                "More than one COD " + "marker "
1926:                                        + "found in main header");
1927:                    }
1928:                    nfMarkSeg |= COD_FOUND;
1929:                    htKey = "COD";
1930:                    break;
1931:                case COC:
1932:                    nfMarkSeg |= COC_FOUND;
1933:                    htKey = "COC" + (nCOCMarkSeg++);
1934:                    break;
1935:                case QCD:
1936:                    if ((nfMarkSeg & QCD_FOUND) != 0) {
1937:                        throw new CorruptedCodestreamException(
1938:                                "More than one QCD " + "marker "
1939:                                        + "found in main header");
1940:                    }
1941:                    nfMarkSeg |= QCD_FOUND;
1942:                    htKey = "QCD";
1943:                    break;
1944:                case QCC:
1945:                    nfMarkSeg |= QCC_FOUND;
1946:                    htKey = "QCC" + (nQCCMarkSeg++);
1947:                    break;
1948:                case RGN:
1949:                    nfMarkSeg |= RGN_FOUND;
1950:                    htKey = "RGN" + (nRGNMarkSeg++);
1951:                    break;
1952:                case COM:
1953:                    nfMarkSeg |= COM_FOUND;
1954:                    htKey = "COM" + (nCOMMarkSeg++);
1955:                    break;
1956:                case CRG:
1957:                    if ((nfMarkSeg & CRG_FOUND) != 0) {
1958:                        throw new CorruptedCodestreamException(
1959:                                "More than one CRG " + "marker "
1960:                                        + "found in main header");
1961:                    }
1962:                    nfMarkSeg |= CRG_FOUND;
1963:                    htKey = "CRG";
1964:                    break;
1965:                case PPM:
1966:                    nfMarkSeg |= PPM_FOUND;
1967:                    htKey = "PPM" + (nPPMMarkSeg++);
1968:                    break;
1969:                case TLM:
1970:                    if ((nfMarkSeg & TLM_FOUND) != 0) {
1971:                        FacilityManager.getMsgLogger().printmsg(
1972:                                MsgLogger.INFO,
1973:                                "More than one TLM " + "marker "
1974:                                        + "found in main header");
1975:                        /** XXX It is legal to have multiple TLM segments.
1976:                        throw new CorruptedCodestreamException("More than one TLM "+
1977:                                                              "marker "+
1978:                                                              "found in main header");
1979:                         */
1980:                    }
1981:                    nfMarkSeg |= TLM_FOUND;
1982:                    break;
1983:                case PLM:
1984:                    if ((nfMarkSeg & PLM_FOUND) != 0) {
1985:                        throw new CorruptedCodestreamException(
1986:                                "More than one PLM " + "marker "
1987:                                        + "found in main header");
1988:                    }
1989:                    FacilityManager.getMsgLogger().printmsg(
1990:                            MsgLogger.WARNING,
1991:                            "PLM marker segment found but "
1992:                                    + "not used by by JJ2000 decoder.");
1993:                    nfMarkSeg |= PLM_FOUND;
1994:                    htKey = "PLM";
1995:                    break;
1996:                case POC:
1997:                    if ((nfMarkSeg & POC_FOUND) != 0) {
1998:                        throw new CorruptedCodestreamException(
1999:                                "More than one POC " + "marker segment found "
2000:                                        + "in main header");
2001:                    }
2002:                    nfMarkSeg |= POC_FOUND;
2003:                    htKey = "POC";
2004:                    break;
2005:                case PLT:
2006:                    throw new CorruptedCodestreamException(
2007:                            "PLT found in main header");
2008:                case PPT:
2009:                    throw new CorruptedCodestreamException(
2010:                            "PPT found in main header");
2011:                default:
2012:                    htKey = "UNKNOWN";
2013:                    FacilityManager.getMsgLogger().printmsg(
2014:                            MsgLogger.WARNING,
2015:                            "Non recognized marker segment (0x"
2016:                                    + Integer.toHexString(marker)
2017:                                    + ") in main header!");
2018:                    break;
2019:                }
2020:
2021:                if (marker < 0xffffff30 || marker > 0xffffff3f) {
2022:                    // Read marker segment length and create corresponding byte buffer
2023:                    int markSegLen = ehs.readUnsignedShort();
2024:                    byte[] buf = new byte[markSegLen];
2025:
2026:                    // Copy data (after re-insertion of the marker segment length);
2027:                    buf[0] = (byte) ((markSegLen >> 8) & 0xFF);
2028:                    buf[1] = (byte) (markSegLen & 0xFF);
2029:                    ehs.readFully(buf, 2, markSegLen - 2);
2030:
2031:                    if (!htKey.equals("UNKNOWN")) {
2032:                        // Store array in hashTable
2033:                        ht.put(htKey, buf);
2034:                    }
2035:                }
2036:            }
2037:
2038:            /**     
2039:             * This method extracts a marker segment in a tile-part header and stores
2040:             * it into a byte buffer for the second pass. The marker is first
2041:             * recognized, then its flag is activated and, finally, its content is
2042:             * buffered in an element of byte arrays accessible thanks to a hashTable.
2043:             * If a marker segment is not recognized, it prints a warning and skip it
2044:             * according to its length.
2045:             *  
2046:             * @param marker The marker to process
2047:             *  
2048:             * @param ehs The encoded header stream
2049:             *                                            
2050:             * @param tileIdx The index of the current tile
2051:             *
2052:             * @param tilePartIdx The index of the current tile part
2053:             * */
2054:            public void extractTilePartMarkSeg(short marker,
2055:                    RandomAccessIO ehs, int tileIdx, int tilePartIdx)
2056:                    throws IOException {
2057:
2058:                String htKey = ""; // Name used as a hash-table key
2059:                if (ht == null) {
2060:                    ht = new Hashtable();
2061:                }
2062:
2063:                switch (marker) {
2064:                case SOT:
2065:                    throw new CorruptedCodestreamException("Second SOT marker "
2066:                            + "segment found in tile-" + "part header");
2067:                case SIZ:
2068:                    throw new CorruptedCodestreamException(
2069:                            "SIZ found in tile-part" + " header");
2070:                case EOC:
2071:                    throw new CorruptedCodestreamException(
2072:                            "EOC found in tile-part" + " header");
2073:                case TLM:
2074:                    throw new CorruptedCodestreamException(
2075:                            "TLM found in tile-part" + " header");
2076:                case PPM:
2077:                    throw new CorruptedCodestreamException(
2078:                            "PPM found in tile-part" + " header");
2079:                case COD:
2080:                    if ((nfMarkSeg & COD_FOUND) != 0) {
2081:                        throw new CorruptedCodestreamException(
2082:                                "More than one COD " + "marker "
2083:                                        + "found in tile-part" + " header");
2084:                    }
2085:                    nfMarkSeg |= COD_FOUND;
2086:                    htKey = "COD";
2087:                    break;
2088:                case COC:
2089:                    nfMarkSeg |= COC_FOUND;
2090:                    htKey = "COC" + (nCOCMarkSeg++);
2091:                    break;
2092:                case QCD:
2093:                    if ((nfMarkSeg & QCD_FOUND) != 0) {
2094:                        throw new CorruptedCodestreamException(
2095:                                "More than one QCD " + "marker "
2096:                                        + "found in tile-part" + " header");
2097:                    }
2098:                    nfMarkSeg |= QCD_FOUND;
2099:                    htKey = "QCD";
2100:                    break;
2101:                case QCC:
2102:                    nfMarkSeg |= QCC_FOUND;
2103:                    htKey = "QCC" + (nQCCMarkSeg++);
2104:                    break;
2105:                case RGN:
2106:                    nfMarkSeg |= RGN_FOUND;
2107:                    htKey = "RGN" + (nRGNMarkSeg++);
2108:                    break;
2109:                case COM:
2110:                    nfMarkSeg |= COM_FOUND;
2111:                    htKey = "COM" + (nCOMMarkSeg++);
2112:                    break;
2113:                case CRG:
2114:                    throw new CorruptedCodestreamException(
2115:                            "CRG marker found in " + "tile-part header");
2116:                case PPT:
2117:                    nfMarkSeg |= PPT_FOUND;
2118:                    if (nPPTMarkSeg == null) {
2119:                        nPPTMarkSeg = new int[nTiles][];
2120:                    }
2121:                    if (nPPTMarkSeg[tileIdx] == null) {
2122:                        nPPTMarkSeg[tileIdx] = new int[nTileParts[tileIdx]];
2123:                    }
2124:                    htKey = "PPT" + (nPPTMarkSeg[tileIdx][tilePartIdx]++);
2125:                    break;
2126:                case SOD:
2127:                    nfMarkSeg |= SOD_FOUND;
2128:                    return;
2129:                case POC:
2130:                    if ((nfMarkSeg & POC_FOUND) != 0)
2131:                        throw new CorruptedCodestreamException(
2132:                                "More than one POC " + "marker segment found "
2133:                                        + "in tile-part" + " header");
2134:                    nfMarkSeg |= POC_FOUND;
2135:                    htKey = "POC";
2136:                    break;
2137:                case PLT:
2138:                    if ((nfMarkSeg & PLM_FOUND) != 0) {
2139:                        throw new CorruptedCodestreamException(
2140:                                "PLT marker found even" + "though PLM marker "
2141:                                        + "found in main header");
2142:                    }
2143:                    FacilityManager.getMsgLogger().printmsg(
2144:                            MsgLogger.WARNING,
2145:                            "PLT marker segment found but "
2146:                                    + "not used by JJ2000 decoder.");
2147:                    htKey = "UNKNOWN";
2148:                    break;
2149:                default:
2150:                    htKey = "UNKNOWN";
2151:                    FacilityManager.getMsgLogger().printmsg(
2152:                            MsgLogger.WARNING,
2153:                            "Non recognized marker segment (0x"
2154:                                    + Integer.toHexString(marker)
2155:                                    + ") in tile-part header" + " of tile "
2156:                                    + tileIdx + " !");
2157:                    break;
2158:                }
2159:
2160:                // Read marker segment length and create corresponding byte buffer
2161:                int markSegLen = ehs.readUnsignedShort();
2162:                byte[] buf = new byte[markSegLen];
2163:
2164:                // Copy data (after re-insertion of marker segment length);
2165:                buf[0] = (byte) ((markSegLen >> 8) & 0xFF);
2166:                buf[1] = (byte) (markSegLen & 0xFF);
2167:                ehs.readFully(buf, 2, markSegLen - 2);
2168:
2169:                if (!htKey.equals("UNKNOWN")) {
2170:                    // Store array in hashTable
2171:                    ht.put(htKey, buf);
2172:                }
2173:            }
2174:
2175:            /** 
2176:             * Retrieves and reads all marker segments found in the main header during
2177:             * the first pass.
2178:             * */
2179:            private void readFoundMainMarkSeg() throws IOException {
2180:                DataInputStream dis;
2181:                ByteArrayInputStream bais;
2182:
2183:                // SIZ marker segment
2184:                if ((nfMarkSeg & SIZ_FOUND) != 0) {
2185:                    bais = new ByteArrayInputStream((byte[]) (ht.get("SIZ")));
2186:                    readSIZ(new DataInputStream(bais));
2187:                }
2188:
2189:                // COM marker segments
2190:                if ((nfMarkSeg & COM_FOUND) != 0) {
2191:                    for (int i = 0; i < nCOMMarkSeg; i++) {
2192:                        bais = new ByteArrayInputStream((byte[]) (ht.get("COM"
2193:                                + i)));
2194:                        readCOM(new DataInputStream(bais), true, 0, i);
2195:                    }
2196:                }
2197:
2198:                // CRG marker segment
2199:                if ((nfMarkSeg & CRG_FOUND) != 0) {
2200:                    bais = new ByteArrayInputStream((byte[]) (ht.get("CRG")));
2201:                    readCRG(new DataInputStream(bais));
2202:                }
2203:
2204:                // COD marker segment
2205:                if ((nfMarkSeg & COD_FOUND) != 0) {
2206:                    bais = new ByteArrayInputStream((byte[]) (ht.get("COD")));
2207:                    readCOD(new DataInputStream(bais), true, 0, 0);
2208:                }
2209:
2210:                // COC marker segments
2211:                if ((nfMarkSeg & COC_FOUND) != 0) {
2212:                    for (int i = 0; i < nCOCMarkSeg; i++) {
2213:                        bais = new ByteArrayInputStream((byte[]) (ht.get("COC"
2214:                                + i)));
2215:                        readCOC(new DataInputStream(bais), true, 0, 0);
2216:                    }
2217:                }
2218:
2219:                // RGN marker segment
2220:                if ((nfMarkSeg & RGN_FOUND) != 0) {
2221:                    for (int i = 0; i < nRGNMarkSeg; i++) {
2222:                        bais = new ByteArrayInputStream((byte[]) (ht.get("RGN"
2223:                                + i)));
2224:                        readRGN(new DataInputStream(bais), true, 0, 0);
2225:                    }
2226:                }
2227:
2228:                // QCD marker segment
2229:                if ((nfMarkSeg & QCD_FOUND) != 0) {
2230:                    bais = new ByteArrayInputStream((byte[]) (ht.get("QCD")));
2231:                    readQCD(new DataInputStream(bais), true, 0, 0);
2232:                }
2233:
2234:                // QCC marker segments
2235:                if ((nfMarkSeg & QCC_FOUND) != 0) {
2236:                    for (int i = 0; i < nQCCMarkSeg; i++) {
2237:                        bais = new ByteArrayInputStream((byte[]) (ht.get("QCC"
2238:                                + i)));
2239:                        readQCC(new DataInputStream(bais), true, 0, 0);
2240:                    }
2241:                }
2242:
2243:                // POC marker segment
2244:                if ((nfMarkSeg & POC_FOUND) != 0) {
2245:                    bais = new ByteArrayInputStream((byte[]) (ht.get("POC")));
2246:                    readPOC(new DataInputStream(bais), true, 0, 0);
2247:                }
2248:
2249:                // PPM marker segments
2250:                if ((nfMarkSeg & PPM_FOUND) != 0) {
2251:                    for (int i = 0; i < nPPMMarkSeg; i++) {
2252:                        bais = new ByteArrayInputStream((byte[]) (ht.get("PPM"
2253:                                + i)));
2254:                        readPPM(new DataInputStream(bais));
2255:                    }
2256:                }
2257:
2258:                // Reset the hashtable
2259:                ht = null;
2260:            }
2261:
2262:            /**
2263:             * Return the DecoderSpecs instance filled when reading the headers
2264:             *
2265:             * @retrieves and reads all marker segments previously found in the
2266:             * tile-part header.
2267:             *
2268:             * @param tileIdx The index of the current tile
2269:             * 
2270:             * @param tpIdx Index of the current tile-part
2271:             * */
2272:            public void readFoundTilePartMarkSeg(int tileIdx, int tpIdx)
2273:                    throws IOException {
2274:
2275:                DataInputStream dis;
2276:                ByteArrayInputStream bais;
2277:
2278:                // COD marker segment
2279:                if ((nfMarkSeg & COD_FOUND) != 0) {
2280:                    bais = new ByteArrayInputStream((byte[]) (ht.get("COD")));
2281:                    readCOD(new DataInputStream(bais), false, tileIdx, tpIdx);
2282:                }
2283:
2284:                // COC marker segments
2285:                if ((nfMarkSeg & COC_FOUND) != 0) {
2286:                    for (int i = 0; i < nCOCMarkSeg; i++) {
2287:                        bais = new ByteArrayInputStream((byte[]) (ht.get("COC"
2288:                                + i)));
2289:                        readCOC(new DataInputStream(bais), false, tileIdx,
2290:                                tpIdx);
2291:                    }
2292:                }
2293:
2294:                // RGN marker segment
2295:                if ((nfMarkSeg & RGN_FOUND) != 0) {
2296:                    for (int i = 0; i < nRGNMarkSeg; i++) {
2297:                        bais = new ByteArrayInputStream((byte[]) (ht.get("RGN"
2298:                                + i)));
2299:                        readRGN(new DataInputStream(bais), false, tileIdx,
2300:                                tpIdx);
2301:                    }
2302:                }
2303:
2304:                // QCD marker segment
2305:                if ((nfMarkSeg & QCD_FOUND) != 0) {
2306:                    bais = new ByteArrayInputStream((byte[]) (ht.get("QCD")));
2307:                    readQCD(new DataInputStream(bais), false, tileIdx, tpIdx);
2308:                }
2309:
2310:                // QCC marker segments
2311:                if ((nfMarkSeg & QCC_FOUND) != 0) {
2312:                    for (int i = 0; i < nQCCMarkSeg; i++) {
2313:                        bais = new ByteArrayInputStream((byte[]) (ht.get("QCC"
2314:                                + i)));
2315:                        readQCC(new DataInputStream(bais), false, tileIdx,
2316:                                tpIdx);
2317:                    }
2318:                }
2319:                // POC marker segment
2320:                if ((nfMarkSeg & POC_FOUND) != 0) {
2321:                    bais = new ByteArrayInputStream((byte[]) (ht.get("POC")));
2322:                    readPOC(new DataInputStream(bais), false, tileIdx, tpIdx);
2323:                }
2324:
2325:                // COM marker segments
2326:                if ((nfMarkSeg & COM_FOUND) != 0) {
2327:                    for (int i = 0; i < nCOMMarkSeg; i++) {
2328:                        bais = new ByteArrayInputStream((byte[]) (ht.get("COM"
2329:                                + i)));
2330:                        readCOM(new DataInputStream(bais), false, tileIdx, i);
2331:                    }
2332:                }
2333:
2334:                // PPT marker segments
2335:                if ((nfMarkSeg & PPT_FOUND) != 0) {
2336:                    for (int i = 0; i < nPPTMarkSeg[tileIdx][tpIdx]; i++) {
2337:                        bais = new ByteArrayInputStream((byte[]) (ht.get("PPT"
2338:                                + i)));
2339:                        readPPT(new DataInputStream(bais), tileIdx, tpIdx);
2340:                    }
2341:                }
2342:
2343:                // Reset ht
2344:                ht = null;
2345:            }
2346:
2347:            /** 
2348:             * Return the DecoderSpecs instance filled when reading the headers
2349:             * 
2350:             * @return The DecoderSpecs of the decoder
2351:             * */
2352:            public DecoderSpecs getDecoderSpecs() {
2353:                return decSpec;
2354:            }
2355:
2356:            /**
2357:             * Creates a HeaderDecoder instance and read in two passes the main header
2358:             * of the codestream. The first and last marker segments shall be
2359:             * respectively SOC and SOT.
2360:             *
2361:             * @param ehs The encoded header stream where marker segment are
2362:             * extracted.
2363:             *
2364:             * @param j2krparam The parameter list of the decoder
2365:             *
2366:             * @param hi The HeaderInfo holding information found in marker segments
2367:             *
2368:             * @exception IOException If an I/O error occurs while reading from the
2369:             * encoded header stream.
2370:             *
2371:             * @exception EOFException If the end of the encoded header stream is
2372:             * reached before getting all the data.
2373:             *
2374:             * @exception CorruptedCodestreamException If invalid data is found in the
2375:             * codestream main header.
2376:             * */
2377:            public HeaderDecoder(RandomAccessIO ehs,
2378:                    J2KImageReadParamJava j2krparam, HeaderInfo hi)
2379:                    throws IOException {
2380:
2381:                this .hi = hi;
2382:                this .j2krparam = j2krparam;
2383:                mainHeadOff = ehs.getPos();
2384:                if (((short) ehs.readShort()) != Markers.SOC) {
2385:                    throw new CorruptedCodestreamException(
2386:                            "SOC marker segment not " + " found at the "
2387:                                    + "beginning of the " + "codestream.");
2388:                }
2389:
2390:                // First Pass: Decode and store main header information until the SOT
2391:                // marker segment is found
2392:                nfMarkSeg = 0;
2393:                do {
2394:                    extractMainMarkSeg(ehs.readShort(), ehs);
2395:                } while ((nfMarkSeg & SOT_FOUND) == 0); //Stop when SOT is found
2396:                ehs.seek(ehs.getPos() - 2); // Realign codestream on SOT marker
2397:
2398:                // Second pass: Read each marker segment previously found
2399:                readFoundMainMarkSeg();
2400:            }
2401:
2402:            /**
2403:             * Creates and returns the entropy decoder corresponding to the
2404:             * information read from the codestream header and with the special
2405:             * additional parameters from the parameter list.
2406:             *
2407:             * @param src The bit stream reader agent where to get code-block data
2408:             * from.
2409:             *
2410:             * @param j2krparam The parameter list containing parameters applicable to the
2411:             * entropy decoder (other parameters can also be present).
2412:             *
2413:             * @return The entropy decoder
2414:             * */
2415:            public EntropyDecoder createEntropyDecoder(CodedCBlkDataSrcDec src,
2416:                    J2KImageReadParamJava j2krparam) {
2417:                // Get error detection option
2418:                // boolean doer = j2krparam.getCer();;
2419:                boolean doer = true;
2420:                // Get verbose error detection option
2421:                //boolean verber = j2krparam.getVerbose();
2422:                boolean verber = false;
2423:
2424:                // Get maximum number of bit planes from m quit condition
2425:                //        int mMax = j2krparam.getMQuit();
2426:                int mMax = -1;
2427:                return new StdEntropyDecoder(src, decSpec, doer, verber, mMax);
2428:            }
2429:
2430:            /**
2431:             * Creates and returns the EnumeratedColorSpaceMapper
2432:             * corresponding to the information read from the JP2 image file
2433:             * via the ColorSpace parameter.
2434:             *
2435:             * @param src The bit stream reader agent where to get code-block
2436:             * data from.
2437:             * @param csMap provides color space information from the image file
2438:             *
2439:             * @return The color space mapping object
2440:             * @exception IOException image access exception
2441:             * @exception ICCProfileException if image contains a bad icc profile
2442:             * @exception ColorSpaceException if image contains a bad colorspace box
2443:             **/
2444:            /*
2445:             public BlkImgDataSrc createColorSpaceMapper(BlkImgDataSrc src,
2446:             ColorSpace csMap)
2447:             throws IOException, ICCProfileException, ColorSpaceException {
2448:             return ColorSpaceMapper.createInstance(src,csMap);
2449:             }
2450:             */
2451:            /**
2452:             * Creates and returns the ChannelDefinitonMapper which maps the
2453:             * input channels to the channel definition for the appropriate
2454:             * colorspace.
2455:             *
2456:             * @param src The bit stream reader agent where to get code-block
2457:             * data from.
2458:             * @param csMap provides color space information from the image file
2459:             *
2460:             * @return The channel definition mapping object
2461:             * @exception IOException image access exception
2462:             * @exception ColorSpaceException if image contains a bad colorspace box
2463:             **/
2464:            /*
2465:             public BlkImgDataSrc createChannelDefinitionMapper(BlkImgDataSrc src,
2466:             ColorSpace csMap)
2467:             throws IOException, ColorSpaceException {
2468:             return ChannelDefinitionMapper.createInstance(src,csMap);
2469:             }
2470:             */
2471:            /**
2472:             * Creates and returns the PalettizedColorSpaceMapper which uses
2473:             * the input samples as indicies into a sample palette to
2474:             * construct the output.
2475:             *
2476:             * @param src The bit stream reader agent where to get code-block
2477:             * data from.
2478:             * @param csMap provides color space information from the image file
2479:             *
2480:             * @return a  PalettizedColorSpaceMapper instance
2481:             * @exception IOException image access exception
2482:             * @exception ColorSpaceException if image contains a bad colorspace box
2483:             **/
2484:            /*
2485:             public BlkImgDataSrc createPalettizedColorSpaceMapper(BlkImgDataSrc src,
2486:             ColorSpace csMap)
2487:             throws IOException, ColorSpaceException {
2488:             return PalettizedColorSpaceMapper.createInstance(src, csMap); }
2489:             */
2490:            /**
2491:             * Creates and returns the Resampler which converts the input
2492:             * source to one in which all channels have the same number of
2493:             * samples.  This is required for colorspace conversions.
2494:             *
2495:             * @param src The bit stream reader agent where to get code-block
2496:             * data from.
2497:             * @param csMap provides color space information from the image file
2498:             *
2499:             * @return The resampled BlkImgDataSrc
2500:             * @exception IOException image access exception
2501:             * @exception ColorSpaceException if image contains a bad colorspace box
2502:             **/
2503:            /*
2504:             public BlkImgDataSrc createResampler(BlkImgDataSrc src,
2505:             ColorSpace csMap)
2506:             throws IOException, ColorSpaceException {
2507:             return Resampler.createInstance(src, csMap); }
2508:             */
2509:            /**
2510:             * Creates and returns the ROIDeScaler corresponding to the information
2511:             * read from the codestream header and with the special additional
2512:             * parameters from the parameter list.
2513:             *
2514:             * @param src The bit stream reader agent where to get code-block data
2515:             * from.
2516:             *
2517:             * @param pl The parameter list containing parameters applicable to the
2518:             * entropy decoder (other parameters can also be present).
2519:             *
2520:             * @return The ROI descaler
2521:             * */
2522:            public ROIDeScaler createROIDeScaler(CBlkQuantDataSrcDec src,
2523:                    J2KImageReadParamJava j2krparam, DecoderSpecs decSpec2) {
2524:                return ROIDeScaler.createInstance(src, j2krparam, decSpec2);
2525:            }
2526:
2527:            /** 
2528:             * Method that resets members indicating which markers have already been
2529:             * found
2530:             * */
2531:            public void resetHeaderMarkers() {
2532:                // The found status of PLM remains since only PLM OR PLT allowed
2533:                // Same goes for PPM and PPT
2534:                nfMarkSeg = nfMarkSeg & (PLM_FOUND | PPM_FOUND);
2535:                nCOCMarkSeg = 0;
2536:                nQCCMarkSeg = 0;
2537:                nCOMMarkSeg = 0;
2538:                nRGNMarkSeg = 0;
2539:            }
2540:
2541:            /**
2542:             * Print information about the current header.
2543:             *
2544:             * @return Information in a String
2545:             * */
2546:            public String toString() {
2547:                return hdStr;
2548:            }
2549:
2550:            /**
2551:             * Returns the parameters that are used in this class. It returns a 2D
2552:             * String array. Each of the 1D arrays is for a different option, and they
2553:             * have 3 elements. The first element is the option name, the second one
2554:             * is the synopsis and the third one is a long description of what the
2555:             * parameter is. The synopsis or description may be 'null', in which case
2556:             * it is assumed that there is no synopsis or description of the option,
2557:             * respectively.
2558:             *
2559:             * @return the options name, their synopsis and their explanation.
2560:             * */
2561:            public static String[][] getParameterInfo() {
2562:                return pinfo;
2563:            }
2564:
2565:            /**
2566:             * Return the number of tiles in the image
2567:             *
2568:             * @return The number of tiles
2569:             * */
2570:            public int getNumTiles() {
2571:                return nTiles;
2572:            }
2573:
2574:            /**
2575:             * Return the packed packet headers for a given tile.
2576:             *
2577:             * @return An input stream containing the packed packet headers for a
2578:             * particular tile
2579:             *
2580:             * @exception IOException If an I/O error occurs while reading from the
2581:             * encoder header stream
2582:             * */
2583:            public ByteArrayInputStream getPackedPktHead(int tile)
2584:                    throws IOException {
2585:
2586:                if (pkdPktHeaders == null) {
2587:                    int i, t;
2588:                    pkdPktHeaders = new ByteArrayOutputStream[nTiles];
2589:                    for (i = nTiles - 1; i >= 0; i--) {
2590:                        pkdPktHeaders[i] = new ByteArrayOutputStream();
2591:                    }
2592:                    if (nPPMMarkSeg != 0) {
2593:                        // If this is first time packed packet headers are requested,
2594:                        // create packed packet headers from Nppm and Ippm fields
2595:                        int nppm;
2596:                        int nTileParts = tileOfTileParts.size();
2597:                        byte[] temp;
2598:                        ByteArrayInputStream pph;
2599:                        ByteArrayOutputStream allNppmIppm = new ByteArrayOutputStream();
2600:
2601:                        // Concatenate all Nppm and Ippm fields
2602:                        for (i = 0; i < nPPMMarkSeg; i++) {
2603:                            allNppmIppm.write(pPMMarkerData[i]);
2604:                        }
2605:                        pph = new ByteArrayInputStream(allNppmIppm
2606:                                .toByteArray());
2607:
2608:                        // Read all packed packet headers and concatenate for each
2609:                        // tile part
2610:                        for (i = 0; i < nTileParts; i++) {
2611:                            t = ((Integer) tileOfTileParts.elementAt(i))
2612:                                    .intValue();
2613:                            // get Nppm value
2614:                            nppm = (pph.read() << 24) | (pph.read() << 16)
2615:                                    | (pph.read() << 8) | (pph.read());
2616:
2617:                            temp = new byte[nppm];
2618:                            // get ippm field
2619:                            pph.read(temp);
2620:                            pkdPktHeaders[t].write(temp);
2621:                        }
2622:                    } else {
2623:                        int tp;
2624:                        // Write all packed packet headers to pkdPktHeaders
2625:                        for (t = nTiles - 1; t >= 0; t--) {
2626:                            for (tp = 0; tp < nTileParts[t]; tp++) {
2627:                                for (i = 0; i < nPPTMarkSeg[t][tp]; i++) {
2628:                                    pkdPktHeaders[t]
2629:                                            .write(tilePartPkdPktHeaders[t][tp][i]);
2630:                                }
2631:                            }
2632:                        }
2633:                    }
2634:                }
2635:
2636:                return new ByteArrayInputStream(pkdPktHeaders[tile]
2637:                        .toByteArray());
2638:            }
2639:
2640:            /**
2641:             * Sets the tile of each tile part in order. This information is needed
2642:             * for identifying which packet header belongs to which tile when using
2643:             * the PPM marker.
2644:             *
2645:             * @param tile The tile number that the present tile part belongs to.
2646:             * */
2647:            public void setTileOfTileParts(int tile) {
2648:                if (nPPMMarkSeg != 0) {
2649:                    tileOfTileParts.addElement(new Integer(tile));
2650:                }
2651:            }
2652:
2653:            /**
2654:             * Returns the number of found marker segments in the current header.
2655:             *
2656:             * @return The number of marker segments found in the current header.
2657:             * */
2658:            public int getNumFoundMarkSeg() {
2659:                return nfMarkSeg;
2660:            }
2661:
2662:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.