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


0001:        /*
0002:         * $RCSfile: ForwWTFull.java,v $
0003:         * $Revision: 1.1 $
0004:         * $Date: 2005/02/11 05:02:31 $
0005:         * $State: Exp $
0006:         *
0007:         * Class:                   ForwWTFull
0008:         *
0009:         * Description:             This class implements the full page
0010:         *                          forward wavelet transform for both integer
0011:         *                          and floating point implementations.
0012:         *
0013:         *
0014:         *
0015:         * COPYRIGHT:
0016:         *
0017:         * This software module was originally developed by Raphaël Grosbois and
0018:         * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
0019:         * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
0020:         * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
0021:         * Centre France S.A) in the course of development of the JPEG2000
0022:         * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
0023:         * software module is an implementation of a part of the JPEG 2000
0024:         * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
0025:         * Systems AB and Canon Research Centre France S.A (collectively JJ2000
0026:         * Partners) agree not to assert against ISO/IEC and users of the JPEG
0027:         * 2000 Standard (Users) any of their rights under the copyright, not
0028:         * including other intellectual property rights, for this software module
0029:         * with respect to the usage by ISO/IEC and Users of this software module
0030:         * or modifications thereof for use in hardware or software products
0031:         * claiming conformance to the JPEG 2000 Standard. Those intending to use
0032:         * this software module in hardware or software products are advised that
0033:         * their use may infringe existing patents. The original developers of
0034:         * this software module, JJ2000 Partners and ISO/IEC assume no liability
0035:         * for use of this software module or modifications thereof. No license
0036:         * or right to this software module is granted for non JPEG 2000 Standard
0037:         * conforming products. JJ2000 Partners have full right to use this
0038:         * software module for his/her own purpose, assign or donate this
0039:         * software module to any third party and to inhibit third parties from
0040:         * using this software module for non JPEG 2000 Standard conforming
0041:         * products. This copyright notice must be included in all copies or
0042:         * derivative works of this software module.
0043:         *
0044:         * Copyright (c) 1999/2000 JJ2000 Partners.
0045:         * */
0046:        package jj2000.j2k.wavelet.analysis;
0047:
0048:        import java.awt.Point;
0049:
0050:        import jj2000.j2k.codestream.*;
0051:        import jj2000.j2k.entropy.*;
0052:        import jj2000.j2k.wavelet.*; //import jj2000.j2k.encoder.*;
0053:        import jj2000.j2k.image.*;
0054:        import jj2000.j2k.util.*;
0055:        import jj2000.j2k.*;
0056:
0057:        import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava;
0058:
0059:        /**
0060:         * This class implements the ForwardWT with the full-page approach to be used
0061:         * either with integer or floating-point filters
0062:         * */
0063:        public class ForwWTFull extends ForwardWT {
0064:
0065:            /** Boolean to know if one are currently dealing with int or float
0066:                data. */
0067:            private boolean intData;
0068:
0069:            /**
0070:             * The subband trees for each component, in each tile. The array is
0071:             * allocated by the constructor of this class. This array is updated by
0072:             * the getSubbandTree() method, an a as needed basis. The first index is
0073:             * the tile index (in lexicographical order) and the second index is the
0074:             * component index.
0075:             *
0076:             * <P>The subband tree for a component in the current tile is created on
0077:             * the first call to getSubbandTree() for that component, in the current
0078:             * tile. Before that the element in 'subbTrees' is null.
0079:             * */
0080:            private SubbandAn subbTrees[][];
0081:
0082:            /** The source of image data */
0083:            private BlkImgDataSrc src;
0084:
0085:            /** The horizontal coordinate of the code-block partition origin on the
0086:                reference grid */
0087:            private int cb0x;
0088:
0089:            /** The vertical coordinate of the code-block partition on the reference
0090:                grid */
0091:            private int cb0y;
0092:
0093:            /** The number of decomposition levels specification */
0094:            private IntegerSpec dls;
0095:
0096:            /** Wavelet filters for all components and tiles */
0097:            private AnWTFilterSpec filters;
0098:
0099:            /** The code-block size specifications */
0100:            private CBlkSizeSpec cblks;
0101:
0102:            /** The precinct partition specifications */
0103:            private PrecinctSizeSpec pss;
0104:
0105:            /** Block storing the full band decomposition for each component. */
0106:            private DataBlk decomposedComps[];
0107:
0108:            /**
0109:             * The horizontal index of the last code-block "sent" in the current
0110:             * subband in each component. It should be -1 if none have been sent yet.
0111:             * */
0112:            private int lastn[];
0113:
0114:            /**
0115:             * The vertical index of the last code-block "sent" in the current subband
0116:             * in each component. It should be 0 if none have been sent yet.
0117:             * */
0118:            private int lastm[];
0119:
0120:            /** The subband being dealt with in each component */
0121:            SubbandAn currentSubband[];
0122:
0123:            /** Cache object to avoid excessive allocation/deallocation. This variable
0124:             * makes the class inheritently thread unsafe. */
0125:            Point ncblks;
0126:
0127:            /**
0128:             * Initializes this object with the given source of image data and with
0129:             * all the decompositon parameters
0130:             *
0131:             * @param src From where the image data should be obtained.
0132:             *
0133:             * @param encSpec The encoder specifications
0134:             *
0135:             * @param pox The horizontal coordinate of the cell and code-block
0136:             * partition origin with respect to the canvas origin, on the reference
0137:             * grid.
0138:             *
0139:             * @param poy The vertical coordinate of the cell and code-block partition
0140:             * origin with respect to the canvas origin, on the reference grid.
0141:             *
0142:             * @see ForwardWT
0143:             * */
0144:            public ForwWTFull(BlkImgDataSrc src, J2KImageWriteParamJava wp,
0145:                    int pox, int poy) {
0146:                super (src);
0147:                this .src = src;
0148:
0149:                this .cb0x = cb0x;
0150:                this .cb0y = cb0y;
0151:                this .dls = wp.getDecompositionLevel();
0152:                this .filters = wp.getFilters();
0153:                this .cblks = wp.getCodeBlockSize();
0154:                this .pss = wp.getPrecinctPartition();
0155:
0156:                int ncomp = src.getNumComps();
0157:                int ntiles = src.getNumTiles();
0158:
0159:                currentSubband = new SubbandAn[ncomp];
0160:                decomposedComps = new DataBlk[ncomp];
0161:                subbTrees = new SubbandAn[ntiles][ncomp];
0162:                lastn = new int[ncomp];
0163:                lastm = new int[ncomp];
0164:            }
0165:
0166:            /**
0167:             * Returns the implementation type of this wavelet transform, WT_IMPL_FULL
0168:             * (full-page based transform). All components return the same.
0169:             *
0170:             * @param c The index of the component.
0171:             *
0172:             * @return WT_IMPL_FULL
0173:             * */
0174:            public int getImplementationType(int c) {
0175:                return WaveletTransform.WT_IMPL_FULL;
0176:            }
0177:
0178:            /**
0179:             * Returns the number of decomposition levels that are applied to the LL
0180:             * band, in the specified tile-component. A value of 0 means that no
0181:             * wavelet transform is applied.
0182:             *
0183:             * @param t The tile index
0184:             *
0185:             * @param c The index of the component.
0186:             *
0187:             * @return The number of decompositions applied to the LL band (0 for no
0188:             * wavelet transform).
0189:             * */
0190:            public int getDecompLevels(int t, int c) {
0191:                return ((Integer) dls.getTileCompVal(t, c)).intValue();
0192:            }
0193:
0194:            /**
0195:             * Returns the wavelet tree decomposition. Actually JPEG 2000 part 1 only
0196:             * supports WT_DECOMP_DYADIC decomposition.
0197:             *
0198:             * @param t The tile-index
0199:             *
0200:             * @param c The index of the component.
0201:             *
0202:             * @return The wavelet decomposition.
0203:             * */
0204:            public int getDecomp(int t, int c) {
0205:                return WT_DECOMP_DYADIC;
0206:            }
0207:
0208:            /**
0209:             * Returns the horizontal analysis wavelet filters used in each level, for
0210:             * the specified component and tile. The first element in the array is the
0211:             * filter used to obtain the lowest resolution (resolution level 0)
0212:             * subbands (i.e. lowest frequency LL subband), the second element is the
0213:             * one used to generate the resolution level 1 subbands, and so on. If
0214:             * there are less elements in the array than the number of resolution
0215:             * levels, then the last one is assumed to repeat itself.
0216:             *
0217:             * <P>The returned filters are applicable only to the specified component
0218:             * and in the current tile.
0219:             *
0220:             * <P>The resolution level of a subband is the resolution level to which a
0221:             * subband contributes, which is different from its decomposition level.
0222:             *
0223:             * @param t The index of the tile for which to return the filters.
0224:             *
0225:             * @param c The index of the component for which to return the filters.
0226:             *
0227:             * @return The horizontal analysis wavelet filters used in each level.
0228:             * */
0229:            public AnWTFilter[] getHorAnWaveletFilters(int t, int c) {
0230:                return filters.getHFilters(t, c);
0231:            }
0232:
0233:            /**
0234:             * Returns the vertical analysis wavelet filters used in each level, for
0235:             * the specified component and tile. The first element in the array is the
0236:             * filter used to obtain the lowest resolution (resolution level 0)
0237:             * subbands (i.e. lowest frequency LL subband), the second element is the
0238:             * one used to generate the resolution level 1 subbands, and so on. If
0239:             * there are less elements in the array than the number of resolution
0240:             * levels, then the last one is assumed to repeat itself.
0241:             *
0242:             * <P>The returned filters are applicable only to the specified component
0243:             * and in the current tile.
0244:             *
0245:             * <P>The resolution level of a subband is the resolution level to which a
0246:             * subband contributes, which is different from its decomposition level.
0247:             *
0248:             * @param t The index of the tile for which to return the filters.
0249:             *
0250:             * @param c The index of the component for which to return the filters.
0251:             *
0252:             * @return The vertical analysis wavelet filters used in each level.
0253:             * */
0254:            public AnWTFilter[] getVertAnWaveletFilters(int t, int c) {
0255:                return filters.getVFilters(t, c);
0256:            }
0257:
0258:            /**
0259:             * Returns the reversibility of the wavelet transform for the specified
0260:             * component and tile. A wavelet transform is reversible when it is
0261:             * suitable for lossless and lossy-to-lossless compression.
0262:             *
0263:             * @param t The index of the tile.
0264:             *
0265:             * @param c The index of the component.
0266:             *
0267:             * @return true is the wavelet transform is reversible, false if not.
0268:             * */
0269:            public boolean isReversible(int t, int c) {
0270:                return filters.isReversible(t, c);
0271:            }
0272:
0273:            /**
0274:             * Returns the horizontal offset of the code-block partition. Allowable
0275:             * values are 0 and 1, nothing else.
0276:             * */
0277:            public int getCbULX() {
0278:                return cb0x;
0279:            }
0280:
0281:            /**
0282:             * Returns the vertical offset of the code-block partition. Allowable
0283:             * values are 0 and 1, nothing else.
0284:             * */
0285:            public int getCbULY() {
0286:                return cb0y;
0287:            }
0288:
0289:            /**
0290:             * Returns the position of the fixed point in the specified
0291:             * component. This is the position of the least significant integral
0292:             * (i.e. non-fractional) bit, which is equivalent to the number of
0293:             * fractional bits. For instance, for fixed-point values with 2 fractional
0294:             * bits, 2 is returned. For floating-point data this value does not apply
0295:             * and 0 should be returned. Position 0 is the position of the least
0296:             * significant bit in the data.
0297:             *
0298:             * @param c The index of the component.
0299:             *
0300:             * @return The position of the fixed-point, which is the same as the
0301:             * number of fractional bits. For floating-point data 0 is returned.
0302:             * */
0303:            public int getFixedPoint(int c) {
0304:                return src.getFixedPoint(c);
0305:            }
0306:
0307:            /**
0308:             * Returns the next code-block in the current tile for the specified
0309:             * component. The order in which code-blocks are returned is not
0310:             * specified. However each code-block is returned only once and all
0311:             * code-blocks will be returned if the method is called 'N' times, where
0312:             * 'N' is the number of code-blocks in the tile. After all the code-blocks
0313:             * have been returned for the current tile calls to this method will
0314:             * return 'null'.
0315:             *
0316:             * <p>When changing the current tile (through 'setTile()' or 'nextTile()')
0317:             * this method will always return the first code-block, as if this method
0318:             * was never called before for the new current tile.</p>
0319:             *
0320:             * <p>The data returned by this method is the data in the internal buffer
0321:             * of this object, and thus can not be modified by the caller. The
0322:             * 'offset' and 'scanw' of the returned data have, in general, some
0323:             * non-zero value. The 'magbits' of the returned data is not set by this
0324:             * method and should be ignored. See the 'CBlkWTData' class.</p>
0325:             *
0326:             * <p>The 'ulx' and 'uly' members of the returned 'CBlkWTData' object
0327:             * contain the coordinates of the top-left corner of the block, with
0328:             * respect to the tile, not the subband.</p>
0329:             *
0330:             * @param c The component for which to return the next code-block.
0331:             *
0332:             * @param cblk If non-null this object will be used to return the new
0333:             * code-block. If null a new one will be allocated and returned.
0334:             *
0335:             * @return The next code-block in the current tile for component 'n', or
0336:             * null if all code-blocks for the current tile have been returned.
0337:             *
0338:             * @see CBlkWTData
0339:             * */
0340:            public CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk) {
0341:                int cbm, cbn, cn, cm;
0342:                int acb0x, acb0y;
0343:                SubbandAn sb;
0344:                intData = (filters.getWTDataType(tIdx, c) == DataBlk.TYPE_INT);
0345:
0346:                //If the source image has not been decomposed 
0347:                if (decomposedComps[c] == null) {
0348:                    int k, w, h;
0349:                    DataBlk bufblk;
0350:                    Object dst_data;
0351:
0352:                    w = getTileCompWidth(tIdx, c);
0353:                    h = getTileCompHeight(tIdx, c);
0354:
0355:                    //Get the source image data
0356:                    if (intData) {
0357:                        decomposedComps[c] = new DataBlkInt(0, 0, w, h);
0358:                        bufblk = new DataBlkInt();
0359:                    } else {
0360:                        decomposedComps[c] = new DataBlkFloat(0, 0, w, h);
0361:                        bufblk = new DataBlkFloat();
0362:                    }
0363:
0364:                    // Get data from source line by line (this diminishes the memory
0365:                    // requirements on the data source)
0366:                    dst_data = decomposedComps[c].getData();
0367:                    int lstart = getCompULX(c);
0368:                    bufblk.ulx = lstart;
0369:                    bufblk.w = w;
0370:                    bufblk.h = 1;
0371:                    int kk = getCompULY(c);
0372:                    for (k = 0; k < h; k++, kk++) {
0373:                        bufblk.uly = kk;
0374:                        bufblk.ulx = lstart;
0375:                        bufblk = src.getInternCompData(bufblk, c);
0376:                        System.arraycopy(bufblk.getData(), bufblk.offset,
0377:                                dst_data, k * w, w);
0378:                    }
0379:
0380:                    //Decompose source image
0381:                    waveletTreeDecomposition(decomposedComps[c],
0382:                            getAnSubbandTree(tIdx, c), c);
0383:
0384:                    // Make the first subband the current one
0385:                    currentSubband[c] = getNextSubband(c);
0386:
0387:                    lastn[c] = -1;
0388:                    lastm[c] = 0;
0389:                }
0390:
0391:                // Get the next code-block to "send"
0392:                do {
0393:                    // Calculate number of code-blocks in current subband
0394:                    ncblks = currentSubband[c].numCb;
0395:                    // Goto next code-block
0396:                    lastn[c]++;
0397:                    if (lastn[c] == ncblks.x) { // Got to end of this row of
0398:                        // code-blocks
0399:                        lastn[c] = 0;
0400:                        lastm[c]++;
0401:                    }
0402:                    if (lastm[c] < ncblks.y) {
0403:                        // Not past the last code-block in the subband, we can return
0404:                        // this code-block
0405:                        break;
0406:                    }
0407:                    // If we get here we already sent all code-blocks in this subband,
0408:                    // goto next subband
0409:                    currentSubband[c] = getNextSubband(c);
0410:                    lastn[c] = -1;
0411:                    lastm[c] = 0;
0412:                    if (currentSubband[c] == null) {
0413:                        // We don't need the transformed data any more (a priori)
0414:                        decomposedComps[c] = null;
0415:                        // All code-blocks from all subbands in the current
0416:                        // tile have been returned so we return a null
0417:                        // reference
0418:                        return null;
0419:                    }
0420:                    // Loop to find the next code-block
0421:                } while (true);
0422:
0423:                // Project code-block partition origin to subband. Since the origin is
0424:                // always 0 or 1, it projects to the low-pass side (throught the ceil
0425:                // operator) as itself (i.e. no change) and to the high-pass side
0426:                // (through the floor operator) as 0, always.
0427:                acb0x = cb0x;
0428:                acb0y = cb0y;
0429:                switch (currentSubband[c].sbandIdx) {
0430:                case Subband.WT_ORIENT_LL:
0431:                    // No need to project since all low-pass => nothing to do
0432:                    break;
0433:                case Subband.WT_ORIENT_HL:
0434:                    acb0x = 0;
0435:                    break;
0436:                case Subband.WT_ORIENT_LH:
0437:                    acb0y = 0;
0438:                    break;
0439:                case Subband.WT_ORIENT_HH:
0440:                    acb0x = 0;
0441:                    acb0y = 0;
0442:                    break;
0443:                default:
0444:                    throw new Error("Internal JJ2000 error");
0445:                }
0446:                // Initialize output code-block
0447:                if (cblk == null) {
0448:                    if (intData) {
0449:                        cblk = new CBlkWTDataInt();
0450:                    } else {
0451:                        cblk = new CBlkWTDataFloat();
0452:                    }
0453:                }
0454:                cbn = lastn[c];
0455:                cbm = lastm[c];
0456:                sb = currentSubband[c];
0457:                cblk.n = cbn;
0458:                cblk.m = cbm;
0459:                cblk.sb = sb;
0460:                // Calculate the indexes of first code-block in subband with respect
0461:                // to the partitioning origin, to then calculate the position and size
0462:                // NOTE: when calculating "floor()" by integer division the dividend
0463:                // and divisor must be positive, we ensure that by adding the divisor
0464:                // to the dividend and then substracting 1 to the result of the
0465:                // division
0466:                cn = (sb.ulcx - acb0x + sb.nomCBlkW) / sb.nomCBlkW - 1;
0467:                cm = (sb.ulcy - acb0y + sb.nomCBlkH) / sb.nomCBlkH - 1;
0468:                if (cbn == 0) { // Left-most code-block, starts where subband starts
0469:                    cblk.ulx = sb.ulx;
0470:                } else {
0471:                    // Calculate starting canvas coordinate and convert to subb. coords
0472:                    cblk.ulx = (cn + cbn) * sb.nomCBlkW - (sb.ulcx - acb0x)
0473:                            + sb.ulx;
0474:                }
0475:                if (cbm == 0) { // Bottom-most code-block, starts where subband starts
0476:                    cblk.uly = sb.uly;
0477:                } else {
0478:                    cblk.uly = (cm + cbm) * sb.nomCBlkH - (sb.ulcy - acb0y)
0479:                            + sb.uly;
0480:                }
0481:                if (cbn < ncblks.x - 1) {
0482:                    // Calculate where next code-block starts => width
0483:                    cblk.w = (cn + cbn + 1) * sb.nomCBlkW - (sb.ulcx - acb0x)
0484:                            + sb.ulx - cblk.ulx;
0485:                } else { // Right-most code-block, ends where subband ends
0486:                    cblk.w = sb.ulx + sb.w - cblk.ulx;
0487:                }
0488:                if (cbm < ncblks.y - 1) {
0489:                    // Calculate where next code-block starts => height
0490:                    cblk.h = (cm + cbm + 1) * sb.nomCBlkH - (sb.ulcy - acb0y)
0491:                            + sb.uly - cblk.uly;
0492:                } else { // Bottom-most code-block, ends where subband ends
0493:                    cblk.h = sb.uly + sb.h - cblk.uly;
0494:                }
0495:                cblk.wmseScaling = 1f;
0496:
0497:                // Since we are in getNextInternCodeBlock() we can return a
0498:                // reference to the internal buffer, no need to copy. Just initialize
0499:                // the 'offset' and 'scanw'
0500:                cblk.offset = cblk.uly * decomposedComps[c].w + cblk.ulx;
0501:                cblk.scanw = decomposedComps[c].w;
0502:
0503:                // For the data just put a reference to our buffer
0504:                cblk.setData(decomposedComps[c].getData());
0505:                // Return code-block
0506:                return cblk;
0507:            }
0508:
0509:            /**
0510:             * Returns the next code-block in the current tile for the specified
0511:             * component, as a copy (see below). The order in which code-blocks are
0512:             * returned is not specified. However each code-block is returned only
0513:             * once and all code-blocks will be returned if the method is called 'N'
0514:             * times, where 'N' is the number of code-blocks in the tile. After all
0515:             * the code-blocks have been returned for the current tile calls to this
0516:             * method will return 'null'.
0517:             *
0518:             * <P>When changing the current tile (through 'setTile()' or 'nextTile()')
0519:             * this method will always return the first code-block, as if this method
0520:             * was never called before for the new current tile.
0521:             *
0522:             * <P>The data returned by this method is always a copy of the internal
0523:             * data of this object, and it can be modified "in place" without
0524:             * any problems after being returned. The 'offset' of the returned data is
0525:             * 0, and the 'scanw' is the same as the code-block width.  The 'magbits'
0526:             * of the returned data is not set by this method and should be
0527:             * ignored. See the 'CBlkWTData' class.
0528:             *
0529:             * <P>The 'ulx' and 'uly' members of the returned 'CBlkWTData' object
0530:             * contain the coordinates of the top-left corner of the block, with
0531:             * respect to the tile, not the subband.
0532:             *
0533:             * @param c The component for which to return the next code-block.
0534:             *
0535:             * @param cblk If non-null this object will be used to return the new
0536:             * code-block. If null a new one will be allocated and returned. If the
0537:             * "data" array of the object is non-null it will be reused, if possible,
0538:             * to return the data.
0539:             *
0540:             * @return The next code-block in the current tile for component 'c', or
0541:             * null if all code-blocks for the current tile have been returned.
0542:             *
0543:             * @see CBlkWTData
0544:             * */
0545:            public CBlkWTData getNextCodeBlock(int c, CBlkWTData cblk) {
0546:                // We can not directly use getNextInternCodeBlock() since that returns
0547:                // a reference to the internal buffer, we have to copy that data
0548:
0549:                int j, k;
0550:                int w;
0551:                Object dst_data; // a int[] or float[] object
0552:                int[] dst_data_int;
0553:                float[] dst_data_float;
0554:                Object src_data; // a int[] or float[] object
0555:
0556:                intData = (filters.getWTDataType(tIdx, c) == DataBlk.TYPE_INT);
0557:
0558:                dst_data = null;
0559:
0560:                // Cache the data array, if any
0561:                if (cblk != null) {
0562:                    dst_data = cblk.getData();
0563:                }
0564:
0565:                // Get the next code-block
0566:                cblk = getNextInternCodeBlock(c, cblk);
0567:
0568:                if (cblk == null) {
0569:                    return null; // No more code-blocks in current tile for component
0570:                    // c
0571:                }
0572:
0573:                // Ensure size of output buffer
0574:                if (intData) { // int data
0575:                    dst_data_int = (int[]) dst_data;
0576:                    if (dst_data_int == null
0577:                            || dst_data_int.length < cblk.w * cblk.h) {
0578:                        dst_data = new int[cblk.w * cblk.h];
0579:                    }
0580:                } else { // float data
0581:                    dst_data_float = (float[]) dst_data;
0582:                    if (dst_data_float == null
0583:                            || dst_data_float.length < cblk.w * cblk.h) {
0584:                        dst_data = new float[cblk.w * cblk.h];
0585:                    }
0586:                }
0587:
0588:                // Copy data line by line
0589:                src_data = cblk.getData();
0590:                w = cblk.w;
0591:                for (j = w * (cblk.h - 1), k = cblk.offset + (cblk.h - 1)
0592:                        * cblk.scanw; j >= 0; j -= w, k -= cblk.scanw) {
0593:                    System.arraycopy(src_data, k, dst_data, j, w);
0594:                }
0595:                cblk.setData(dst_data);
0596:                cblk.offset = 0;
0597:                cblk.scanw = w;
0598:
0599:                return cblk;
0600:            }
0601:
0602:            /**
0603:             * Return the data type of this CBlkWTDataSrc. Its value should be either
0604:             * DataBlk.TYPE_INT or DataBlk.TYPE_FLOAT but can change according to the
0605:             * current tile-component.
0606:             *
0607:             * @param t The index of the tile for which to return the data type.
0608:             *
0609:             * @param c The index of the component for which to return the data type.
0610:             *
0611:             * @return Current data type
0612:             * */
0613:            public int getDataType(int t, int c) {
0614:                return filters.getWTDataType(t, c);
0615:            }
0616:
0617:            /**
0618:             * Returns the next subband that will be used to get the next code-block
0619:             * to return by the getNext[Intern]CodeBlock method.
0620:             *
0621:             * @param c The component
0622:             *
0623:             * @return Its returns the next subband that will be used to get the next
0624:             * code-block to return by the getNext[Intern]CodeBlock method.
0625:             **/
0626:            private SubbandAn getNextSubband(int c) {
0627:                int down = 1;
0628:                int up = 0;
0629:                int direction = down;
0630:                SubbandAn nextsb;
0631:
0632:                nextsb = currentSubband[c];
0633:                //If it is the first call to this method
0634:                if (nextsb == null) {
0635:                    nextsb = this .getAnSubbandTree(tIdx, c);
0636:                    //If there is no decomposition level then send the whole image
0637:                    if (!nextsb.isNode) {
0638:                        return nextsb;
0639:                    }
0640:                }
0641:
0642:                //Find the next subband to send
0643:                do {
0644:                    //If the current subband is null then break
0645:                    if (nextsb == null) {
0646:                        break;
0647:                    }
0648:
0649:                    //If the current subband is a leaf then select the next leaf to
0650:                    //send or go up in the decomposition tree if the leaf was a LL
0651:                    //one.
0652:                    else if (!nextsb.isNode) {
0653:                        switch (nextsb.orientation) {
0654:                        case Subband.WT_ORIENT_HH:
0655:                            nextsb = (SubbandAn) nextsb.getParent().getLH();
0656:                            direction = down;
0657:                            break;
0658:                        case Subband.WT_ORIENT_LH:
0659:                            nextsb = (SubbandAn) nextsb.getParent().getHL();
0660:                            direction = down;
0661:                            break;
0662:                        case Subband.WT_ORIENT_HL:
0663:                            nextsb = (SubbandAn) nextsb.getParent().getLL();
0664:                            direction = down;
0665:                            break;
0666:                        case Subband.WT_ORIENT_LL:
0667:                            nextsb = (SubbandAn) nextsb.getParent();
0668:                            direction = up;
0669:                            break;
0670:                        }
0671:                    }
0672:
0673:                    //Else if the current subband is a node
0674:                    else if (nextsb.isNode) {
0675:                        //If the direction is down the select the HH subband of the
0676:                        //current node.
0677:                        if (direction == down) {
0678:                            nextsb = (SubbandAn) nextsb.getHH();
0679:                        }
0680:                        //Else the direction is up the select the next node to cover
0681:                        //or still go up in the decomposition tree if the node is a LL
0682:                        //subband
0683:                        else if (direction == up) {
0684:                            switch (nextsb.orientation) {
0685:                            case Subband.WT_ORIENT_HH:
0686:                                nextsb = (SubbandAn) nextsb.getParent().getLH();
0687:                                direction = down;
0688:                                break;
0689:                            case Subband.WT_ORIENT_LH:
0690:                                nextsb = (SubbandAn) nextsb.getParent().getHL();
0691:                                direction = down;
0692:                                break;
0693:                            case Subband.WT_ORIENT_HL:
0694:                                nextsb = (SubbandAn) nextsb.getParent().getLL();
0695:                                direction = down;
0696:                                break;
0697:                            case Subband.WT_ORIENT_LL:
0698:                                nextsb = (SubbandAn) nextsb.getParent();
0699:                                direction = up;
0700:                                break;
0701:                            }
0702:                        }
0703:                    }
0704:
0705:                    if (nextsb == null) {
0706:                        break;
0707:                    }
0708:                } while (nextsb.isNode);
0709:                return nextsb;
0710:            }
0711:
0712:            /**
0713:             * Performs the forward wavelet transform on the whole band. It
0714:             * iteratively decomposes the subbands from the top node to the leaves.
0715:             *
0716:             * @param band The band containing the float data to decompose
0717:             *
0718:             * @param subband The structure containing the coordinates of the current
0719:             * subband in the whole band to decompose.
0720:             *
0721:             * @param c The index of the current component to decompose
0722:             * */
0723:            private void waveletTreeDecomposition(DataBlk band,
0724:                    SubbandAn subband, int c) {
0725:
0726:                //If the current subband is a leaf then nothing to be done (a leaf is
0727:                //not decomposed).
0728:                if (!subband.isNode)
0729:                    return;
0730:
0731:                else {
0732:                    //Perform the 2D wavelet decomposition of the current subband
0733:                    wavelet2DDecomposition(band, (SubbandAn) subband, c);
0734:
0735:                    //Perform the decomposition of the four resulting subbands
0736:                    waveletTreeDecomposition(band, (SubbandAn) subband.getHH(),
0737:                            c);
0738:                    waveletTreeDecomposition(band, (SubbandAn) subband.getLH(),
0739:                            c);
0740:                    waveletTreeDecomposition(band, (SubbandAn) subband.getHL(),
0741:                            c);
0742:                    waveletTreeDecomposition(band, (SubbandAn) subband.getLL(),
0743:                            c);
0744:                }
0745:            }
0746:
0747:            /**
0748:             * Performs the 2D forward wavelet transform on a subband of the initial
0749:             * band. This method will successively perform 1D filtering steps on all
0750:             * lines and then all columns of the subband. In this class only filters
0751:             * with floating point implementations can be used.
0752:             *
0753:             * @param band The band containing the float data to decompose
0754:             *
0755:             * @param subband The structure containing the coordinates of the subband
0756:             * in the whole band to decompose.
0757:             *
0758:             * @param c The index of the current component to decompose
0759:             * */
0760:            private void wavelet2DDecomposition(DataBlk band,
0761:                    SubbandAn subband, int c) {
0762:
0763:                int ulx, uly, w, h;
0764:                int band_w, band_h;
0765:
0766:                // If subband is empty (i.e. zero size) nothing to do
0767:                if (subband.w == 0 || subband.h == 0) {
0768:                    return;
0769:                }
0770:
0771:                ulx = subband.ulx;
0772:                uly = subband.uly;
0773:                w = subband.w;
0774:                h = subband.h;
0775:                band_w = getTileCompWidth(tIdx, c);
0776:                band_h = getTileCompHeight(tIdx, c);
0777:
0778:                if (intData) {
0779:                    //Perform the decompositions if the filter is implemented with an
0780:                    //integer arithmetic.
0781:                    int i, j;
0782:                    int offset;
0783:                    int[] tmpVector = new int[java.lang.Math.max(w, h)];
0784:
0785:                    int[] data = ((DataBlkInt) band).getDataInt();
0786:
0787:                    //Perform the vertical decomposition
0788:                    if (subband.ulcy % 2 == 0) { // Even start index => use LPF
0789:                        for (j = 0; j < w; j++) {
0790:                            offset = uly * band_w + ulx + j;
0791:                            for (i = 0; i < h; i++)
0792:                                tmpVector[i] = data[offset + (i * band_w)];
0793:                            subband.vFilter.analyze_lpf(tmpVector, 0, h, 1,
0794:                                    data, offset, band_w, data, offset
0795:                                            + ((h + 1) / 2) * band_w, band_w);
0796:                        }
0797:                    } else { // Odd start index => use HPF
0798:                        for (j = 0; j < w; j++) {
0799:                            offset = uly * band_w + ulx + j;
0800:                            for (i = 0; i < h; i++)
0801:                                tmpVector[i] = data[offset + (i * band_w)];
0802:                            subband.vFilter.analyze_hpf(tmpVector, 0, h, 1,
0803:                                    data, offset, band_w, data, offset
0804:                                            + (h / 2) * band_w, band_w);
0805:                        }
0806:                    }
0807:
0808:                    //Perform the horizontal decomposition.
0809:                    if (subband.ulcx % 2 == 0) { // Even start index => use LPF
0810:                        for (i = 0; i < h; i++) {
0811:                            offset = (uly + i) * band_w + ulx;
0812:                            for (j = 0; j < w; j++)
0813:                                tmpVector[j] = data[offset + j];
0814:                            subband.hFilter.analyze_lpf(tmpVector, 0, w, 1,
0815:                                    data, offset, 1, data,
0816:                                    offset + (w + 1) / 2, 1);
0817:                        }
0818:                    } else { // Odd start index => use HPF
0819:                        for (i = 0; i < h; i++) {
0820:                            offset = (uly + i) * band_w + ulx;
0821:                            for (j = 0; j < w; j++)
0822:                                tmpVector[j] = data[offset + j];
0823:                            subband.hFilter.analyze_hpf(tmpVector, 0, w, 1,
0824:                                    data, offset, 1, data, offset + w / 2, 1);
0825:                        }
0826:                    }
0827:                } else {
0828:                    //Perform the decompositions if the filter is implemented with a
0829:                    //float arithmetic.
0830:                    int i, j;
0831:                    int offset;
0832:                    float[] tmpVector = new float[java.lang.Math.max(w, h)];
0833:                    float[] data = ((DataBlkFloat) band).getDataFloat();
0834:
0835:                    //Perform the vertical decomposition.
0836:                    if (subband.ulcy % 2 == 0) { // Even start index => use LPF
0837:                        for (j = 0; j < w; j++) {
0838:                            offset = uly * band_w + ulx + j;
0839:                            for (i = 0; i < h; i++)
0840:                                tmpVector[i] = data[offset + (i * band_w)];
0841:                            subband.vFilter.analyze_lpf(tmpVector, 0, h, 1,
0842:                                    data, offset, band_w, data, offset
0843:                                            + ((h + 1) / 2) * band_w, band_w);
0844:                        }
0845:                    } else { // Odd start index => use HPF
0846:                        for (j = 0; j < w; j++) {
0847:                            offset = uly * band_w + ulx + j;
0848:                            for (i = 0; i < h; i++)
0849:                                tmpVector[i] = data[offset + (i * band_w)];
0850:                            subband.vFilter.analyze_hpf(tmpVector, 0, h, 1,
0851:                                    data, offset, band_w, data, offset
0852:                                            + (h / 2) * band_w, band_w);
0853:                        }
0854:                    }
0855:                    //Perform the horizontal decomposition.
0856:                    if (subband.ulcx % 2 == 0) { // Even start index => use LPF
0857:                        for (i = 0; i < h; i++) {
0858:                            offset = (uly + i) * band_w + ulx;
0859:                            for (j = 0; j < w; j++)
0860:                                tmpVector[j] = data[offset + j];
0861:                            subband.hFilter.analyze_lpf(tmpVector, 0, w, 1,
0862:                                    data, offset, 1, data,
0863:                                    offset + (w + 1) / 2, 1);
0864:                        }
0865:                    } else { // Odd start index => use HPF
0866:                        for (i = 0; i < h; i++) {
0867:                            offset = (uly + i) * band_w + ulx;
0868:                            for (j = 0; j < w; j++)
0869:                                tmpVector[j] = data[offset + j];
0870:                            subband.hFilter.analyze_hpf(tmpVector, 0, w, 1,
0871:                                    data, offset, 1, data, offset + w / 2, 1);
0872:                        }
0873:                    }
0874:                }
0875:            }
0876:
0877:            /**
0878:             * Changes the current tile, given the new coordinates.
0879:             *
0880:             * <P>This method resets the 'subbTrees' array, and recalculates the
0881:             * values of the 'reversible' array. It also resets the decomposed
0882:             * component buffers.
0883:             *
0884:             * @param x The horizontal coordinate of the tile.
0885:             *
0886:             * @param y The vertical coordinate of the new tile.
0887:             * */
0888:            public void setTile(int x, int y) {
0889:                int i;
0890:
0891:                // Change tile
0892:                super .setTile(x, y);
0893:
0894:                // Reset the decomposed component buffers.
0895:                if (decomposedComps != null) {
0896:                    for (i = decomposedComps.length - 1; i >= 0; i--) {
0897:                        decomposedComps[i] = null;
0898:                        currentSubband[i] = null;
0899:                    }
0900:                }
0901:
0902:            }
0903:
0904:            /**
0905:             * Advances to the next tile, in standard scan-line order (by rows then
0906:             * columns). An NoNextElementException is thrown if the current tile is
0907:             * the last one (i.e. there is no next tile).
0908:             *
0909:             * <P>This method resets the 'subbTrees' array, and recalculates the
0910:             * values of the 'reversible' array. It also resets the decomposed
0911:             * component buffers.
0912:             * */
0913:            public void nextTile() {
0914:                int i;
0915:
0916:                // Change tile
0917:                super .nextTile();
0918:                // Reset the decomposed component buffers
0919:                if (decomposedComps != null) {
0920:                    for (i = decomposedComps.length - 1; i >= 0; i--) {
0921:                        decomposedComps[i] = null;
0922:                        currentSubband[i] = null;
0923:                    }
0924:                }
0925:
0926:            }
0927:
0928:            /**
0929:             * Returns a reference to the subband tree structure representing the
0930:             * subband decomposition for the specified tile-component of the source.
0931:             *
0932:             * @param t The index of the tile.
0933:             *
0934:             * @param c The index of the component.
0935:             *
0936:             * @return The subband tree structure, see Subband.
0937:             *
0938:             * @see SubbandAn
0939:             * @see Subband
0940:             * */
0941:            public SubbandAn getAnSubbandTree(int t, int c) {
0942:                if (subbTrees[t][c] == null) {
0943:                    subbTrees[t][c] = new SubbandAn(getTileCompWidth(tIdx, c),
0944:                            getTileCompHeight(tIdx, c), getCompULX(c),
0945:                            getCompULY(c), getDecompLevels(t, c),
0946:                            getHorAnWaveletFilters(t, c),
0947:                            getVertAnWaveletFilters(t, c));
0948:                    initSubbandsFields(t, c, subbTrees[t][c]);
0949:                }
0950:                return subbTrees[t][c];
0951:            }
0952:
0953:            /** 
0954:             * Initialises subbands fields, such as number of code-blocks and
0955:             * code-blocks dimension, in the subband tree. The nominal code-block
0956:             * width/height depends on the precincts dimensions if used.
0957:             *
0958:             * @param t The tile index of the subband
0959:             *
0960:             * @param c The component index
0961:             *
0962:             * @param sb The subband tree to be initialised.
0963:             * */
0964:            private void initSubbandsFields(int t, int c, Subband sb) {
0965:                int cbw = cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c);
0966:                int cbh = cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c);
0967:
0968:                if (!sb.isNode) {
0969:                    // Code-blocks dimension
0970:                    int ppx, ppy;
0971:                    int ppxExp, ppyExp, cbwExp, cbhExp;
0972:                    ppx = pss.getPPX(t, c, sb.resLvl);
0973:                    ppy = pss.getPPY(t, c, sb.resLvl);
0974:
0975:                    if (ppx != Markers.PRECINCT_PARTITION_DEF_SIZE
0976:                            || ppy != Markers.PRECINCT_PARTITION_DEF_SIZE) {
0977:
0978:                        ppxExp = MathUtil.log2(ppx);
0979:                        ppyExp = MathUtil.log2(ppy);
0980:                        cbwExp = MathUtil.log2(cbw);
0981:                        cbhExp = MathUtil.log2(cbh);
0982:
0983:                        // Precinct partition is used
0984:                        switch (sb.resLvl) {
0985:                        case 0:
0986:                            sb.nomCBlkW = (cbwExp < ppxExp ? (1 << cbwExp)
0987:                                    : (1 << ppxExp));
0988:                            sb.nomCBlkH = (cbhExp < ppyExp ? (1 << cbhExp)
0989:                                    : (1 << ppyExp));
0990:                            break;
0991:
0992:                        default:
0993:                            sb.nomCBlkW = (cbwExp < ppxExp - 1 ? (1 << cbwExp)
0994:                                    : (1 << (ppxExp - 1)));
0995:                            sb.nomCBlkH = (cbhExp < ppyExp - 1 ? (1 << cbhExp)
0996:                                    : (1 << (ppyExp - 1)));
0997:                            break;
0998:                        }
0999:                    } else {
1000:                        sb.nomCBlkW = cbw;
1001:                        sb.nomCBlkH = cbh;
1002:                    }
1003:
1004:                    // Number of code-blocks
1005:                    if (sb.numCb == null)
1006:                        sb.numCb = new Point();
1007:                    if (sb.w != 0 && sb.h != 0) {
1008:                        int acb0x = cb0x;
1009:                        int acb0y = cb0y;
1010:                        int tmp;
1011:
1012:                        // Project code-block partition origin to subband. Since the
1013:                        // origin is always 0 or 1, it projects to the low-pass side
1014:                        // (throught the ceil operator) as itself (i.e. no change) and
1015:                        // to the high-pass side (through the floor operator) as 0,
1016:                        // always.
1017:                        switch (sb.sbandIdx) {
1018:                        case Subband.WT_ORIENT_LL:
1019:                            // No need to project since all low-pass => nothing to do
1020:                            break;
1021:                        case Subband.WT_ORIENT_HL:
1022:                            acb0x = 0;
1023:                            break;
1024:                        case Subband.WT_ORIENT_LH:
1025:                            acb0y = 0;
1026:                            break;
1027:                        case Subband.WT_ORIENT_HH:
1028:                            acb0x = 0;
1029:                            acb0y = 0;
1030:                            break;
1031:                        default:
1032:                            throw new Error("Internal JJ2000 error");
1033:                        }
1034:                        if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0) {
1035:                            throw new IllegalArgumentException(
1036:                                    "Invalid code-blocks "
1037:                                            + "partition origin or "
1038:                                            + "image offset in the "
1039:                                            + "reference grid.");
1040:                        }
1041:                        // NOTE: when calculating "floor()" by integer division the
1042:                        // dividend and divisor must be positive, we ensure that by
1043:                        // adding the divisor to the dividend and then substracting 1
1044:                        // to the result of the division
1045:                        tmp = sb.ulcx - acb0x + sb.nomCBlkW;
1046:                        sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW
1047:                                - (tmp / sb.nomCBlkW - 1);
1048:                        tmp = sb.ulcy - acb0y + sb.nomCBlkH;
1049:                        sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH
1050:                                - (tmp / sb.nomCBlkH - 1);
1051:                    } else {
1052:                        sb.numCb.x = sb.numCb.y = 0;
1053:                    }
1054:                } else {
1055:                    initSubbandsFields(t, c, sb.getLL());
1056:                    initSubbandsFields(t, c, sb.getHL());
1057:                    initSubbandsFields(t, c, sb.getLH());
1058:                    initSubbandsFields(t, c, sb.getHH());
1059:                }
1060:            }
1061:
1062:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.