0001: /*
0002: * $RCSfile: BitstreamReaderAgent.java,v $
0003: * $Revision: 1.1 $
0004: * $Date: 2005/02/11 05:02:00 $
0005: * $State: Exp $
0006: *
0007: * Class: BitstreamReaderAgent
0008: *
0009: * Description: The generic interface for bit stream
0010: * transport agents.
0011: *
0012: *
0013: *
0014: * COPYRIGHT:
0015: *
0016: * This software module was originally developed by Raphaël Grosbois and
0017: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
0018: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
0019: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
0020: * Centre France S.A) in the course of development of the JPEG2000
0021: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
0022: * software module is an implementation of a part of the JPEG 2000
0023: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
0024: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
0025: * Partners) agree not to assert against ISO/IEC and users of the JPEG
0026: * 2000 Standard (Users) any of their rights under the copyright, not
0027: * including other intellectual property rights, for this software module
0028: * with respect to the usage by ISO/IEC and Users of this software module
0029: * or modifications thereof for use in hardware or software products
0030: * claiming conformance to the JPEG 2000 Standard. Those intending to use
0031: * this software module in hardware or software products are advised that
0032: * their use may infringe existing patents. The original developers of
0033: * this software module, JJ2000 Partners and ISO/IEC assume no liability
0034: * for use of this software module or modifications thereof. No license
0035: * or right to this software module is granted for non JPEG 2000 Standard
0036: * conforming products. JJ2000 Partners have full right to use this
0037: * software module for his/her own purpose, assign or donate this
0038: * software module to any third party and to inhibit third parties from
0039: * using this software module for non JPEG 2000 Standard conforming
0040: * products. This copyright notice must be included in all copies or
0041: * derivative works of this software module.
0042: *
0043: * Copyright (c) 1999/2000 JJ2000 Partners.
0044: * */
0045: package jj2000.j2k.codestream.reader;
0046:
0047: import java.awt.Point;
0048:
0049: import jj2000.j2k.quantization.dequantizer.*;
0050: import jj2000.j2k.wavelet.synthesis.*;
0051: import jj2000.j2k.entropy.decoder.*;
0052: import jj2000.j2k.codestream.*;
0053: import jj2000.j2k.wavelet.*;
0054: import jj2000.j2k.decoder.*;
0055: import jj2000.j2k.image.*;
0056: import jj2000.j2k.util.*;
0057: import jj2000.j2k.io.*;
0058: import jj2000.j2k.*;
0059:
0060: import java.io.*;
0061:
0062: import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReadParamJava;
0063:
0064: /**
0065: * This is the generic interface for bit stream reader agents. A bit stream
0066: * reader agent is an entity that allows reading from a bit stream and
0067: * requesting compressed code-blocks. It can be a simple file reader, or a
0068: * network connection, or anything else.
0069: *
0070: * <P>The bit stream reader agent allows to make request for compressed block
0071: * data in any order. The amount of data returned would normally depend on the
0072: * data available at the time of the request, be it from a file or from a
0073: * network connection.
0074: *
0075: * <P>The bit stream reader agent has the notion of a current tile, and
0076: * coordinates are relative to the current tile, where applicable.
0077: *
0078: * <P>Resolution level 0 is the lowest resolution level, i.e. the LL subband
0079: * alone.
0080: * */
0081: public abstract class BitstreamReaderAgent implements
0082: CodedCBlkDataSrcDec {
0083:
0084: /** The decoder specifications */
0085: protected DecoderSpecs decSpec;
0086:
0087: /**
0088: * Whether or not the components in the current tile uses a derived
0089: * quantization step size (only relevant in non reversible quantization
0090: * mode). This field is actualized by the setTile method in
0091: * FileBitstreamReaderAgent.
0092: *
0093: * @see FileBitstreamReaderAgent#initSubbandsFields
0094: * */
0095: protected boolean derived[] = null;
0096:
0097: /**
0098: * Number of guard bits off all component in the current tile. This field
0099: * is actualized by the setTile method in FileBitstreamReaderAgent.
0100: *
0101: * @see FileBitstreamReaderAgent#initSubbandsFields
0102: * */
0103: protected int[] gb = null;
0104:
0105: /**
0106: * Dequantization parameters of all subbands and all components in the
0107: * current tile. The value is actualized by the setTile method in
0108: * FileBitstreamReaderAgent.
0109: *
0110: * @see FileBitstreamReaderAgent#initSubbandsFields
0111: * */
0112: protected StdDequantizerParams params[] = null;
0113:
0114: /** The prefix for bit stream reader options: 'B' */
0115: public final static char OPT_PREFIX = 'B';
0116:
0117: /** The list of parameters that is accepted by the bit stream
0118: * readers. They start with 'B'. */
0119: private static final String[][] pinfo = null;
0120:
0121: /**
0122: * The maximum number of decompostion levels for each component of the
0123: * current tile. It means that component c has mdl[c]+1 resolution levels
0124: * (indexed from 0 to mdl[c])
0125: * */
0126: protected int mdl[];
0127:
0128: /** The number of components */
0129: protected final int nc;
0130:
0131: /** Image resolution level to generate */
0132: protected int targetRes;
0133:
0134: /**
0135: * The subband trees for each component in the current tile. Each element
0136: * in the array is the root element of the subband tree for a
0137: * component. The number of magnitude bits in each subband (magBits member
0138: * variable) is not initialized.
0139: * */
0140: protected SubbandSyn subbTrees[];
0141:
0142: /** The image width on the hi-res reference grid */
0143: protected final int imgW;
0144:
0145: /** The image width on the hi-res reference grid */
0146: protected final int imgH;
0147:
0148: /** The horizontal coordinate of the image origin in the canvas system, on
0149: * the reference grid. */
0150: protected final int ax;
0151:
0152: /** The vertical coordinate of the image origin in the canvas system, on
0153: * the reference grid. */
0154: protected final int ay;
0155:
0156: /** The horizontal coordinate of the tiling origin in the canvas system, on
0157: * the reference grid. */
0158: protected final int px;
0159:
0160: /** The vertical coordinate of the tiling origin in the canvas system, on
0161: * the reference grid. */
0162: protected final int py;
0163:
0164: /** The horizontal offsets of the upper-left corner of the current tile
0165: * (not active tile) with respect to the canvas origin, in the component
0166: * hi-res grid, for each component. */
0167: protected final int offX[];
0168:
0169: /** The vertical offsets of the upper-left corner of the current tile (not
0170: * active tile) with respect to the canvas origin, in the component hi-res
0171: * grid, for each component. */
0172: protected final int offY[];
0173:
0174: /** The horizontal coordinates of the upper-left corner of the active
0175: * tile, with respect to the canvas origin, in the component hi-res grid,
0176: * for each component. */
0177: protected final int culx[];
0178:
0179: /** The vertical coordinates of the upper-left corner of the active tile,
0180: * with respect to the canvas origin, in the component hi-res grid, for
0181: * each component. */
0182: protected final int culy[];
0183:
0184: /** The nominal tile width, in the hi-res reference grid */
0185: protected final int ntW;
0186:
0187: /** The nominal tile height, in the hi-res reference grid */
0188: protected final int ntH;
0189:
0190: /** The number of tile in the horizontal direction */
0191: protected final int ntX;
0192:
0193: /** The number of tiles in the vertical direction */
0194: protected final int ntY;
0195:
0196: /** The total number of tiles. */
0197: protected final int nt;
0198:
0199: /** The current tile horizontal index */
0200: protected int ctX;
0201:
0202: /** The current tile vertical index */
0203: protected int ctY;
0204:
0205: /** The decoded bit stream header */
0206: protected final HeaderDecoder hd;
0207:
0208: /** Number of bytes targeted to be read */
0209: protected int tnbytes;
0210:
0211: /** Actual number of read bytes */
0212: protected int anbytes;
0213:
0214: /** Target decoding rate in bpp */
0215: protected float trate;
0216:
0217: /** Actual decoding rate in bpp */
0218: protected float arate;
0219:
0220: /**
0221: * Initializes members of this class. This constructor takes a
0222: * HeaderDecoder object. This object must be initialized by the
0223: * constructor of the implementing class from the header of the bit
0224: * stream.
0225: *
0226: * @param hd The decoded header of the bit stream from where to initialize
0227: * the values.
0228: *
0229: * @param decSpec The decoder specifications
0230: * */
0231: protected BitstreamReaderAgent(HeaderDecoder hd,
0232: DecoderSpecs decSpec) {
0233: Point co;
0234: int i, j, max;
0235:
0236: this .decSpec = decSpec;
0237: this .hd = hd;
0238:
0239: // Number of components
0240: nc = hd.getNumComps();
0241: offX = new int[nc];
0242: offY = new int[nc];
0243: culx = new int[nc];
0244: culy = new int[nc];
0245:
0246: // Image size and origin
0247: imgW = hd.getImgWidth();
0248: imgH = hd.getImgHeight();
0249: ax = hd.getImgULX();
0250: ay = hd.getImgULY();
0251:
0252: // Tiles
0253: co = hd.getTilingOrigin(null);
0254: px = co.x;
0255: py = co.y;
0256: ntW = hd.getNomTileWidth();
0257: ntH = hd.getNomTileHeight();
0258: ntX = (ax + imgW - px + ntW - 1) / ntW;
0259: ntY = (ay + imgH - py + ntH - 1) / ntH;
0260: nt = ntX * ntY;
0261: }
0262:
0263: /**
0264: * Returns the vertical code-block partition origin. Allowable values are
0265: * 0 and 1, nothing else.
0266: * */
0267: public final int getCbULX() {
0268: return hd.getCbULX();
0269: }
0270:
0271: /**
0272: * Returns the vertical code-block partition origin. Allowable values are
0273: * 0 and 1, nothing else.
0274: * */
0275: public int getCbULY() {
0276: return hd.getCbULY();
0277: }
0278:
0279: /**
0280: * Returns the number of components in the image.
0281: *
0282: * @return The number of components in the image.
0283: * */
0284: public final int getNumComps() {
0285: return nc;
0286: }
0287:
0288: /**
0289: * Returns the component subsampling factor in the horizontal direction,
0290: * for the specified component. This is, approximately, the ratio of
0291: * dimensions between the reference grid and the component itself, see the
0292: * 'ImgData' interface desription for details.
0293: *
0294: * @param c The index of the component (between 0 and N-1)
0295: *
0296: * @return The horizontal subsampling factor of component 'c'
0297: *
0298: * @see jj2000.j2k.image.ImgData
0299: * */
0300: public final int getCompSubsX(int c) {
0301: return hd.getCompSubsX(c);
0302: }
0303:
0304: /**
0305: * Returns the component subsampling factor in the vertical direction, for
0306: * the specified component. This is, approximately, the ratio of
0307: * dimensions between the reference grid and the component itself, see the
0308: * 'ImgData' interface desription for details.
0309: *
0310: * @param c The index of the component (between 0 and C-1)
0311: *
0312: * @return The vertical subsampling factor of component 'c'
0313: *
0314: * @see jj2000.j2k.image.ImgData
0315: * */
0316: public int getCompSubsY(int c) {
0317: return hd.getCompSubsY(c);
0318: }
0319:
0320: /**
0321: * Returns the overall width of the current tile in pixels for the given
0322: * (tile) resolution level. This is the tile's width without accounting
0323: * for any component subsampling.
0324: *
0325: * <P>Note: Tile resolution level indexes may be different from
0326: * tile-component resolution index. They are indeed indexed starting from
0327: * the lowest number of decomposition levels of each component of the
0328: * tile.
0329: *
0330: * <P>For an image (1 tile) with 2 components (component 0 having 2
0331: * decomposition levels and component 1 having 3 decomposition levels),
0332: * the first (tile-)component has 3 resolution levels and the second one
0333: * has 4 resolution levels, whereas the tile has only 3 resolution levels
0334: * available.
0335: *
0336: * @param rl The (tile) resolution level.
0337: *
0338: * @return The current tile's width in pixels.
0339: * */
0340: public int getTileWidth(int rl) {
0341: // The minumum number of decomposition levels between all the
0342: // components
0343: int mindl = decSpec.dls.getMinInTile(getTileIdx());
0344: if (rl > mindl) {
0345: throw new IllegalArgumentException(
0346: "Requested resolution level"
0347: + " is not available for, at "
0348: + "least, one component in " + "tile: "
0349: + ctX + "x" + ctY);
0350: }
0351: int ctulx, ntulx;
0352: int dl = mindl - rl; // Number of decomposition to obtain this
0353: // resolution
0354:
0355: // Calculate starting X of current tile at hi-res
0356: ctulx = (ctX == 0) ? ax : px + ctX * ntW;
0357: // Calculate starting X of next tile X-wise at hi-res
0358: ntulx = (ctX < ntX - 1) ? px + (ctX + 1) * ntW : ax + imgW;
0359: dl = 1 << dl;
0360: // The difference at the rl resolution level is the width
0361: return (ntulx + dl - 1) / dl - (ctulx + dl - 1) / dl;
0362: }
0363:
0364: /**
0365: * Returns the overall height of the current tile in pixels, for the given
0366: * resolution level. This is the tile's height without accounting for any
0367: * component subsampling.
0368: *
0369: * <P>Note: Tile resolution level indexes may be different from
0370: * tile-component resolution index. They are indeed indexed starting from
0371: * the lowest number of decomposition levels of each component of the
0372: * tile.
0373: *
0374: * <P>For an image (1 tile) with 2 components (component 0 having 2
0375: * decomposition levels and component 1 having 3 decomposition levels),
0376: * the first (tile-)component has 3 resolution levels and the second one
0377: * has 4 resolution levels, whereas the tile has only 3 resolution levels
0378: * available.
0379: *
0380: * @param rl The (tile) resolution level.
0381: *
0382: * @return The total current tile's height in pixels.
0383: * */
0384: public int getTileHeight(int rl) {
0385: // The minumum number of decomposition levels between all the
0386: // components
0387: int mindl = decSpec.dls.getMinInTile(getTileIdx());
0388: if (rl > mindl) {
0389: throw new IllegalArgumentException(
0390: "Requested resolution level"
0391: + " is not available for, at "
0392: + "least, one component in" + " tile: "
0393: + ctX + "x" + ctY);
0394: }
0395:
0396: int ctuly, ntuly;
0397: int dl = mindl - rl; // Number of decomposition to obtain this
0398: // resolution
0399:
0400: // Calculate starting Y of current tile at hi-res
0401: ctuly = (ctY == 0) ? ay : py + ctY * ntH;
0402: // Calculate starting Y of next tile Y-wise at hi-res
0403: ntuly = (ctY < ntY - 1) ? py + (ctY + 1) * ntH : ay + imgH;
0404: dl = 1 << dl;
0405: // The difference at the rl level is the height
0406: return (ntuly + dl - 1) / dl - (ctuly + dl - 1) / dl;
0407: }
0408:
0409: /**
0410: * Returns the overall width of the image in pixels, for the given (image)
0411: * resolution level. This is the image's width without accounting for any
0412: * component subsampling or tiling.
0413: *
0414: * <P>Note: Image resolution level indexes may differ from tile-component
0415: * resolution index. They are indeed indexed starting from the lowest
0416: * number of decomposition levels of each component of each tile.
0417: *
0418: * <P>Example: For an image (1 tile) with 2 components (component 0 having
0419: * 2 decomposition levels and component 1 having 3 decomposition levels),
0420: * the first (tile-) component has 3 resolution levels and the second one
0421: * has 4 resolution levels, whereas the image has only 3 resolution levels
0422: * available.
0423: *
0424: * @param rl The image resolution level.
0425: *
0426: * @return The total image's width in pixels.
0427: * */
0428: public int getImgWidth(int rl) {
0429: // The minimum number of decomposition levels of each
0430: // tile-component
0431: int mindl = decSpec.dls.getMin();
0432: if (rl > mindl) {
0433: throw new IllegalArgumentException(
0434: "Requested resolution level"
0435: + " is not available for, at "
0436: + "least, one tile-component");
0437: }
0438: // Retrieve number of decomposition levels corresponding to
0439: // this resolution level
0440: int dl = 1 << mindl - rl;
0441: return (ax + imgW + dl - 1) / dl - (ax + dl - 1) / dl;
0442: }
0443:
0444: /**
0445: * Returns the overall height of the image in pixels, for the given
0446: * resolution level. This is the image's height without accounting for any
0447: * component subsampling or tiling.
0448: *
0449: * <P>Note: Image resolution level indexes may differ from tile-component
0450: * resolution index. They are indeed indexed starting from the lowest
0451: * number of decomposition levels of each component of each tile.
0452: *
0453: * <P>Example: For an image (1 tile) with 2 components (component 0 having
0454: * 2 decomposition levels and component 1 having 3 decomposition levels),
0455: * the first (tile-) component has 3 resolution levels and the second one
0456: * has 4 resolution levels, whereas the image has only 3 resolution levels
0457: * available.
0458: *
0459: * @param rl The image resolution level, from 0 to L.
0460: *
0461: * @return The total image's height in pixels.
0462: * */
0463: public int getImgHeight(int rl) {
0464: int mindl = decSpec.dls.getMin();
0465: if (rl > mindl) {
0466: throw new IllegalArgumentException(
0467: "Requested resolution level"
0468: + " is not available for, at "
0469: + "least, one tile-component");
0470: }
0471: // Retrieve number of decomposition levels corresponding to this
0472: // resolution level
0473: int dl = 1 << mindl - rl;
0474: return (ay + imgH + dl - 1) / dl - (ay + dl - 1) / dl;
0475: }
0476:
0477: /**
0478: * Returns the horizontal coordinate of the image origin, the top-left
0479: * corner, in the canvas system, on the reference grid at the specified
0480: * resolution level.
0481: *
0482: * <P>Note: Image resolution level indexes may differ from tile-component
0483: * resolution index. They are indeed indexed starting from the lowest
0484: * number of decomposition levels of each component of each tile.
0485: *
0486: * <P>Example: For an image (1 tile) with 2 components (component 0 having
0487: * 2 decomposition levels and component 1 having 3 decomposition levels),
0488: * the first (tile-) component has 3 resolution levels and the second one
0489: * has 4 resolution levels, whereas the image has only 3 resolution levels
0490: * available.
0491: *
0492: * @param rl The resolution level, from 0 to L.
0493: *
0494: * @return The horizontal coordinate of the image origin in the canvas
0495: * system, on the reference grid.
0496: * */
0497: public int getImgULX(int rl) {
0498: int mindl = decSpec.dls.getMin();
0499: if (rl > mindl) {
0500: throw new IllegalArgumentException(
0501: "Requested resolution level"
0502: + " is not available for, at "
0503: + "least, one tile-component");
0504: }
0505: // Retrieve number of decomposition levels corresponding to this
0506: // resolution level
0507: int dl = 1 << mindl - rl;
0508: return (ax + dl - 1) / dl;
0509: }
0510:
0511: /**
0512: * Returns the vertical coordinate of the image origin, the top-left
0513: * corner, in the canvas system, on the reference grid at the specified
0514: * resolution level.
0515: *
0516: * <P>Note: Image resolution level indexes may differ from tile-component
0517: * resolution index. They are indeed indexed starting from the lowest
0518: * number of decomposition levels of each component of each tile.
0519: *
0520: * <P>Example: For an image (1 tile) with 2 components (component 0 having
0521: * 2 decomposition levels and component 1 having 3 decomposition levels),
0522: * the first (tile-) component has 3 resolution levels and the second one
0523: * has 4 resolution levels, whereas the image has only 3 resolution levels
0524: * available.
0525: *
0526: * @param rl The resolution level, from 0 to L.
0527: *
0528: * @return The vertical coordinate of the image origin in the canvas
0529: * system, on the reference grid.
0530: * */
0531: public int getImgULY(int rl) {
0532: int mindl = decSpec.dls.getMin();
0533: if (rl > mindl) {
0534: throw new IllegalArgumentException(
0535: "Requested resolution level"
0536: + " is not available for, at "
0537: + "least, one tile-component");
0538: }
0539: // Retrieve number of decomposition levels corresponding to this
0540: // resolution level
0541: int dl = 1 << mindl - rl;
0542: return (ay + dl - 1) / dl;
0543: }
0544:
0545: /**
0546: * Returns the width in pixels of the specified tile-component for the
0547: * given (tile-component) resolution level.
0548: *
0549: * @param t The tile index
0550: *
0551: * @param c The index of the component, from 0 to N-1.
0552: *
0553: * @param rl The resolution level, from 0 to L.
0554: *
0555: * @return The width in pixels of component <tt>c</tt> in tile <tt>t</tt>
0556: * for resolution level <tt>rl</tt>.
0557: * */
0558: public final int getTileCompWidth(int t, int c, int rl) {
0559: int tIdx = getTileIdx();
0560: if (t != tIdx) {
0561: throw new Error(
0562: "Asking the tile-component width of a tile "
0563: + "different from the current one.");
0564: }
0565: // Calculate starting X of next tile X-wise at reference grid hi-res
0566: int ntulx = (ctX < ntX - 1) ? px + (ctX + 1) * ntW : ax + imgW;
0567: // Convert reference grid hi-res to component grid hi-res
0568: ntulx = (ntulx + hd.getCompSubsX(c) - 1) / hd.getCompSubsX(c);
0569: int dl = 1 << mdl[c] - rl;
0570: // Starting X of current tile at component grid hi-res is culx[c]
0571: // The difference at the rl level is the width
0572: return (ntulx + dl - 1) / dl - (culx[c] + dl - 1) / dl;
0573: }
0574:
0575: /**
0576: * Returns the height in pixels of the specified tile-component for the
0577: * given (tile-component) resolution level.
0578: *
0579: * @param t The tile index.
0580: *
0581: * @param c The index of the component, from 0 to N-1.
0582: *
0583: * @param rl The resolution level, from 0 to L.
0584: *
0585: * @return The height in pixels of component <tt>c</tt> in the current
0586: * tile.
0587: * */
0588: public final int getTileCompHeight(int t, int c, int rl) {
0589: int tIdx = getTileIdx();
0590: if (t != tIdx) {
0591: throw new Error(
0592: "Asking the tile-component width of a tile "
0593: + "different from the current one.");
0594: }
0595: // Calculate starting Y of next tile Y-wise at reference grid hi-res
0596: int ntuly = (ctY < ntY - 1) ? py + (ctY + 1) * ntH : ay + imgH;
0597: // Convert reference grid hi-res to component grid hi-res
0598: ntuly = (ntuly + hd.getCompSubsY(c) - 1) / hd.getCompSubsY(c);
0599: int dl = 1 << mdl[c] - rl; // Revert level indexation (0 is hi-res)
0600: // Starting Y of current tile at component grid hi-res is culy[c]
0601: // The difference at the rl level is the height
0602: return (ntuly + dl - 1) / dl - (culy[c] + dl - 1) / dl;
0603: }
0604:
0605: /**
0606: * Returns the width in pixels of the specified component in the overall
0607: * image, for the given (component) resolution level.
0608: *
0609: * <P>Note: Component resolution level indexes may differ from
0610: * tile-component resolution index. They are indeed indexed starting from
0611: * the lowest number of decomposition levels of same component of each
0612: * tile.
0613: *
0614: * <P>Example: For an image (2 tiles) with 1 component (tile 0 having 2
0615: * decomposition levels and tile 1 having 3 decomposition levels), the
0616: * first tile(-component) has 3 resolution levels and the second one has 4
0617: * resolution levels, whereas the component has only 3 resolution levels
0618: * available.
0619: *
0620: * @param c The index of the component, from 0 to N-1.
0621: *
0622: * @param rl The resolution level, from 0 to L.
0623: *
0624: * @return The width in pixels of component <tt>c</tt> in the overall
0625: * image.
0626: * */
0627: public final int getCompImgWidth(int c, int rl) {
0628: // indexation (0 is hi-res)
0629: // Calculate image starting x at component hi-res grid
0630: int sx = (ax + hd.getCompSubsX(c) - 1) / hd.getCompSubsX(c);
0631: // Calculate image ending (excluding) x at component hi-res grid
0632: int ex = (ax + imgW + hd.getCompSubsX(c) - 1)
0633: / hd.getCompSubsX(c);
0634: int dl = 1 << decSpec.dls.getMinInComp(c) - rl;
0635: // The difference at the rl level is the width
0636: return (ex + dl - 1) / dl - (sx + dl - 1) / dl;
0637: }
0638:
0639: /**
0640: * Returns the height in pixels of the specified component in the overall
0641: * image, for the given (component) resolution level.
0642: *
0643: * <P>Note: Component resolution level indexes may differ from
0644: * tile-component resolution index. They are indeed indexed starting from
0645: * the lowest number of decomposition levels of same component of each
0646: * tile.
0647: *
0648: * <P>Example: For an image (2 tiles) with 1 component (tile 0 having 2
0649: * decomposition levels and tile 1 having 3 decomposition levels), the
0650: * first tile(-component) has 3 resolution levels and the second one has 4
0651: * resolution levels, whereas the component has only 3 resolution levels
0652: * available.
0653: *
0654: * @param c The index of the component, from 0 to N-1.
0655: *
0656: * @param rl The resolution level, from 0 to L.
0657: *
0658: * @return The height in pixels of component <tt>c</tt> in the overall
0659: * image.
0660: * */
0661: public final int getCompImgHeight(int c, int rl) {
0662: // indexation (0 is hi-res)
0663: // Calculate image starting x at component hi-res grid
0664: int sy = (ay + hd.getCompSubsY(c) - 1) / hd.getCompSubsY(c);
0665: // Calculate image ending (excluding) x at component hi-res grid
0666: int ey = (ay + imgH + hd.getCompSubsY(c) - 1)
0667: / hd.getCompSubsY(c);
0668: int dl = 1 << decSpec.dls.getMinInComp(c) - rl;
0669: // The difference at the rl level is the width
0670: return (ey + dl - 1) / dl - (sy + dl - 1) / dl;
0671: }
0672:
0673: /**
0674: * Changes the current tile, given the new indexes. An
0675: * IllegalArgumentException is thrown if the indexes do not correspond to
0676: * a valid tile.
0677: *
0678: * @param x The horizontal indexes the tile.
0679: *
0680: * @param y The vertical indexes of the new tile.
0681: * */
0682: public abstract void setTile(int x, int y);
0683:
0684: /**
0685: * Advances to the next tile, in standard scan-line order (by rows then
0686: * columns). An NoNextElementException is thrown if the current tile is
0687: * the last one (i.e. there is no next tile).
0688: * */
0689: public abstract void nextTile();
0690:
0691: /**
0692: * Returns the indexes of the current tile. These are the horizontal and
0693: * vertical indexes of the current tile.
0694: *
0695: * @param co If not null this object is used to return the information. If
0696: * null a new one is created and returned.
0697: *
0698: * @return The current tile's indexes (vertical and horizontal indexes).
0699: * */
0700: public final Point getTile(Point co) {
0701: if (co != null) {
0702: co.x = ctX;
0703: co.y = ctY;
0704: return co;
0705: } else {
0706: return new Point(ctX, ctY);
0707: }
0708: }
0709:
0710: /**
0711: * Returns the index of the current tile, relative to a standard scan-line
0712: * order.
0713: *
0714: * @return The current tile's index (starts at 0).
0715: * */
0716: public final int getTileIdx() {
0717: return ctY * ntX + ctX;
0718: }
0719:
0720: /**
0721: * Returns the horizontal coordinate of the upper-left corner of the
0722: * specified resolution in the given component of the current tile.
0723: *
0724: * @param c The component index.
0725: *
0726: * @param rl The resolution level index.
0727: * */
0728: public final int getResULX(int c, int rl) {
0729: int dl = mdl[c] - rl;
0730: if (dl < 0) {
0731: throw new IllegalArgumentException(
0732: "Requested resolution level"
0733: + " is not available for, at "
0734: + "least, one component in " + "tile: "
0735: + ctX + "x" + ctY);
0736: }
0737: int tx0 = (int) Math.max(px + ctX * ntW, ax);
0738: int tcx0 = (int) Math.ceil(tx0 / (double) getCompSubsX(c));
0739: return (int) Math.ceil(tcx0 / (double) (1 << dl));
0740: }
0741:
0742: /**
0743: * Returns the vertical coordinate of the upper-left corner of the
0744: * specified component in the given component of the current tile.
0745: *
0746: * @param c The component index.
0747: *
0748: * @param rl The resolution level index.
0749: * */
0750: public final int getResULY(int c, int rl) {
0751: int dl = mdl[c] - rl;
0752: if (dl < 0) {
0753: throw new IllegalArgumentException(
0754: "Requested resolution level"
0755: + " is not available for, at "
0756: + "least, one component in " + "tile: "
0757: + ctX + "x" + ctY);
0758: }
0759: int ty0 = (int) Math.max(py + ctY * ntH, ay);
0760: int tcy0 = (int) Math.ceil(ty0 / (double) getCompSubsY(c));
0761: return (int) Math.ceil(tcy0 / (double) (1 << dl));
0762: }
0763:
0764: /**
0765: * Returns the number of tiles in the horizontal and vertical directions.
0766: *
0767: * @param co If not null this object is used to return the information. If
0768: * null a new one is created and returned.
0769: *
0770: * @return The number of tiles in the horizontal (Point.x) and vertical
0771: * (Point.y) directions.
0772: * */
0773: public final Point getNumTiles(Point co) {
0774: if (co != null) {
0775: co.x = ntX;
0776: co.y = ntY;
0777: return co;
0778: } else {
0779: return new Point(ntX, ntY);
0780: }
0781: }
0782:
0783: /**
0784: * Returns the total number of tiles in the image.
0785: *
0786: * @return The total number of tiles in the image.
0787: * */
0788: public final int getNumTiles() {
0789: return ntX * ntY;
0790: }
0791:
0792: /**
0793: * Returns the subband tree, for the specified tile-component. This method
0794: * returns the root element of the subband tree structure, see Subband and
0795: * SubbandSyn. The tree comprises all the available resolution levels.
0796: *
0797: * <p>Note: this method is not able to return subband tree for a tile
0798: * different than the current one.</p>
0799: *
0800: * <p>The number of magnitude bits ('magBits' member variable) for each
0801: * subband is not initialized.</p>
0802: *
0803: * @param t The tile index
0804: *
0805: * @param c The index of the component, from 0 to C-1.
0806: *
0807: * @return The root of the tree structure.
0808: * */
0809: public final SubbandSyn getSynSubbandTree(int t, int c) {
0810: if (t != getTileIdx()) {
0811: throw new IllegalArgumentException(
0812: "Can not request subband"
0813: + " tree of a different tile"
0814: + " than the current one");
0815: }
0816: if (c < 0 || c >= nc) {
0817: throw new IllegalArgumentException(
0818: "Component index out of range");
0819: }
0820: return subbTrees[c];
0821: }
0822:
0823: /**
0824: * Creates a bit stream reader of the correct type that works on the
0825: * provided RandomAccessIO, with the special parameters from the parameter
0826: * list.
0827: *
0828: * @param in The RandomAccessIO source from which to read the bit stream.
0829: *
0830: * @param hd Header of the codestream.
0831: *
0832: * @param j2krparam The parameters applicable to the
0833: * bit stream read (other parameters may also be present).
0834: *
0835: * @param decSpec The decoder specifications
0836: *
0837: * @param cdstrInfo Whether or not to print information found in
0838: * codestream.
0839: *
0840: * @param hi Reference to the HeaderInfo instance.
0841: *
0842: * @exception IOException If an I/O error occurs while reading initial
0843: * data from the bit stream.
0844: * @exception IllegalArgumentException If an unrecognised bit stream
0845: * reader option is present.
0846: * */
0847: public static BitstreamReaderAgent createInstance(
0848: RandomAccessIO in, HeaderDecoder hd,
0849: J2KImageReadParamJava j2krparam, DecoderSpecs decSpec,
0850: boolean cdstrInfo, HeaderInfo hi) throws IOException {
0851: // Check header length
0852: /*
0853: if (in.getPos() != hd.getTotalHeaderLength() + hd.initPos) {
0854: throw new IllegalArgumentException("Invalid header length");
0855: }
0856: */
0857: return new FileBitstreamReaderAgent(hd, in, decSpec, j2krparam,
0858: cdstrInfo, hi);
0859: }
0860:
0861: /**
0862: * Returns the parameters that are used in this class and implementing
0863: * classes. It returns a 2D String array. Each of the 1D arrays is for a
0864: * different option, and they have 3 elements. The first element is the
0865: * option name, the second one is the synopsis and the third one is a long
0866: * description of what the parameter is. The synopsis or description may
0867: * be 'null', in which case it is assumed that there is no synopsis or
0868: * description of the option, respectively. Null may be returned if no
0869: * options are supported.
0870: *
0871: * @return the options name, their synopsis and their explanation, or null
0872: * if no options are supported.
0873: * */
0874: public static String[][] getParameterInfo() {
0875: return pinfo;
0876: }
0877:
0878: /**
0879: * Returns the precinct partition width for the specified tile-component
0880: * and (tile-component) resolution level.
0881: *
0882: * @param t the tile index
0883: *
0884: * @param c The index of the component (between 0 and N-1)
0885: *
0886: * @param rl The resolution level, from 0 to L.
0887: *
0888: * @return the precinct partition width for the specified component,
0889: * resolution level and tile.
0890: * */
0891: public final int getPPX(int t, int c, int rl) {
0892: return decSpec.pss.getPPX(t, c, rl);
0893: }
0894:
0895: /**
0896: * Returns the precinct partition height for the specified tile-component
0897: * and (tile-component) resolution level.
0898: *
0899: * @param t The tile index
0900: *
0901: * @param c The index of the component (between 0 and N-1)
0902: *
0903: * @param rl The resolution level, from 0 to L.
0904: *
0905: * @return The precinct partition height in the specified component, for
0906: * the specified resolution level, for the current tile.
0907: * */
0908: public final int getPPY(int t, int c, int rl) {
0909: return decSpec.pss.getPPY(t, c, rl);
0910: }
0911:
0912: /**
0913: * Initialises subbands fields, such as code-blocks dimension and number
0914: * of magnitude bits, in the subband tree. The nominal code-block
0915: * width/height depends on the precincts dimensions if used. The way the
0916: * number of magnitude bits is computed depends on the quantization type
0917: * (reversible, derived, expounded).
0918: *
0919: * @param c The component index
0920: *
0921: * @param sb The subband tree to be initialised.
0922: * */
0923: protected void initSubbandsFields(int c, SubbandSyn sb) {
0924: int t = getTileIdx();
0925: int rl = sb.resLvl;
0926: int cbw, cbh;
0927:
0928: cbw = decSpec.cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t,
0929: c);
0930: cbh = decSpec.cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t,
0931: c);
0932:
0933: if (!sb.isNode) {
0934: if (hd.precinctPartitionUsed()) {
0935: // The precinct partition is used
0936: int ppxExp, ppyExp, cbwExp, cbhExp;
0937:
0938: // Get exponents
0939: ppxExp = MathUtil.log2(getPPX(t, c, rl));
0940: ppyExp = MathUtil.log2(getPPY(t, c, rl));
0941: cbwExp = MathUtil.log2(cbw);
0942: cbhExp = MathUtil.log2(cbh);
0943:
0944: switch (sb.resLvl) {
0945: case 0:
0946: sb.nomCBlkW = (cbwExp < ppxExp ? (1 << cbwExp)
0947: : (1 << ppxExp));
0948: sb.nomCBlkH = (cbhExp < ppyExp ? (1 << cbhExp)
0949: : (1 << ppyExp));
0950: break;
0951:
0952: default:
0953: sb.nomCBlkW = (cbwExp < ppxExp - 1 ? (1 << cbwExp)
0954: : (1 << (ppxExp - 1)));
0955: sb.nomCBlkH = (cbhExp < ppyExp - 1 ? (1 << cbhExp)
0956: : (1 << (ppyExp - 1)));
0957: break;
0958: }
0959: } else {
0960: sb.nomCBlkW = cbw;
0961: sb.nomCBlkH = cbh;
0962: }
0963:
0964: // Number of code-blocks
0965: if (sb.numCb == null)
0966: sb.numCb = new Point();
0967: if (sb.w == 0 || sb.h == 0) {
0968: sb.numCb.x = 0;
0969: sb.numCb.y = 0;
0970: } else {
0971: int cb0x = getCbULX();
0972: int cb0y = getCbULY();
0973: int tmp;
0974:
0975: // Projects code-block partition origin to subband. Since the
0976: // origin is always 0 or 1, it projects to the low-pass side
0977: // (throught the ceil operator) as itself (i.e. no change) and
0978: // to the high-pass side (through the floor operator) as 0,
0979: // always.
0980: int acb0x = cb0x;
0981: int acb0y = cb0y;
0982:
0983: switch (sb.sbandIdx) {
0984: case Subband.WT_ORIENT_LL:
0985: // No need to project since all low-pass => nothing to do
0986: break;
0987: case Subband.WT_ORIENT_HL:
0988: acb0x = 0;
0989: break;
0990: case Subband.WT_ORIENT_LH:
0991: acb0y = 0;
0992: break;
0993: case Subband.WT_ORIENT_HH:
0994: acb0x = 0;
0995: acb0y = 0;
0996: break;
0997: default:
0998: throw new Error("Internal JJ2000 error");
0999: }
1000: if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0) {
1001: throw new IllegalArgumentException(
1002: "Invalid code-blocks "
1003: + "partition origin or "
1004: + "image offset in the "
1005: + "reference grid.");
1006: }
1007:
1008: // NOTE: when calculating "floor()" by integer division the
1009: // dividend and divisor must be positive, we ensure that by
1010: // adding the divisor to the dividend and then substracting 1
1011: // to the result of the division
1012:
1013: tmp = sb.ulcx - acb0x + sb.nomCBlkW;
1014: sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW
1015: - (tmp / sb.nomCBlkW - 1);
1016:
1017: tmp = sb.ulcy - acb0y + sb.nomCBlkH;
1018: sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH
1019: - (tmp / sb.nomCBlkH - 1);
1020: }
1021:
1022: if (derived[c]) {
1023: sb.magbits = gb[c]
1024: + (params[c].exp[0][0] - (mdl[c] - sb.level))
1025: - 1;
1026: } else {
1027: sb.magbits = gb[c]
1028: + params[c].exp[sb.resLvl][sb.sbandIdx] - 1;
1029: }
1030: } else {
1031: initSubbandsFields(c, (SubbandSyn) sb.getLL());
1032: initSubbandsFields(c, (SubbandSyn) sb.getHL());
1033: initSubbandsFields(c, (SubbandSyn) sb.getLH());
1034: initSubbandsFields(c, (SubbandSyn) sb.getHH());
1035: }
1036: }
1037:
1038: /**
1039: * Returns the image resolution level to reconstruct from the
1040: * codestream. This value cannot be computed before every main and tile
1041: * headers are read.
1042: *
1043: * @return The image resolution level
1044: * */
1045: public int getImgRes() {
1046: return targetRes;
1047: }
1048:
1049: /**
1050: * Return the target decoding rate in bits per pixel.
1051: *
1052: * @return Target decoding rate in bpp.
1053: * */
1054: public float getTargetRate() {
1055: return trate;
1056: }
1057:
1058: /**
1059: * Return the actual decoding rate in bits per pixel.
1060: *
1061: * @return Actual decoding rate in bpp.
1062: * */
1063: public float getActualRate() {
1064: arate = anbytes * 8f / hd.getMaxCompImgWidth()
1065: / hd.getMaxCompImgHeight();
1066: return arate;
1067: }
1068:
1069: /**
1070: * Return the target number of read bytes.
1071: *
1072: * @return Target decoding rate in bytes.
1073: * */
1074: public int getTargetNbytes() {
1075: return tnbytes;
1076: }
1077:
1078: /**
1079: * Return the actual number of read bytes.
1080: *
1081: * @return Actual decoding rate in bytes.
1082: * */
1083: public int getActualNbytes() {
1084: return anbytes;
1085: }
1086:
1087: /** Returns the horizontal offset of tile partition */
1088: public int getTilePartULX() {
1089: return hd.getTilingOrigin(null).x;
1090: }
1091:
1092: /** Returns the vertical offset of tile partition */
1093: public int getTilePartULY() {
1094: return hd.getTilingOrigin(null).y;
1095: }
1096:
1097: /** Returns the nominal tile width */
1098: public int getNomTileWidth() {
1099: return hd.getNomTileWidth();
1100: }
1101:
1102: /** Returns the nominal tile height */
1103: public int getNomTileHeight() {
1104: return hd.getNomTileHeight();
1105: }
1106: }
|