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

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


0001:        /*
0002:         * $RCSfile: HeaderEncoder.java,v $
0003:         * $Revision: 1.1 $
0004:         * $Date: 2005/02/11 05:02:02 $
0005:         * $State: Exp $
0006:         *
0007:         * Class:                   HeaderEncoder
0008:         *
0009:         * Description:             Write codestream 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.writer;
0045:
0046:        import java.awt.Point;
0047:
0048:        import jj2000.j2k.quantization.quantizer.*;
0049:        import jj2000.j2k.wavelet.analysis.*;
0050:        import jj2000.j2k.entropy.encoder.*;
0051:        import jj2000.j2k.quantization.*;
0052:        import jj2000.j2k.image.input.*;
0053:        import jj2000.j2k.roi.encoder.*;
0054:        import jj2000.j2k.codestream.*;
0055:        import jj2000.j2k.wavelet.*;
0056:        import jj2000.j2k.entropy.*;
0057:        import jj2000.j2k.image.*;
0058:        import jj2000.j2k.util.*;
0059:        import jj2000.j2k.io.*;
0060:        import jj2000.j2k.*;
0061:
0062:        import java.util.*;
0063:        import java.io.*;
0064:
0065:        import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava;
0066:
0067:        /**
0068:         * This class writes almost of the markers and marker segments in main header
0069:         * and in tile-part headers. It is created by the run() method of the Encoder
0070:         * instance.
0071:         *
0072:         * <p>A marker segment includes a marker and eventually marker segment
0073:         * parameters. It is designed by the three letter code of the marker
0074:         * associated with the marker segment. JPEG 2000 part I defines 6 types of
0075:         * markers: <ul> <li> Delimiting : SOC,SOT,SOD,EOC (written in
0076:         * FileCodestreamWriter).</li> <li> Fixed information: SIZ.</li> <li>
0077:         * Functional: COD,COC,RGN,QCD,QCC,POC.</li> <li> In bit-stream: SOP,EPH.</li>
0078:         * <li> Pointer: TLM,PLM,PLT,PPM,PPT.</li> <li> Informational:
0079:         * CRG,COM.</li></ul>
0080:         *
0081:         * <p>Main Header is written when Encoder instance calls encodeMainHeader
0082:         * whereas tile-part headers are written when the EBCOTRateAllocator instance
0083:         * calls encodeTilePartHeader.
0084:         *
0085:         * @see Encoder
0086:         * @see Markers
0087:         * @see EBCOTRateAllocator
0088:         * */
0089:        public class HeaderEncoder implements  Markers, StdEntropyCoderOptions {
0090:
0091:            /** Nominal range bit of the component defining default values in QCD for
0092:             * main header */
0093:            private int defimgn;
0094:
0095:            /** Nominal range bit of the component defining default values in QCD for
0096:             * tile headers */
0097:            private int deftilenr;
0098:
0099:            /** The number of components in the image */
0100:            protected int nComp;
0101:
0102:            /** Whether or not to write the JJ2000 COM marker segment */
0103:            private boolean enJJ2KMarkSeg = true;
0104:
0105:            /** Other COM marker segments specified in the command line */
0106:            private String otherCOMMarkSeg = null;
0107:
0108:            /** The ByteArrayOutputStream to store header data. This handler
0109:             * is kept in order to use methods not accessible from a general
0110:             * DataOutputStream. For the other methods, it's better to use
0111:             * variable hbuf.
0112:             *
0113:             * @see #hbuf */
0114:            protected ByteArrayOutputStream baos;
0115:
0116:            /** The DataOutputStream to store header data. This kind of object
0117:             * is useful to write short, int, .... It's constructor takes
0118:             * baos as parameter.
0119:             *
0120:             * @see #baos
0121:             **/
0122:            protected DataOutputStream hbuf;
0123:
0124:            /** The image data reader. Source of original data info */
0125:            protected ImgData origSrc;
0126:
0127:            /** An array specifying, for each component,if the data was signed
0128:                or not */
0129:            protected boolean isOrigSig[];
0130:
0131:            /** Reference to the rate allocator */
0132:            protected PostCompRateAllocator ralloc;
0133:
0134:            /** Reference to the DWT module */
0135:            protected ForwardWT dwt;
0136:
0137:            /** Reference to the tiler module */
0138:            protected Tiler tiler;
0139:
0140:            /** Reference to the ROI module */
0141:            protected ROIScaler roiSc;
0142:
0143:            /** The encoder specifications */
0144:            protected J2KImageWriteParamJava wp;
0145:
0146:            /**
0147:             * Initializes the header writer with the references to the coding chain.
0148:             *
0149:             * @param origsrc The original image data (before any component mixing,
0150:             * tiling, etc.)
0151:             *
0152:             * @param isorigsig An array specifying for each component if it was
0153:             * originally signed or not.
0154:             *
0155:             * @param dwt The discrete wavelet transform module.
0156:             *
0157:             * @param tiler The tiler module.
0158:             *
0159:             * @param encSpec The encoder specifications
0160:             *
0161:             * @param roiSc The ROI scaler module.
0162:             *
0163:             * @param ralloc The post compression rate allocator.
0164:             * */
0165:            public HeaderEncoder(ImgData origsrc, boolean isorigsig[],
0166:                    ForwardWT dwt, Tiler tiler, J2KImageWriteParamJava wp,
0167:                    ROIScaler roiSc, PostCompRateAllocator ralloc) {
0168:                if (origsrc.getNumComps() != isorigsig.length) {
0169:                    throw new IllegalArgumentException();
0170:                }
0171:                this .origSrc = origsrc;
0172:                this .isOrigSig = isorigsig;
0173:                this .dwt = dwt;
0174:                this .tiler = tiler;
0175:                this .wp = wp;
0176:                this .roiSc = roiSc;
0177:                this .ralloc = ralloc;
0178:
0179:                baos = new ByteArrayOutputStream();
0180:                hbuf = new DataOutputStream(baos);
0181:                nComp = origsrc.getNumComps();
0182:                //        enJJ2KMarkSeg = wp.getHjj2000_COM();
0183:                //        otherCOMMarkSeg = wp.getHCOM();
0184:            }
0185:
0186:            /**
0187:             * Resets the contents of this HeaderEncoder to its initial state. It
0188:             * erases all the data in the header buffer and reactualizes the
0189:             * headerLength field of the bit stream writer.
0190:             * */
0191:            public void reset() {
0192:                baos.reset();
0193:                hbuf = new DataOutputStream(baos);
0194:            }
0195:
0196:            /**
0197:             * Returns the byte-buffer used to store the codestream header.
0198:             *
0199:             * @return A byte array countaining codestream header
0200:             * */
0201:            protected byte[] getBuffer() {
0202:                return baos.toByteArray();
0203:            }
0204:
0205:            /**
0206:             * Returns the length of the header.
0207:             *
0208:             * @return The length of the header in bytes
0209:             * */
0210:            public int getLength() {
0211:                return hbuf.size();
0212:            }
0213:
0214:            /**
0215:             * Writes the header to the specified BinaryDataOutput.
0216:             *
0217:             * @param out Where to write the header.
0218:             * */
0219:            public void writeTo(BinaryDataOutput out) throws IOException {
0220:                int i, len;
0221:                byte buf[];
0222:
0223:                buf = getBuffer();
0224:                len = getLength();
0225:
0226:                for (i = 0; i < len; i++) {
0227:                    out.writeByte(buf[i]);
0228:                }
0229:            }
0230:
0231:            /**
0232:             * Returns the number of bytes used in the codestream header's
0233:             * buffer.
0234:             *
0235:             * @return Header length in buffer (without any header
0236:             * overhead)
0237:             * */
0238:            protected int getBufferLength() {
0239:                return baos.size();
0240:            }
0241:
0242:            /**
0243:             * Writes the header to the specified OutputStream.
0244:             *
0245:             * @param out Where to write the header.
0246:             * */
0247:            public void writeTo(OutputStream out) throws IOException {
0248:                out.write(getBuffer(), 0, getBufferLength());
0249:            }
0250:
0251:            /**
0252:             * Start Of Codestream marker (SOC) signalling the beginning of a
0253:             * codestream.
0254:             * */
0255:            private void writeSOC() throws IOException {
0256:                hbuf.writeShort(SOC);
0257:            }
0258:
0259:            /**
0260:             * Writes SIZ marker segment of the codestream header. It is a fixed
0261:             * information marker segment containing informations about image and tile
0262:             * sizes. It is required in the main header immediately after SOC marker
0263:             * segment.
0264:             * */
0265:            private void writeSIZ() throws IOException {
0266:                int tmp;
0267:
0268:                // SIZ marker
0269:                hbuf.writeShort(SIZ);
0270:
0271:                // Lsiz (Marker length) corresponding to
0272:                // Lsiz(2 bytes)+Rsiz(2)+Xsiz(4)+Ysiz(4)+XOsiz(4)+YOsiz(4)+
0273:                // XTsiz(4)+YTsiz(4)+XTOsiz(4)+YTOsiz(4)+Csiz(2)+
0274:                // (Ssiz(1)+XRsiz(1)+YRsiz(1))*nComp
0275:                // markSegLen = 38 + 3*nComp;
0276:                int markSegLen = 38 + 3 * nComp;
0277:                hbuf.writeShort(markSegLen);
0278:
0279:                // Rsiz (codestream capabilities)
0280:                hbuf.writeShort(0); // JPEG 2000 - Part I
0281:
0282:                // Xsiz (original image width)
0283:                hbuf.writeInt(tiler.getImgWidth() + tiler.getImgULX());
0284:
0285:                // Ysiz (original image height)
0286:                hbuf.writeInt(tiler.getImgHeight() + tiler.getImgULY());
0287:
0288:                // XOsiz (horizontal offset from the origin of the reference
0289:                // grid to the left side of the image area)
0290:                hbuf.writeInt(tiler.getImgULX());
0291:
0292:                // YOsiz (vertical offset from the origin of the reference
0293:                // grid to the top side of the image area)
0294:                hbuf.writeInt(tiler.getImgULY());
0295:
0296:                // XTsiz (nominal tile width)
0297:                hbuf.writeInt(tiler.getNomTileWidth());
0298:
0299:                // YTsiz (nominal tile height)
0300:                hbuf.writeInt(tiler.getNomTileHeight());
0301:
0302:                Point torig = tiler.getTilingOrigin(null);
0303:                // XTOsiz (Horizontal offset from the origin of the reference
0304:                // grid to the left side of the first tile)
0305:                hbuf.writeInt(torig.x);
0306:
0307:                // YTOsiz (Vertical offset from the origin of the reference
0308:                // grid to the top side of the first tile)
0309:                hbuf.writeInt(torig.y);
0310:
0311:                // Csiz (number of components)
0312:                hbuf.writeShort(nComp);
0313:
0314:                // Bit-depth and downsampling factors.
0315:                for (int c = 0; c < nComp; c++) { // Loop on each component
0316:
0317:                    // Ssiz bit-depth before mixing
0318:                    tmp = origSrc.getNomRangeBits(c) - 1;
0319:
0320:                    tmp |= ((isOrigSig[c] ? 1 : 0) << SSIZ_DEPTH_BITS);
0321:                    hbuf.write(tmp);
0322:
0323:                    // XRsiz (component sub-sampling value x-wise)
0324:                    hbuf.write(tiler.getCompSubsX(c));
0325:
0326:                    // YRsiz (component sub-sampling value y-wise)
0327:                    hbuf.write(tiler.getCompSubsY(c));
0328:
0329:                } // End loop on each component
0330:
0331:            }
0332:
0333:            /**
0334:             * Writes COD marker segment. COD is a functional marker segment
0335:             * containing the code style default (coding style, decomposition,
0336:             * layering) used for compressing all the components in an image.
0337:             *
0338:             * <p>The values can be overriden for an individual component by a COC
0339:             * marker in either the main or the tile header.
0340:             *
0341:             * @param mh Flag indicating whether this marker belongs to the main
0342:             * header
0343:             *
0344:             * @param tileIdx Tile index if the marker belongs to a tile-part header
0345:             *
0346:             * @see #writeCOC
0347:             * */
0348:            protected void writeCOD(boolean mh, int tileIdx) throws IOException {
0349:                AnWTFilter[][] filt;
0350:                boolean precinctPartitionUsed;
0351:                int tmp;
0352:                int mrl = 0, a = 0;
0353:                int ppx = 0, ppy = 0;
0354:                Progression[] prog;
0355:
0356:                if (mh) {
0357:                    mrl = ((Integer) wp.getDecompositionLevel().getDefault())
0358:                            .intValue();
0359:                    // get default precinct size
0360:                    ppx = wp.getPrecinctPartition().getPPX(-1, -1, mrl);
0361:                    ppy = wp.getPrecinctPartition().getPPY(-1, -1, mrl);
0362:                    prog = (Progression[]) (wp.getProgressionType()
0363:                            .getDefault());
0364:                } else {
0365:                    mrl = ((Integer) wp.getDecompositionLevel().getTileDef(
0366:                            tileIdx)).intValue();
0367:                    // get precinct size for specified tile
0368:                    ppx = wp.getPrecinctPartition().getPPX(tileIdx, -1, mrl);
0369:                    ppy = wp.getPrecinctPartition().getPPY(tileIdx, -1, mrl);
0370:                    prog = (Progression[]) (wp.getProgressionType()
0371:                            .getTileDef(tileIdx));
0372:                }
0373:
0374:                if (ppx != PRECINCT_PARTITION_DEF_SIZE
0375:                        || ppy != PRECINCT_PARTITION_DEF_SIZE) {
0376:                    precinctPartitionUsed = true;
0377:                } else {
0378:                    precinctPartitionUsed = false;
0379:                }
0380:
0381:                if (precinctPartitionUsed) {
0382:                    // If precinct partition is used we add one byte per resolution
0383:                    // level i.e. mrl+1 (+1 for resolution 0).
0384:                    a = mrl + 1;
0385:                }
0386:
0387:                // Write COD marker
0388:                hbuf.writeShort(COD);
0389:
0390:                // Lcod (marker segment length (in bytes)) Basic : Lcod(2
0391:                // bytes)+Scod(1)+SGcod(4)+SPcod(5+a)  where:
0392:                // a=0 if no precinct partition is used
0393:                // a=mrl+1 if precinct partition used
0394:                int markSegLen = 12 + a;
0395:                hbuf.writeShort(markSegLen);
0396:
0397:                // Scod (coding style parameter)
0398:                tmp = 0;
0399:                if (precinctPartitionUsed)
0400:                    tmp = SCOX_PRECINCT_PARTITION;
0401:
0402:                // Are SOP markers used ?
0403:                if (mh) {
0404:                    if (((String) wp.getSOP().getDefault().toString())
0405:                            .equalsIgnoreCase("true")) {
0406:                        tmp |= SCOX_USE_SOP;
0407:                    }
0408:                } else {
0409:                    if (((String) wp.getSOP().getTileDef(tileIdx).toString())
0410:                            .equalsIgnoreCase("true")) {
0411:                        tmp |= SCOX_USE_SOP;
0412:                    }
0413:                }
0414:
0415:                // Are EPH markers used ?
0416:                if (mh) {
0417:                    if (((String) wp.getEPH().getDefault().toString())
0418:                            .equalsIgnoreCase("true")) {
0419:                        tmp |= SCOX_USE_EPH;
0420:                    }
0421:                } else {
0422:                    if (((String) wp.getEPH().getTileDef(tileIdx).toString())
0423:                            .equalsIgnoreCase("true")) {
0424:                        tmp |= SCOX_USE_EPH;
0425:                    }
0426:                }
0427:                if (dwt.getCbULX() != 0)
0428:                    tmp |= SCOX_HOR_CB_PART;
0429:                if (dwt.getCbULY() != 0)
0430:                    tmp |= SCOX_VER_CB_PART;
0431:                hbuf.write(tmp);
0432:
0433:                // SGcod
0434:                // Progression order
0435:                hbuf.write(prog[0].type);
0436:
0437:                // Number of layers
0438:                hbuf.writeShort(ralloc.getNumLayers());
0439:
0440:                // Multiple component transform
0441:                // CSsiz (Color transform)
0442:                String str = null;
0443:                if (mh)
0444:                    str = (String) wp.getComponentTransformation().getDefault();
0445:                else
0446:                    str = (String) wp.getComponentTransformation().getTileDef(
0447:                            tileIdx);
0448:
0449:                if (str.equals("none"))
0450:                    hbuf.write(0);
0451:                else
0452:                    hbuf.write(1);
0453:
0454:                // SPcod
0455:                // Number of decomposition levels
0456:                hbuf.write(mrl);
0457:
0458:                // Code-block width and height
0459:                if (mh) {
0460:                    // main header, get default values
0461:                    tmp = wp.getCodeBlockSize().getCBlkWidth(
0462:                            ModuleSpec.SPEC_DEF, -1, -1);
0463:                    hbuf.write(MathUtil.log2(tmp) - 2);
0464:                    tmp = wp.getCodeBlockSize().getCBlkHeight(
0465:                            ModuleSpec.SPEC_DEF, -1, -1);
0466:                    hbuf.write(MathUtil.log2(tmp) - 2);
0467:                } else {
0468:                    // tile header, get tile default values
0469:                    tmp = wp.getCodeBlockSize().getCBlkWidth(
0470:                            ModuleSpec.SPEC_TILE_DEF, tileIdx, -1);
0471:                    hbuf.write(MathUtil.log2(tmp) - 2);
0472:                    tmp = wp.getCodeBlockSize().getCBlkHeight(
0473:                            ModuleSpec.SPEC_TILE_DEF, tileIdx, -1);
0474:                    hbuf.write(MathUtil.log2(tmp) - 2);
0475:                }
0476:
0477:                // Style of the code-block coding passes
0478:                tmp = 0;
0479:                if (mh) { // Main header
0480:                    // Selective arithmetic coding bypass ?
0481:                    if (((String) wp.getBypass().getDefault()).equals("true")) {
0482:                        tmp |= OPT_BYPASS;
0483:                    }
0484:                    // MQ reset after each coding pass ?
0485:                    if (((String) wp.getResetMQ().getDefault()).equals("true")) {
0486:                        tmp |= OPT_RESET_MQ;
0487:                    }
0488:                    // MQ termination after each arithmetically coded coding pass ?
0489:                    if (((String) wp.getTerminateOnByte().getDefault())
0490:                            .equals("true")) {
0491:                        tmp |= OPT_TERM_PASS;
0492:                    }
0493:                    // Vertically stripe-causal context mode ?
0494:                    if (((String) wp.getCausalCXInfo().getDefault())
0495:                            .equals("true")) {
0496:                        tmp |= OPT_VERT_STR_CAUSAL;
0497:                    }
0498:                    // Predictable termination ?
0499:                    if (((String) wp.getMethodForMQTermination().getDefault())
0500:                            .equals("predict")) {
0501:                        tmp |= OPT_PRED_TERM;
0502:                    }
0503:                    // Error resilience segmentation symbol insertion ?
0504:                    if (((String) wp.getCodeSegSymbol().getDefault())
0505:                            .equals("true")) {
0506:                        tmp |= OPT_SEG_SYMBOLS;
0507:                    }
0508:                } else { // Tile header
0509:
0510:                    // Selective arithmetic coding bypass ?
0511:                    if (((String) wp.getBypass().getTileDef(tileIdx))
0512:                            .equals("true")) {
0513:                        tmp |= OPT_BYPASS;
0514:                    }
0515:                    // MQ reset after each coding pass ?
0516:                    if (((String) wp.getResetMQ().getTileDef(tileIdx))
0517:                            .equals("true")) {
0518:                        tmp |= OPT_RESET_MQ;
0519:                    }
0520:                    // MQ termination after each arithmetically coded coding pass ?
0521:                    if (((String) wp.getTerminateOnByte().getTileDef(tileIdx))
0522:                            .equals("true")) {
0523:                        tmp |= OPT_TERM_PASS;
0524:                    }
0525:                    // Vertically stripe-causal context mode ?
0526:                    if (((String) wp.getCausalCXInfo().getTileDef(tileIdx))
0527:                            .equals("true")) {
0528:                        tmp |= OPT_VERT_STR_CAUSAL;
0529:                    }
0530:                    // Predictable termination ?
0531:                    if (((String) wp.getMethodForMQTermination().getTileDef(
0532:                            tileIdx)).equals("predict")) {
0533:                        tmp |= OPT_PRED_TERM;
0534:                    }
0535:                    // Error resilience segmentation symbol insertion ?
0536:                    if (((String) wp.getCodeSegSymbol().getTileDef(tileIdx))
0537:                            .equals("true")) {
0538:                        tmp |= OPT_SEG_SYMBOLS;
0539:                    }
0540:                }
0541:                hbuf.write(tmp);
0542:
0543:                // Wavelet transform
0544:                // Wavelet Filter
0545:                if (mh) {
0546:                    filt = ((AnWTFilter[][]) wp.getFilters().getDefault());
0547:                    hbuf.write(filt[0][0].getFilterType());
0548:                } else {
0549:                    filt = ((AnWTFilter[][]) wp.getFilters()
0550:                            .getTileDef(tileIdx));
0551:                    hbuf.write(filt[0][0].getFilterType());
0552:                }
0553:
0554:                // Precinct partition
0555:                if (precinctPartitionUsed) {
0556:                    // Write the precinct size for each resolution level + 1
0557:                    // (resolution 0) if precinct partition is used.
0558:                    Vector v[] = null;
0559:                    if (mh) {
0560:                        v = (Vector[]) wp.getPrecinctPartition().getDefault();
0561:                    } else {
0562:                        v = (Vector[]) wp.getPrecinctPartition().getTileDef(
0563:                                tileIdx);
0564:                    }
0565:                    for (int r = mrl; r >= 0; r--) {
0566:                        if (r >= v[1].size()) {
0567:                            tmp = ((Integer) v[1].elementAt(v[1].size() - 1))
0568:                                    .intValue();
0569:                        } else {
0570:                            tmp = ((Integer) v[1].elementAt(r)).intValue();
0571:                        }
0572:                        int yExp = (MathUtil.log2(tmp) << 4) & 0x00F0;
0573:
0574:                        if (r >= v[0].size()) {
0575:                            tmp = ((Integer) v[0].elementAt(v[0].size() - 1))
0576:                                    .intValue();
0577:                        } else {
0578:                            tmp = ((Integer) v[0].elementAt(r)).intValue();
0579:                        }
0580:                        int xExp = MathUtil.log2(tmp) & 0x000F;
0581:                        hbuf.write(yExp | xExp);
0582:                    }
0583:                }
0584:            }
0585:
0586:            /**
0587:             * Writes COC marker segment . It is a functional marker containing the
0588:             * coding style for one component (coding style, decomposition, layering).
0589:             *
0590:             * <P>Its values overrides any value previously set in COD in the main
0591:             * header or in the tile header.
0592:             *
0593:             * @param mh Flag indicating whether the main header is to be written
0594:             *
0595:             * @param tileIdx Tile index
0596:             *
0597:             * @param compIdx index of the component which need use of the COC marker
0598:             * segment.
0599:             *
0600:             * @see #writeCOD
0601:             * */
0602:            protected void writeCOC(boolean mh, int tileIdx, int compIdx)
0603:                    throws IOException {
0604:                AnWTFilter[][] filt;
0605:                boolean precinctPartitionUsed;
0606:                int tmp;
0607:                int mrl = 0, a = 0;
0608:                int ppx = 0, ppy = 0;
0609:                Progression[] prog;
0610:
0611:                if (mh) {
0612:                    mrl = ((Integer) wp.getDecompositionLevel().getCompDef(
0613:                            compIdx)).intValue();
0614:                    // Get precinct size for specified component
0615:                    ppx = wp.getPrecinctPartition().getPPX(-1, compIdx, mrl);
0616:                    ppy = wp.getPrecinctPartition().getPPY(-1, compIdx, mrl);
0617:                    prog = (Progression[]) (wp.getProgressionType()
0618:                            .getCompDef(compIdx));
0619:                } else {
0620:                    mrl = ((Integer) wp.getDecompositionLevel().getTileCompVal(
0621:                            tileIdx, compIdx)).intValue();
0622:                    // Get precinct size for specified component/tile
0623:                    ppx = wp.getPrecinctPartition().getPPX(tileIdx, compIdx,
0624:                            mrl);
0625:                    ppy = wp.getPrecinctPartition().getPPY(tileIdx, compIdx,
0626:                            mrl);
0627:                    prog = (Progression[]) (wp.getProgressionType()
0628:                            .getTileCompVal(tileIdx, compIdx));
0629:                }
0630:
0631:                if (ppx != Markers.PRECINCT_PARTITION_DEF_SIZE
0632:                        || ppy != Markers.PRECINCT_PARTITION_DEF_SIZE) {
0633:                    precinctPartitionUsed = true;
0634:                } else {
0635:                    precinctPartitionUsed = false;
0636:                }
0637:                if (precinctPartitionUsed) {
0638:                    // If precinct partition is used we add one byte per resolution
0639:                    // level  i.e. mrl+1 (+1 for resolution 0).
0640:                    a = mrl + 1;
0641:                }
0642:
0643:                // COC marker
0644:                hbuf.writeShort(COC);
0645:
0646:                // Lcoc (marker segment length (in bytes))
0647:                // Basic: Lcoc(2 bytes)+Scoc(1)+ Ccoc(1 or 2)+SPcod(5+a)
0648:                int markSegLen = 8 + ((nComp < 257) ? 1 : 2) + a;
0649:
0650:                // Rounded to the nearest even value greater or equals
0651:                hbuf.writeShort(markSegLen);
0652:
0653:                // Ccoc
0654:                if (nComp < 257) {
0655:                    hbuf.write(compIdx);
0656:                } else {
0657:                    hbuf.writeShort(compIdx);
0658:                }
0659:
0660:                // Scod (coding style parameter)
0661:                tmp = 0;
0662:                if (precinctPartitionUsed) {
0663:                    tmp = SCOX_PRECINCT_PARTITION;
0664:                }
0665:                hbuf.write(tmp);
0666:
0667:                // SPcoc
0668:
0669:                // Number of decomposition levels
0670:                hbuf.write(mrl);
0671:
0672:                // Code-block width and height
0673:                if (mh) {
0674:                    // main header, get component default values
0675:                    tmp = wp.getCodeBlockSize().getCBlkWidth(
0676:                            ModuleSpec.SPEC_COMP_DEF, -1, compIdx);
0677:                    hbuf.write(MathUtil.log2(tmp) - 2);
0678:                    tmp = wp.getCodeBlockSize().getCBlkHeight(
0679:                            ModuleSpec.SPEC_COMP_DEF, -1, compIdx);
0680:                    hbuf.write(MathUtil.log2(tmp) - 2);
0681:                } else {
0682:                    // tile header, get tile component values
0683:                    tmp = wp.getCodeBlockSize().getCBlkWidth(
0684:                            ModuleSpec.SPEC_TILE_COMP, tileIdx, compIdx);
0685:                    hbuf.write(MathUtil.log2(tmp) - 2);
0686:                    tmp = wp.getCodeBlockSize().getCBlkHeight(
0687:                            ModuleSpec.SPEC_TILE_COMP, tileIdx, compIdx);
0688:                    hbuf.write(MathUtil.log2(tmp) - 2);
0689:                }
0690:
0691:                // Entropy coding mode options
0692:                tmp = 0;
0693:                if (mh) { // Main header
0694:                    // Lazy coding mode ?
0695:                    if (((String) wp.getBypass().getCompDef(compIdx))
0696:                            .equals("true")) {
0697:                        tmp |= OPT_BYPASS;
0698:                    }
0699:                    // MQ reset after each coding pass ?
0700:                    if (((String) wp.getResetMQ().getCompDef(compIdx))
0701:                            .equalsIgnoreCase("true")) {
0702:                        tmp |= OPT_RESET_MQ;
0703:                    }
0704:                    // MQ termination after each arithmetically coded coding pass ?
0705:                    if (((String) wp.getTerminateOnByte().getCompDef(compIdx))
0706:                            .equals("true")) {
0707:                        tmp |= OPT_TERM_PASS;
0708:                    }
0709:                    // Vertically stripe-causal context mode ?
0710:                    if (((String) wp.getCausalCXInfo().getCompDef(compIdx))
0711:                            .equals("true")) {
0712:                        tmp |= OPT_VERT_STR_CAUSAL;
0713:                    }
0714:                    // Predictable termination ?
0715:                    if (((String) wp.getMethodForMQTermination().getCompDef(
0716:                            compIdx)).equals("predict")) {
0717:                        tmp |= OPT_PRED_TERM;
0718:                    }
0719:                    // Error resilience segmentation symbol insertion ?
0720:                    if (((String) wp.getCodeSegSymbol().getCompDef(compIdx))
0721:                            .equals("true")) {
0722:                        tmp |= OPT_SEG_SYMBOLS;
0723:                    }
0724:                } else { // Tile Header
0725:                    if (((String) wp.getBypass().getTileCompVal(tileIdx,
0726:                            compIdx)).equals("true")) {
0727:                        tmp |= OPT_BYPASS;
0728:                    }
0729:                    // MQ reset after each coding pass ?
0730:                    if (((String) wp.getResetMQ().getTileCompVal(tileIdx,
0731:                            compIdx)).equals("true")) {
0732:                        tmp |= OPT_RESET_MQ;
0733:                    }
0734:                    // MQ termination after each arithmetically coded coding pass ?
0735:                    if (((String) wp.getTerminateOnByte().getTileCompVal(
0736:                            tileIdx, compIdx)).equals("true")) {
0737:                        tmp |= OPT_TERM_PASS;
0738:                    }
0739:                    // Vertically stripe-causal context mode ?
0740:                    if (((String) wp.getCausalCXInfo().getTileCompVal(tileIdx,
0741:                            compIdx)).equals("true")) {
0742:                        tmp |= OPT_VERT_STR_CAUSAL;
0743:                    }
0744:                    // Predictable termination ?
0745:                    if (((String) wp.getMethodForMQTermination()
0746:                            .getTileCompVal(tileIdx, compIdx))
0747:                            .equals("predict")) {
0748:                        tmp |= OPT_PRED_TERM;
0749:                    }
0750:                    // Error resilience segmentation symbol insertion ?
0751:                    if (((String) wp.getCodeSegSymbol().getTileCompVal(tileIdx,
0752:                            compIdx)).equals("true")) {
0753:                        tmp |= OPT_SEG_SYMBOLS;
0754:                    }
0755:                }
0756:                hbuf.write(tmp);
0757:
0758:                // Wavelet transform
0759:                // Wavelet Filter
0760:                if (mh) {
0761:                    filt = ((AnWTFilter[][]) wp.getFilters()
0762:                            .getCompDef(compIdx));
0763:                    hbuf.write(filt[0][0].getFilterType());
0764:                } else {
0765:                    filt = ((AnWTFilter[][]) wp.getFilters().getTileCompVal(
0766:                            tileIdx, compIdx));
0767:                    hbuf.write(filt[0][0].getFilterType());
0768:                }
0769:
0770:                // Precinct partition
0771:                if (precinctPartitionUsed) {
0772:                    // Write the precinct size for each resolution level + 1
0773:                    // (resolution 0) if precinct partition is used.
0774:                    Vector v[] = null;
0775:                    if (mh) {
0776:                        v = (Vector[]) wp.getPrecinctPartition().getCompDef(
0777:                                compIdx);
0778:                    } else {
0779:                        v = (Vector[]) wp.getPrecinctPartition()
0780:                                .getTileCompVal(tileIdx, compIdx);
0781:                    }
0782:                    for (int r = mrl; r >= 0; r--) {
0783:                        if (r >= v[1].size()) {
0784:                            tmp = ((Integer) v[1].elementAt(v[1].size() - 1))
0785:                                    .intValue();
0786:                        } else {
0787:                            tmp = ((Integer) v[1].elementAt(r)).intValue();
0788:                        }
0789:                        int yExp = (MathUtil.log2(tmp) << 4) & 0x00F0;
0790:
0791:                        if (r >= v[0].size()) {
0792:                            tmp = ((Integer) v[0].elementAt(v[0].size() - 1))
0793:                                    .intValue();
0794:                        } else {
0795:                            tmp = ((Integer) v[0].elementAt(r)).intValue();
0796:                        }
0797:                        int xExp = MathUtil.log2(tmp) & 0x000F;
0798:                        hbuf.write(yExp | xExp);
0799:                    }
0800:                }
0801:
0802:            }
0803:
0804:            /**
0805:             * Writes QCD marker segment in main header. QCD is a functional marker
0806:             * segment countaining the quantization default used for compressing all
0807:             * the components in an image. The values can be overriden for an
0808:             * individual component by a QCC marker in either the main or the tile
0809:             * header.
0810:             * */
0811:            protected void writeMainQCD() throws IOException {
0812:                float step;
0813:
0814:                String qType = (String) wp.getQuantizationType().getDefault();
0815:                float baseStep = ((Float) wp.getQuantizationStep().getDefault())
0816:                        .floatValue();
0817:                int gb = ((Integer) wp.getGuardBits().getDefault()).intValue();
0818:
0819:                boolean isDerived = qType.equals("derived");
0820:                boolean isReversible = qType.equals("reversible");
0821:                int mrl = ((Integer) wp.getDecompositionLevel().getDefault())
0822:                        .intValue();
0823:
0824:                int nt = dwt.getNumTiles();
0825:                int nc = dwt.getNumComps();
0826:                int tmpI;
0827:                int[] tcIdx = new int[2];
0828:                String tmpStr;
0829:                boolean notFound = true;
0830:                for (int t = 0; t < nt && notFound; t++) {
0831:                    for (int c = 0; c < nc && notFound; c++) {
0832:                        tmpI = ((Integer) wp.getDecompositionLevel()
0833:                                .getTileCompVal(t, c)).intValue();
0834:                        tmpStr = (String) wp.getQuantizationType()
0835:                                .getTileCompVal(t, c);
0836:                        if (tmpI == mrl && tmpStr.equals(qType)) {
0837:                            tcIdx[0] = t;
0838:                            tcIdx[1] = c;
0839:                            notFound = false;
0840:                        }
0841:                    }
0842:                }
0843:                if (notFound) {
0844:                    throw new Error(
0845:                            "Default representative for quantization type "
0846:                                    + " and number of decomposition levels not found "
0847:                                    + " in main QCD marker segment. "
0848:                                    + "You have found a JJ2000 bug.");
0849:                }
0850:                SubbandAn sb, csb, sbRoot = dwt.getAnSubbandTree(tcIdx[0],
0851:                        tcIdx[1]);
0852:                defimgn = dwt.getNomRangeBits(tcIdx[1]);
0853:
0854:                int nqcd; // Number of quantization step-size to transmit
0855:
0856:                // Get the quantization style
0857:                int qstyle = (isReversible) ? SQCX_NO_QUANTIZATION
0858:                        : ((isDerived) ? SQCX_SCALAR_DERIVED
0859:                                : SQCX_SCALAR_EXPOUNDED);
0860:
0861:                // QCD marker
0862:                hbuf.writeShort(QCD);
0863:
0864:                // Compute the number of steps to send
0865:                switch (qstyle) {
0866:                case SQCX_SCALAR_DERIVED:
0867:                    nqcd = 1; // Just the LL value
0868:                    break;
0869:                case SQCX_NO_QUANTIZATION:
0870:                case SQCX_SCALAR_EXPOUNDED:
0871:                    // One value per subband
0872:                    nqcd = 0;
0873:
0874:                    sb = sbRoot;
0875:
0876:                    // Get the subband at first resolution level
0877:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
0878:
0879:                    // Count total number of subbands
0880:                    for (int j = 0; j <= mrl; j++) {
0881:                        csb = sb;
0882:                        while (csb != null) {
0883:                            nqcd++;
0884:                            csb = (SubbandAn) csb.nextSubband();
0885:                        }
0886:                        // Go up one resolution level
0887:                        sb = (SubbandAn) sb.getNextResLevel();
0888:                    }
0889:                    break;
0890:                default:
0891:                    throw new Error("Internal JJ2000 error");
0892:                }
0893:
0894:                // Lqcd (marker segment length (in bytes))
0895:                // Lqcd(2 bytes)+Sqcd(1)+ SPqcd (2*Nqcd)
0896:                int markSegLen = 3 + ((isReversible) ? nqcd : 2 * nqcd);
0897:
0898:                // Rounded to the nearest even value greater or equals
0899:                hbuf.writeShort(markSegLen);
0900:
0901:                // Sqcd
0902:                hbuf.write(qstyle + (gb << SQCX_GB_SHIFT));
0903:
0904:                // SPqcd
0905:                switch (qstyle) {
0906:                case SQCX_NO_QUANTIZATION:
0907:                    sb = sbRoot;
0908:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
0909:
0910:                    // Output one exponent per subband
0911:                    for (int j = 0; j <= mrl; j++) {
0912:                        csb = sb;
0913:                        while (csb != null) {
0914:                            int tmp = (defimgn + csb.anGainExp);
0915:                            hbuf.write(tmp << SQCX_EXP_SHIFT);
0916:
0917:                            csb = (SubbandAn) csb.nextSubband();
0918:                            // Go up one resolution level
0919:                        }
0920:                        sb = (SubbandAn) sb.getNextResLevel();
0921:                    }
0922:                    break;
0923:                case SQCX_SCALAR_DERIVED:
0924:                    sb = sbRoot;
0925:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
0926:
0927:                    // Calculate subband step (normalized to unit
0928:                    // dynamic range)
0929:                    step = baseStep / (1 << sb.level);
0930:
0931:                    // Write exponent-mantissa, 16 bits
0932:                    hbuf.writeShort(StdQuantizer.convertToExpMantissa(step));
0933:                    break;
0934:                case SQCX_SCALAR_EXPOUNDED:
0935:                    sb = sbRoot;
0936:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
0937:
0938:                    // Output one step per subband
0939:                    for (int j = 0; j <= mrl; j++) {
0940:                        csb = sb;
0941:                        while (csb != null) {
0942:                            // Calculate subband step (normalized to unit
0943:                            // dynamic range)
0944:                            step = baseStep
0945:                                    / (csb.l2Norm * (1 << csb.anGainExp));
0946:
0947:                            // Write exponent-mantissa, 16 bits
0948:                            hbuf.writeShort(StdQuantizer
0949:                                    .convertToExpMantissa(step));
0950:
0951:                            csb = (SubbandAn) csb.nextSubband();
0952:                        }
0953:                        // Go up one resolution level
0954:                        sb = (SubbandAn) sb.getNextResLevel();
0955:                    }
0956:                    break;
0957:                default:
0958:                    throw new Error("Internal JJ2000 error");
0959:                }
0960:            }
0961:
0962:            /**
0963:             * Writes QCC marker segment in main header. It is a functional
0964:             * marker segment countaining the quantization used for
0965:             * compressing the specified component in an image. The values
0966:             * override for the specified component what was defined by a QCC
0967:             * marker in either the main or the tile header.
0968:             *
0969:             * @param compIdx Index of the component which needs QCC marker
0970:             * segment.
0971:             * */
0972:            protected void writeMainQCC(int compIdx) throws IOException {
0973:
0974:                int mrl;
0975:                int qstyle;
0976:                int tIdx = 0;
0977:                float step;
0978:
0979:                SubbandAn sb, sb2;
0980:                SubbandAn sbRoot;
0981:
0982:                int imgnr = dwt.getNomRangeBits(compIdx);
0983:                String qType = (String) wp.getQuantizationType().getCompDef(
0984:                        compIdx);
0985:                float baseStep = ((Float) wp.getQuantizationStep().getCompDef(
0986:                        compIdx)).floatValue();
0987:                int gb = ((Integer) wp.getGuardBits().getCompDef(compIdx))
0988:                        .intValue();
0989:
0990:                boolean isReversible = qType.equals("reversible");
0991:                boolean isDerived = qType.equals("derived");
0992:
0993:                mrl = ((Integer) wp.getDecompositionLevel().getCompDef(compIdx))
0994:                        .intValue();
0995:
0996:                int nt = dwt.getNumTiles();
0997:                int nc = dwt.getNumComps();
0998:                int tmpI;
0999:                String tmpStr;
1000:                boolean notFound = true;
1001:                for (int t = 0; t < nt && notFound; t++) {
1002:                    for (int c = 0; c < nc && notFound; c++) {
1003:                        tmpI = ((Integer) wp.getDecompositionLevel()
1004:                                .getTileCompVal(t, c)).intValue();
1005:                        tmpStr = (String) wp.getQuantizationType()
1006:                                .getTileCompVal(t, c);
1007:                        if (tmpI == mrl && tmpStr.equals(qType)) {
1008:                            tIdx = t;
1009:                            notFound = false;
1010:                        }
1011:                    }
1012:                }
1013:                if (notFound) {
1014:                    throw new Error(
1015:                            "Default representative for quantization type "
1016:                                    + " and number of decomposition levels not found "
1017:                                    + " in main QCC (c=" + compIdx
1018:                                    + ") marker segment. "
1019:                                    + "You have found a JJ2000 bug.");
1020:                }
1021:                sbRoot = dwt.getAnSubbandTree(tIdx, compIdx);
1022:
1023:                int nqcc; // Number of quantization step-size to transmit
1024:
1025:                // Get the quantization style
1026:                if (isReversible) {
1027:                    qstyle = SQCX_NO_QUANTIZATION;
1028:                } else if (isDerived) {
1029:                    qstyle = SQCX_SCALAR_DERIVED;
1030:                } else {
1031:                    qstyle = SQCX_SCALAR_EXPOUNDED;
1032:                }
1033:
1034:                // QCC marker
1035:                hbuf.writeShort(QCC);
1036:
1037:                // Compute the number of steps to send
1038:                switch (qstyle) {
1039:                case SQCX_SCALAR_DERIVED:
1040:                    nqcc = 1; // Just the LL value
1041:                    break;
1042:                case SQCX_NO_QUANTIZATION:
1043:                case SQCX_SCALAR_EXPOUNDED:
1044:                    // One value per subband
1045:                    nqcc = 0;
1046:
1047:                    sb = sbRoot;
1048:                    mrl = sb.resLvl;
1049:
1050:                    // Get the subband at first resolution level
1051:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1052:
1053:                    // Find root element for LL subband
1054:                    while (sb.resLvl != 0) {
1055:                        sb = sb.subb_LL;
1056:                    }
1057:
1058:                    // Count total number of subbands
1059:                    for (int j = 0; j <= mrl; j++) {
1060:                        sb2 = sb;
1061:                        while (sb2 != null) {
1062:                            nqcc++;
1063:                            sb2 = (SubbandAn) sb2.nextSubband();
1064:                        }
1065:                        // Go up one resolution level
1066:                        sb = (SubbandAn) sb.getNextResLevel();
1067:                    }
1068:                    break;
1069:                default:
1070:                    throw new Error("Internal JJ2000 error");
1071:                }
1072:
1073:                // Lqcc (marker segment length (in bytes))
1074:                // Lqcc(2 bytes)+Cqcc(1 or 2)+Sqcc(1)+ SPqcc (2*Nqcc)
1075:                int markSegLen = 3 + ((nComp < 257) ? 1 : 2)
1076:                        + ((isReversible) ? nqcc : 2 * nqcc);
1077:                hbuf.writeShort(markSegLen);
1078:
1079:                // Cqcc
1080:                if (nComp < 257) {
1081:                    hbuf.write(compIdx);
1082:                } else {
1083:                    hbuf.writeShort(compIdx);
1084:                }
1085:
1086:                // Sqcc (quantization style)
1087:                hbuf.write(qstyle + (gb << SQCX_GB_SHIFT));
1088:
1089:                // SPqcc
1090:                switch (qstyle) {
1091:                case SQCX_NO_QUANTIZATION:
1092:                    // Get resolution level 0 subband
1093:                    sb = sbRoot;
1094:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1095:
1096:                    // Output one exponent per subband
1097:                    for (int j = 0; j <= mrl; j++) {
1098:                        sb2 = sb;
1099:                        while (sb2 != null) {
1100:                            int tmp = (imgnr + sb2.anGainExp);
1101:                            hbuf.write(tmp << SQCX_EXP_SHIFT);
1102:
1103:                            sb2 = (SubbandAn) sb2.nextSubband();
1104:                        }
1105:                        // Go up one resolution level
1106:                        sb = (SubbandAn) sb.getNextResLevel();
1107:                    }
1108:                    break;
1109:                case SQCX_SCALAR_DERIVED:
1110:                    // Get resolution level 0 subband
1111:                    sb = sbRoot;
1112:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1113:
1114:                    // Calculate subband step (normalized to unit
1115:                    // dynamic range)
1116:                    step = baseStep / (1 << sb.level);
1117:
1118:                    // Write exponent-mantissa, 16 bits
1119:                    hbuf.writeShort(StdQuantizer.convertToExpMantissa(step));
1120:                    break;
1121:                case SQCX_SCALAR_EXPOUNDED:
1122:                    // Get resolution level 0 subband
1123:                    sb = sbRoot;
1124:                    mrl = sb.resLvl;
1125:
1126:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1127:
1128:                    for (int j = 0; j <= mrl; j++) {
1129:                        sb2 = sb;
1130:                        while (sb2 != null) {
1131:                            // Calculate subband step (normalized to unit
1132:                            // dynamic range)
1133:                            step = baseStep
1134:                                    / (sb2.l2Norm * (1 << sb2.anGainExp));
1135:
1136:                            // Write exponent-mantissa, 16 bits
1137:                            hbuf.writeShort(StdQuantizer
1138:                                    .convertToExpMantissa(step));
1139:                            sb2 = (SubbandAn) sb2.nextSubband();
1140:                        }
1141:                        // Go up one resolution level
1142:                        sb = (SubbandAn) sb.getNextResLevel();
1143:                    }
1144:                    break;
1145:                default:
1146:                    throw new Error("Internal JJ2000 error");
1147:                }
1148:            }
1149:
1150:            /**
1151:             * Writes QCD marker segment in tile header. QCD is a functional
1152:             * marker segment countaining the quantization default used for
1153:             * compressing all the components in an image. The values can be
1154:             * overriden for an individual component by a QCC marker in either
1155:             * the main or the tile header.
1156:             *
1157:             * @param tIdx Tile index
1158:             * */
1159:            protected void writeTileQCD(int tIdx) throws IOException {
1160:                int mrl;
1161:                int qstyle;
1162:
1163:                float step;
1164:                SubbandAn sb, csb, sbRoot;
1165:
1166:                String qType = (String) wp.getQuantizationType().getTileDef(
1167:                        tIdx);
1168:                float baseStep = ((Float) wp.getQuantizationStep().getTileDef(
1169:                        tIdx)).floatValue();
1170:                mrl = ((Integer) wp.getDecompositionLevel().getTileDef(tIdx))
1171:                        .intValue();
1172:
1173:                int nc = dwt.getNumComps();
1174:                int tmpI;
1175:                String tmpStr;
1176:                boolean notFound = true;
1177:                int compIdx = 0;
1178:                for (int c = 0; c < nc && notFound; c++) {
1179:                    tmpI = ((Integer) wp.getDecompositionLevel()
1180:                            .getTileCompVal(tIdx, c)).intValue();
1181:                    tmpStr = (String) wp.getQuantizationStep().getTileCompVal(
1182:                            tIdx, c);
1183:                    if (tmpI == mrl && tmpStr.equals(qType)) {
1184:                        compIdx = c;
1185:                        notFound = false;
1186:                    }
1187:                }
1188:                if (notFound) {
1189:                    throw new Error(
1190:                            "Default representative for quantization type "
1191:                                    + " and number of decomposition levels not found "
1192:                                    + " in tile QCD (t=" + tIdx
1193:                                    + ") marker segment. "
1194:                                    + "You have found a JJ2000 bug.");
1195:                }
1196:
1197:                sbRoot = dwt.getAnSubbandTree(tIdx, compIdx);
1198:                deftilenr = dwt.getNomRangeBits(compIdx);
1199:                int gb = ((Integer) wp.getGuardBits().getTileDef(tIdx))
1200:                        .intValue();
1201:
1202:                boolean isDerived = qType.equals("derived");
1203:                boolean isReversible = qType.equals("reversible");
1204:
1205:                int nqcd; // Number of quantization step-size to transmit
1206:
1207:                // Get the quantization style
1208:                qstyle = (isReversible) ? SQCX_NO_QUANTIZATION
1209:                        : ((isDerived) ? SQCX_SCALAR_DERIVED
1210:                                : SQCX_SCALAR_EXPOUNDED);
1211:
1212:                // QCD marker
1213:                hbuf.writeShort(QCD);
1214:
1215:                // Compute the number of steps to send
1216:                switch (qstyle) {
1217:                case SQCX_SCALAR_DERIVED:
1218:                    nqcd = 1; // Just the LL value
1219:                    break;
1220:                case SQCX_NO_QUANTIZATION:
1221:                case SQCX_SCALAR_EXPOUNDED:
1222:                    // One value per subband
1223:                    nqcd = 0;
1224:
1225:                    sb = sbRoot;
1226:
1227:                    // Get the subband at first resolution level
1228:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1229:
1230:                    // Count total number of subbands
1231:                    for (int j = 0; j <= mrl; j++) {
1232:                        csb = sb;
1233:                        while (csb != null) {
1234:                            nqcd++;
1235:                            csb = (SubbandAn) csb.nextSubband();
1236:                        }
1237:                        // Go up one resolution level
1238:                        sb = (SubbandAn) sb.getNextResLevel();
1239:                    }
1240:                    break;
1241:                default:
1242:                    throw new Error("Internal JJ2000 error");
1243:                }
1244:
1245:                // Lqcd (marker segment length (in bytes))
1246:                // Lqcd(2 bytes)+Sqcd(1)+ SPqcd (2*Nqcd)
1247:                int markSegLen = 3 + ((isReversible) ? nqcd : 2 * nqcd);
1248:
1249:                // Rounded to the nearest even value greater or equals
1250:                hbuf.writeShort(markSegLen);
1251:
1252:                // Sqcd
1253:                hbuf.write(qstyle + (gb << SQCX_GB_SHIFT));
1254:
1255:                // SPqcd
1256:                switch (qstyle) {
1257:                case SQCX_NO_QUANTIZATION:
1258:                    sb = sbRoot;
1259:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1260:
1261:                    // Output one exponent per subband
1262:                    for (int j = 0; j <= mrl; j++) {
1263:                        csb = sb;
1264:                        while (csb != null) {
1265:                            int tmp = (deftilenr + csb.anGainExp);
1266:                            hbuf.write(tmp << SQCX_EXP_SHIFT);
1267:
1268:                            csb = (SubbandAn) csb.nextSubband();
1269:                            // Go up one resolution level
1270:                        }
1271:                        sb = (SubbandAn) sb.getNextResLevel();
1272:                    }
1273:                    break;
1274:                case SQCX_SCALAR_DERIVED:
1275:                    sb = sbRoot;
1276:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1277:
1278:                    // Calculate subband step (normalized to unit
1279:                    // dynamic range)
1280:                    step = baseStep / (1 << sb.level);
1281:
1282:                    // Write exponent-mantissa, 16 bits
1283:                    hbuf.writeShort(StdQuantizer.convertToExpMantissa(step));
1284:                    break;
1285:                case SQCX_SCALAR_EXPOUNDED:
1286:                    sb = sbRoot;
1287:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1288:
1289:                    // Output one step per subband
1290:                    for (int j = 0; j <= mrl; j++) {
1291:                        csb = sb;
1292:                        while (csb != null) {
1293:                            // Calculate subband step (normalized to unit
1294:                            // dynamic range)
1295:                            step = baseStep
1296:                                    / (csb.l2Norm * (1 << csb.anGainExp));
1297:
1298:                            // Write exponent-mantissa, 16 bits
1299:                            hbuf.writeShort(StdQuantizer
1300:                                    .convertToExpMantissa(step));
1301:
1302:                            csb = (SubbandAn) csb.nextSubband();
1303:                        }
1304:                        // Go up one resolution level
1305:                        sb = (SubbandAn) sb.getNextResLevel();
1306:                    }
1307:                    break;
1308:                default:
1309:                    throw new Error("Internal JJ2000 error");
1310:                }
1311:            }
1312:
1313:            /**
1314:             * Writes QCC marker segment in tile header. It is a functional
1315:             * marker segment countaining the quantization used for
1316:             * compressing the specified component in an image. The values
1317:             * override for the specified component what was defined by a QCC
1318:             * marker in either the main or the tile header.
1319:             *
1320:             * @param t Tile index
1321:             *
1322:             * @param compIdx Index of the component which needs QCC marker
1323:             * segment.
1324:             * */
1325:            protected void writeTileQCC(int t, int compIdx) throws IOException {
1326:
1327:                int mrl;
1328:                int qstyle;
1329:                float step;
1330:
1331:                SubbandAn sb, sb2;
1332:                int nqcc; // Number of quantization step-size to transmit
1333:
1334:                SubbandAn sbRoot = dwt.getAnSubbandTree(t, compIdx);
1335:                int imgnr = dwt.getNomRangeBits(compIdx);
1336:                String qType = (String) wp.getQuantizationType()
1337:                        .getTileCompVal(t, compIdx);
1338:                float baseStep = ((Float) wp.getQuantizationStep()
1339:                        .getTileCompVal(t, compIdx)).floatValue();
1340:                int gb = ((Integer) wp.getGuardBits()
1341:                        .getTileCompVal(t, compIdx)).intValue();
1342:
1343:                boolean isReversible = qType.equals("reversible");
1344:                boolean isDerived = qType.equals("derived");
1345:
1346:                mrl = ((Integer) wp.getDecompositionLevel().getTileCompVal(t,
1347:                        compIdx)).intValue();
1348:
1349:                // Get the quantization style
1350:                if (isReversible) {
1351:                    qstyle = SQCX_NO_QUANTIZATION;
1352:                } else if (isDerived) {
1353:                    qstyle = SQCX_SCALAR_DERIVED;
1354:                } else {
1355:                    qstyle = SQCX_SCALAR_EXPOUNDED;
1356:                }
1357:
1358:                // QCC marker
1359:                hbuf.writeShort(QCC);
1360:
1361:                // Compute the number of steps to send
1362:                switch (qstyle) {
1363:                case SQCX_SCALAR_DERIVED:
1364:                    nqcc = 1; // Just the LL value
1365:                    break;
1366:                case SQCX_NO_QUANTIZATION:
1367:                case SQCX_SCALAR_EXPOUNDED:
1368:                    // One value per subband
1369:                    nqcc = 0;
1370:
1371:                    sb = sbRoot;
1372:                    mrl = sb.resLvl;
1373:
1374:                    // Get the subband at first resolution level
1375:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1376:
1377:                    // Find root element for LL subband
1378:                    while (sb.resLvl != 0) {
1379:                        sb = sb.subb_LL;
1380:                    }
1381:
1382:                    // Count total number of subbands
1383:                    for (int j = 0; j <= mrl; j++) {
1384:                        sb2 = sb;
1385:                        while (sb2 != null) {
1386:                            nqcc++;
1387:                            sb2 = (SubbandAn) sb2.nextSubband();
1388:                        }
1389:                        // Go up one resolution level
1390:                        sb = (SubbandAn) sb.getNextResLevel();
1391:                    }
1392:                    break;
1393:                default:
1394:                    throw new Error("Internal JJ2000 error");
1395:                }
1396:
1397:                // Lqcc (marker segment length (in bytes))
1398:                // Lqcc(2 bytes)+Cqcc(1 or 2)+Sqcc(1)+ SPqcc (2*Nqcc)
1399:                int markSegLen = 3 + ((nComp < 257) ? 1 : 2)
1400:                        + ((isReversible) ? nqcc : 2 * nqcc);
1401:                hbuf.writeShort(markSegLen);
1402:
1403:                // Cqcc
1404:                if (nComp < 257) {
1405:                    hbuf.write(compIdx);
1406:                } else {
1407:                    hbuf.writeShort(compIdx);
1408:                }
1409:
1410:                // Sqcc (quantization style)
1411:                hbuf.write(qstyle + (gb << SQCX_GB_SHIFT));
1412:
1413:                // SPqcc
1414:                switch (qstyle) {
1415:                case SQCX_NO_QUANTIZATION:
1416:                    // Get resolution level 0 subband
1417:                    sb = sbRoot;
1418:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1419:
1420:                    // Output one exponent per subband
1421:                    for (int j = 0; j <= mrl; j++) {
1422:                        sb2 = sb;
1423:                        while (sb2 != null) {
1424:                            int tmp = (imgnr + sb2.anGainExp);
1425:                            hbuf.write(tmp << SQCX_EXP_SHIFT);
1426:
1427:                            sb2 = (SubbandAn) sb2.nextSubband();
1428:                        }
1429:                        // Go up one resolution level
1430:                        sb = (SubbandAn) sb.getNextResLevel();
1431:                    }
1432:                    break;
1433:                case SQCX_SCALAR_DERIVED:
1434:                    // Get resolution level 0 subband
1435:                    sb = sbRoot;
1436:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1437:
1438:                    // Calculate subband step (normalized to unit
1439:                    // dynamic range)
1440:                    step = baseStep / (1 << sb.level);
1441:
1442:                    // Write exponent-mantissa, 16 bits
1443:                    hbuf.writeShort(StdQuantizer.convertToExpMantissa(step));
1444:                    break;
1445:                case SQCX_SCALAR_EXPOUNDED:
1446:                    // Get resolution level 0 subband
1447:                    sb = sbRoot;
1448:                    mrl = sb.resLvl;
1449:
1450:                    sb = (SubbandAn) sb.getSubbandByIdx(0, 0);
1451:
1452:                    for (int j = 0; j <= mrl; j++) {
1453:                        sb2 = sb;
1454:                        while (sb2 != null) {
1455:                            // Calculate subband step (normalized to unit
1456:                            // dynamic range)
1457:                            step = baseStep
1458:                                    / (sb2.l2Norm * (1 << sb2.anGainExp));
1459:
1460:                            // Write exponent-mantissa, 16 bits
1461:                            hbuf.writeShort(StdQuantizer
1462:                                    .convertToExpMantissa(step));
1463:                            sb2 = (SubbandAn) sb2.nextSubband();
1464:                        }
1465:                        // Go up one resolution level
1466:                        sb = (SubbandAn) sb.getNextResLevel();
1467:                    }
1468:                    break;
1469:                default:
1470:                    throw new Error("Internal JJ2000 error");
1471:                }
1472:            }
1473:
1474:            /**
1475:             * Writes POC marker segment. POC is a functional marker segment
1476:             * containing the bounds and progression order for any progression order
1477:             * other than default in the codestream.
1478:             *
1479:             * @param mh Flag indicating whether the main header is to be written
1480:             *
1481:             * @param tileIdx Tile index
1482:             * */
1483:            protected void writePOC(boolean mh, int tileIdx) throws IOException {
1484:                int markSegLen = 0; // Segment marker length
1485:                int lenCompField; // Holds the size of any component field as
1486:                // this size depends on the number of
1487:                //components
1488:                Progression[] prog = null; // Holds the progression(s)
1489:                int npoc; // Number of progression order changes
1490:
1491:                // Get the progression order changes, their number and checks
1492:                // if it is ok
1493:                if (mh) {
1494:                    prog = (Progression[]) (wp.getProgressionType()
1495:                            .getDefault());
1496:                } else {
1497:                    prog = (Progression[]) (wp.getProgressionType()
1498:                            .getTileDef(tileIdx));
1499:                }
1500:
1501:                // Calculate the length of a component field (depends on the number of
1502:                // components)
1503:                lenCompField = (nComp < 257 ? 1 : 2);
1504:
1505:                // POC marker
1506:                hbuf.writeShort(POC);
1507:
1508:                // Lpoc (marker segment length (in bytes))
1509:                // Basic: Lpoc(2 bytes) + npoc * [ RSpoc(1) + CSpoc(1 or 2) + LYEpoc(2)
1510:                // + REpoc(1) + CEpoc(1 or 2) + Ppoc(1) ]
1511:                npoc = prog.length;
1512:                markSegLen = 2 + npoc
1513:                        * (1 + lenCompField + 2 + 1 + lenCompField + 1);
1514:                hbuf.writeShort(markSegLen);
1515:
1516:                // Write each progression order change
1517:                for (int i = 0; i < npoc; i++) {
1518:                    // RSpoc(i)
1519:                    hbuf.write(prog[i].rs);
1520:                    // CSpoc(i)
1521:                    if (lenCompField == 2) {
1522:                        hbuf.writeShort(prog[i].cs);
1523:                    } else {
1524:                        hbuf.write(prog[i].cs);
1525:                    }
1526:                    // LYEpoc(i)
1527:                    hbuf.writeShort(prog[i].lye);
1528:                    // REpoc(i)
1529:                    hbuf.write(prog[i].re);
1530:                    // CEpoc(i)
1531:                    if (lenCompField == 2) {
1532:                        hbuf.writeShort(prog[i].ce);
1533:                    } else {
1534:                        hbuf.write(prog[i].ce);
1535:                    }
1536:                    // Ppoc(i)
1537:                    hbuf.write(prog[i].type);
1538:                }
1539:            }
1540:
1541:            /**
1542:             * Write main header. JJ2000 main header corresponds to the following
1543:             * sequence of marker
1544:             * segments:<ol><li>SOC</li><li>SIZ</li><li>COD</li><li>COC (if
1545:             * needed)</li><li>QCD</li><li>QCC (if needed)</li><li>POC (if
1546:             * needed)</li></ol>
1547:             * */
1548:            public void encodeMainHeader() throws IOException {
1549:                int i;
1550:
1551:                // +---------------------------------+
1552:                // |    SOC marker segment           |
1553:                // +---------------------------------+
1554:                writeSOC();
1555:
1556:                // +---------------------------------+
1557:                // |    Image and tile SIZe (SIZ)    |
1558:                // +---------------------------------+
1559:                writeSIZ();
1560:
1561:                // +-------------------------------+
1562:                // |   COding style Default (COD)  |
1563:                // +-------------------------------+
1564:                boolean isEresUsed = ((String) wp.getTerminateOnByte()
1565:                        .getDefault()).equals("predict");
1566:                writeCOD(true, 0);
1567:
1568:                // +---------------------------------+
1569:                // |   COding style Component (COC)  |
1570:                // +---------------------------------+
1571:                for (i = 0; i < nComp; i++) {
1572:                    boolean isEresUsedinComp = ((String) wp
1573:                            .getTerminateOnByte().getCompDef(i))
1574:                            .equals("predict");
1575:                    if (wp.getFilters().isCompSpecified(i)
1576:                            || wp.getDecompositionLevel().isCompSpecified(i)
1577:                            || wp.getBypass().isCompSpecified(i)
1578:                            || wp.getResetMQ().isCompSpecified(i)
1579:                            || wp.getMethodForMQTermination()
1580:                                    .isCompSpecified(i)
1581:                            || wp.getCodeSegSymbol().isCompSpecified(i)
1582:                            || wp.getCausalCXInfo().isCompSpecified(i)
1583:                            || wp.getPrecinctPartition().isCompSpecified(i)
1584:                            || wp.getCodeBlockSize().isCompSpecified(i)
1585:                            || (isEresUsed != isEresUsedinComp))
1586:                        // Some component non-default stuff => need COC
1587:                        writeCOC(true, 0, i);
1588:                }
1589:
1590:                // +-------------------------------+
1591:                // |   Quantization Default (QCD)  |
1592:                // +-------------------------------+
1593:                writeMainQCD();
1594:
1595:                // +-------------------------------+
1596:                // | Quantization Component (QCC)  |
1597:                // +-------------------------------+
1598:                // Write needed QCC markers
1599:                for (i = 0; i < nComp; i++) {
1600:                    if (dwt.getNomRangeBits(i) != defimgn
1601:                            || wp.getQuantizationType().isCompSpecified(i)
1602:                            || wp.getQuantizationStep().isCompSpecified(i)
1603:                            || wp.getDecompositionLevel().isCompSpecified(i)
1604:                            || wp.getGuardBits().isCompSpecified(i)) {
1605:                        writeMainQCC(i);
1606:                    }
1607:                }
1608:
1609:                // +--------------------------+
1610:                // |    POC maker segment     |
1611:                // +--------------------------+
1612:                Progression[] prog = (Progression[]) (wp.getProgressionType()
1613:                        .getDefault());
1614:                if (prog.length > 1)
1615:                    writePOC(true, 0);
1616:
1617:                // +--------------------------+
1618:                // |      Comment (COM)       |
1619:                // +--------------------------+
1620:                writeCOM();
1621:            }
1622:
1623:            /**
1624:             * Write a COM marker segment adding some comments to the codestream.
1625:             *
1626:             * <p> This marker is currently written in main header and indicates the
1627:             * JJ2000 encoder's version that has created the codestream.
1628:             * */
1629:            private void writeCOM() throws IOException {
1630:                // JJ2000 COM marker segment
1631:                if (enJJ2KMarkSeg) {
1632:                    String str = "Created by: JJ2000 version "
1633:                            + JJ2KInfo.version;
1634:                    int markSegLen; // the marker segment length
1635:
1636:                    // COM marker
1637:                    hbuf.writeShort(COM);
1638:
1639:                    // Calculate length: Lcom(2) + Rcom (2) + string's length;
1640:                    markSegLen = 2 + 2 + str.length();
1641:                    hbuf.writeShort(markSegLen);
1642:
1643:                    // Rcom 
1644:                    hbuf.writeShort(1); // General use (IS 8859-15:1999(Latin) values)
1645:
1646:                    byte[] chars = str.getBytes();
1647:                    for (int i = 0; i < chars.length; i++) {
1648:                        hbuf.writeByte(chars[i]);
1649:                    }
1650:                }
1651:                // other COM marker segments
1652:                if (otherCOMMarkSeg != null) {
1653:                    StringTokenizer stk = new StringTokenizer(otherCOMMarkSeg,
1654:                            "#");
1655:                    while (stk.hasMoreTokens()) {
1656:                        String str = stk.nextToken();
1657:                        int markSegLen; // the marker segment length
1658:
1659:                        // COM marker
1660:                        hbuf.writeShort(COM);
1661:
1662:                        // Calculate length: Lcom(2) + Rcom (2) + string's length;
1663:                        markSegLen = 2 + 2 + str.length();
1664:                        hbuf.writeShort(markSegLen);
1665:
1666:                        // Rcom 
1667:                        hbuf.writeShort(1); // General use (IS 8859-15:1999(Latin)
1668:                        // values)
1669:
1670:                        byte[] chars = str.getBytes();
1671:                        for (int i = 0; i < chars.length; i++) {
1672:                            hbuf.writeByte(chars[i]);
1673:                        }
1674:                    }
1675:                }
1676:            }
1677:
1678:            /**
1679:             * Writes the RGN marker segment in the tile header. It describes the
1680:             * scaling value in each tile component
1681:             *
1682:             * <P>May be used in tile or main header. If used in main header, it
1683:             * refers to a ROI of the whole image, regardless of tiling. When used in
1684:             * tile header, only the particular tile is affected.
1685:             *
1686:             * @param tIdx The tile index
1687:             *
1688:             * @exception IOException If an I/O error occurs while reading from the
1689:             * encoder header stream
1690:             * */
1691:            private void writeRGN(int tIdx) throws IOException {
1692:                int i;
1693:                int markSegLen; // the marker length
1694:
1695:                // Write one RGN marker per component
1696:                for (i = 0; i < nComp; i++) {
1697:                    // RGN marker
1698:                    hbuf.writeShort(RGN);
1699:
1700:                    // Calculate length (Lrgn)
1701:                    // Basic: Lrgn (2) + Srgn (1) + SPrgn + one byte
1702:                    // or two for component number
1703:                    markSegLen = 4 + ((nComp < 257) ? 1 : 2);
1704:                    hbuf.writeShort(markSegLen);
1705:
1706:                    // Write component (Crgn)
1707:                    if (nComp < 257)
1708:                        hbuf.writeByte(i);
1709:                    else
1710:                        hbuf.writeShort(i);
1711:
1712:                    // Write type of ROI (Srgn)
1713:                    hbuf.writeByte(SRGN_IMPLICIT);
1714:
1715:                    // Write ROI info (SPrgn)
1716:                    hbuf.writeByte(((Integer) (wp.getROIs().getTileCompVal(
1717:                            tIdx, i))).intValue());
1718:                }
1719:            }
1720:
1721:            /**
1722:             * Writes tile-part header. JJ2000 tile-part header corresponds to the
1723:             * following sequence of marker segments:<ol> <li>SOT</li> <li>COD (if
1724:             * needed)</li> <li>COC (if needed)</li> <li>QCD (if needed)</li> <li>QCC
1725:             * (if needed)</li> <li>RGN (if needed)</li> <li>POC (if needed)</li>
1726:             * <li>SOD</li> </ol>
1727:             *
1728:             * @param length The length of the current tile-part.
1729:             *
1730:             * @param tileIdx Index of the tile to write
1731:             * */
1732:            public void encodeTilePartHeader(int tileLength, int tileIdx)
1733:                    throws IOException {
1734:
1735:                int tmp;
1736:                Point numTiles = ralloc.getNumTiles(null);
1737:                ralloc.setTile(tileIdx % numTiles.x, tileIdx / numTiles.x);
1738:
1739:                // +--------------------------+
1740:                // |    SOT maker segment     |
1741:                // +--------------------------+
1742:                // SOT marker
1743:                hbuf.writeByte(SOT >> 8);
1744:                hbuf.writeByte(SOT);
1745:
1746:                // Lsot (10 bytes)
1747:                hbuf.writeByte(0);
1748:                hbuf.writeByte(10);
1749:
1750:                // Isot
1751:                if (tileIdx > 65534) {
1752:                    throw new IllegalArgumentException(
1753:                            "Trying to write a tile-part "
1754:                                    + "header whose tile index is too"
1755:                                    + " high");
1756:                }
1757:                hbuf.writeByte(tileIdx >> 8);
1758:                hbuf.writeByte(tileIdx);
1759:
1760:                // Psot
1761:                tmp = tileLength;
1762:                hbuf.writeByte(tmp >> 24);
1763:                hbuf.writeByte(tmp >> 16);
1764:                hbuf.writeByte(tmp >> 8);
1765:                hbuf.writeByte(tmp);
1766:
1767:                // TPsot
1768:                hbuf.writeByte(0); // Only one tile-part currently supported !
1769:
1770:                // TNsot
1771:                hbuf.writeByte(1); // Only one tile-part currently supported !
1772:
1773:                // +--------------------------+
1774:                // |    COD maker segment     |
1775:                // +--------------------------+
1776:                boolean isEresUsed = ((String) wp.getMethodForMQTermination()
1777:                        .getDefault()).equals("predict");
1778:                boolean isEresUsedInTile = ((String) wp
1779:                        .getMethodForMQTermination().getTileDef(tileIdx))
1780:                        .equals("predict");
1781:                boolean tileCODwritten = false;
1782:                if (wp.getFilters().isTileSpecified(tileIdx)
1783:                        || wp.getComponentTransformation().isTileSpecified(
1784:                                tileIdx)
1785:                        || wp.getDecompositionLevel().isTileSpecified(tileIdx)
1786:                        || wp.getBypass().isTileSpecified(tileIdx)
1787:                        || wp.getResetMQ().isTileSpecified(tileIdx)
1788:                        || wp.getTerminateOnByte().isTileSpecified(tileIdx)
1789:                        || wp.getCausalCXInfo().isTileSpecified(tileIdx)
1790:                        || wp.getPrecinctPartition().isTileSpecified(tileIdx)
1791:                        || wp.getSOP().isTileSpecified(tileIdx)
1792:                        || wp.getCodeSegSymbol().isTileSpecified(tileIdx)
1793:                        || wp.getProgressionType().isTileSpecified(tileIdx)
1794:                        || wp.getEPH().isTileSpecified(tileIdx)
1795:                        || wp.getCodeBlockSize().isTileSpecified(tileIdx)
1796:                        || (isEresUsed != isEresUsedInTile)) {
1797:                    writeCOD(false, tileIdx);
1798:                    tileCODwritten = true;
1799:                }
1800:
1801:                // +--------------------------+
1802:                // |    COC maker segment     |
1803:                // +--------------------------+
1804:                for (int c = 0; c < nComp; c++) {
1805:                    boolean isEresUsedInTileComp = ((String) wp
1806:                            .getMethodForMQTermination().getTileCompVal(
1807:                                    tileIdx, c)).equals("predict");
1808:
1809:                    if (wp.getFilters().isTileCompSpecified(tileIdx, c)
1810:                            || wp.getDecompositionLevel().isTileCompSpecified(
1811:                                    tileIdx, c)
1812:                            || wp.getBypass().isTileCompSpecified(tileIdx, c)
1813:                            || wp.getResetMQ().isTileCompSpecified(tileIdx, c)
1814:                            || wp.getTerminateOnByte().isTileCompSpecified(
1815:                                    tileIdx, c)
1816:                            || wp.getCausalCXInfo().isTileCompSpecified(
1817:                                    tileIdx, c)
1818:                            || wp.getPrecinctPartition().isTileCompSpecified(
1819:                                    tileIdx, c)
1820:                            || wp.getCodeSegSymbol().isTileCompSpecified(
1821:                                    tileIdx, c)
1822:                            || wp.getCodeBlockSize().isTileCompSpecified(
1823:                                    tileIdx, c)
1824:                            || (isEresUsedInTileComp != isEresUsed)) {
1825:                        writeCOC(false, tileIdx, c);
1826:                    } else if (tileCODwritten) {
1827:                        if (wp.getFilters().isCompSpecified(c)
1828:                                || wp.getDecompositionLevel()
1829:                                        .isCompSpecified(c)
1830:                                || wp.getBypass().isCompSpecified(c)
1831:                                || wp.getResetMQ().isCompSpecified(c)
1832:                                || wp.getTerminateOnByte().isCompSpecified(c)
1833:                                || wp.getCodeSegSymbol().isCompSpecified(c)
1834:                                || wp.getCausalCXInfo().isCompSpecified(c)
1835:                                || wp.getPrecinctPartition().isCompSpecified(c)
1836:                                || wp.getCodeBlockSize().isCompSpecified(c)
1837:                                || (wp.getMethodForMQTermination()
1838:                                        .isCompSpecified(c) && ((String) wp
1839:                                        .getMethodForMQTermination()
1840:                                        .getCompDef(c)).equals("predict"))) {
1841:                            writeCOC(false, tileIdx, c);
1842:                        }
1843:                    }
1844:                }
1845:
1846:                // +--------------------------+
1847:                // |    QCD maker segment     |
1848:                // +--------------------------+
1849:                boolean tileQCDwritten = false;
1850:                if (wp.getQuantizationType().isTileSpecified(tileIdx)
1851:                        || wp.getQuantizationStep().isTileSpecified(tileIdx)
1852:                        || wp.getDecompositionLevel().isTileSpecified(tileIdx)
1853:                        || wp.getGuardBits().isTileSpecified(tileIdx)) {
1854:                    writeTileQCD(tileIdx);
1855:                    tileQCDwritten = true;
1856:                } else {
1857:                    deftilenr = defimgn;
1858:                }
1859:
1860:                // +--------------------------+
1861:                // |    QCC maker segment     |
1862:                // +--------------------------+
1863:                for (int c = 0; c < nComp; c++) {
1864:                    if (dwt.getNomRangeBits(c) != deftilenr
1865:                            || wp.getQuantizationType().isTileCompSpecified(
1866:                                    tileIdx, c)
1867:                            || wp.getQuantizationStep().isTileCompSpecified(
1868:                                    tileIdx, c)
1869:                            || wp.getDecompositionLevel().isTileCompSpecified(
1870:                                    tileIdx, c)
1871:                            || wp.getGuardBits()
1872:                                    .isTileCompSpecified(tileIdx, c)) {
1873:                        writeTileQCC(tileIdx, c);
1874:                    } else if (tileQCDwritten) {
1875:                        if (wp.getQuantizationType().isCompSpecified(c)
1876:                                || wp.getQuantizationStep().isCompSpecified(c)
1877:                                || wp.getDecompositionLevel()
1878:                                        .isCompSpecified(c)
1879:                                || wp.getGuardBits().isCompSpecified(c)) {
1880:                            writeTileQCC(tileIdx, c);
1881:                        }
1882:                    }
1883:                }
1884:
1885:                // +--------------------------+
1886:                // |    RGN maker segment     |
1887:                // +--------------------------+
1888:                if (roiSc.useRoi() && (!roiSc.getBlockAligned()))
1889:                    writeRGN(tileIdx);
1890:
1891:                // +--------------------------+
1892:                // |    POC maker segment     |
1893:                // +--------------------------+
1894:                Progression[] prog;
1895:                if (wp.getProgressionType().isTileSpecified(tileIdx)) {
1896:                    prog = (Progression[]) (wp.getProgressionType()
1897:                            .getTileDef(tileIdx));
1898:                    if (prog.length > 1)
1899:                        writePOC(false, tileIdx);
1900:                }
1901:
1902:                // +--------------------------+
1903:                // |         SOD maker        |
1904:                // +--------------------------+
1905:                hbuf.writeByte(SOD >> 8);
1906:                hbuf.writeByte(SOD);
1907:            }
1908:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.