/*
* CVS identifier:
*
* $Id: ROIDeScaler.java,v 1.39 2001/10/24 12:02:51 grosbois Exp $
*
*
* Class: ROIDeScaler
*
* Description: The class taking care of de-scaling ROI coeffs.
*
*
*
* COPYRIGHT:
*
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
*
* Copyright (c) 1999/2000 JJ2000 Partners.
* */
using System;
using CSJ2K.j2k.quantization.dequantizer;
using CSJ2K.j2k.codestream.reader;
using CSJ2K.j2k.wavelet.synthesis;
using CSJ2K.j2k.codestream;
using CSJ2K.j2k.entropy;
using CSJ2K.j2k.decoder;
using CSJ2K.j2k.image;
using CSJ2K.j2k.util;
using CSJ2K.j2k.io;
using CSJ2K.j2k;
namespace CSJ2K.j2k.roi
{
/// This class takes care of the de-scaling of ROI coefficients. The de-scaler
/// works on a tile basis and any mask that is generated is for the current
/// mask only
///
/// Default implementations of the methods in 'MultiResImgData' are provided
/// through the 'MultiResImgDataAdapter' abstract class.
///
/// Sign-magnitude representation is used (instead of two's complement) for
/// the output data. The most significant bit is used for the sign (0 if
/// positive, 1 if negative). Then the magnitude of the quantized coefficient
/// is stored in the next most significat bits. The most significant magnitude
/// bit corresponds to the most significant bit-plane and so on.
///
///
public class ROIDeScaler:MultiResImgDataAdapter, CBlkQuantDataSrcDec
{
/// Returns the horizontal code-block partition origin. Allowable values
/// are 0 and 1, nothing else.
///
///
virtual public int CbULX
{
get
{
return src.CbULX;
}
}
/// Returns the vertical code-block partition origin. Allowable values are
/// 0 and 1, nothing else.
///
///
virtual public int CbULY
{
get
{
return src.CbULY;
}
}
/// Returns the parameters that are used in this class and implementing
/// classes. It returns a 2D String array. Each of the 1D arrays is for a
/// different option, and they have 3 elements. The first element is the
/// option name, the second one is the synopsis and the third one is a long
/// description of what the parameter is. The synopsis or description may
/// be 'null', in which case it is assumed that there is no synopsis or
/// description of the option, respectively. Null may be returned if no
/// options are supported.
///
///
/// the options name, their synopsis and their explanation, or null
/// if no options are supported.
///
///
public static System.String[][] ParameterInfo
{
get
{
return pinfo;
}
}
/// The MaxShiftSpec containing the scaling values for all tile-components
///
///
private MaxShiftSpec mss;
/// The prefix for ROI decoder options: 'R'
public const char OPT_PREFIX = 'R';
/// The list of parameters that is accepted by the entropy decoders. They
/// start with 'R'.
///
//UPGRADE_NOTE: Final was removed from the declaration of 'pinfo'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private static readonly System.String[][] pinfo = new System.String[][]{new System.String[]{"Rno_roi", null, "This argument makes sure that the no ROI de-scaling is performed. " + "Decompression is done like there is no ROI in the image", null}};
/// The entropy decoder from where to get the compressed data (the source)
///
///
private CBlkQuantDataSrcDec src;
/// Constructor of the ROI descaler, takes EntropyDEcoder as source of data
/// to de-scale.
///
///
/// The EntropyDecoder that is the source of data.
///
///
/// The MaxShiftSpec containing the scaling values for all
/// tile-components
///
///
public ROIDeScaler(CBlkQuantDataSrcDec src, MaxShiftSpec mss):base(src)
{
this.src = src;
this.mss = mss;
}
/// Returns the subband tree, for the specified tile-component. This method
/// returns the root element of the subband tree structure, see Subband and
/// SubbandSyn. The tree comprises all the available resolution levels.
///
/// The number of magnitude bits ('magBits' member variable) for each
/// subband is not initialized.
///
///
/// The index of the tile, from 0 to T-1.
///
///
/// The index of the component, from 0 to C-1.
///
///
/// The root of the tree structure.
///
///
public override SubbandSyn getSynSubbandTree(int t, int c)
{
return src.getSynSubbandTree(t, c);
}
/// Returns the specified code-block in the current tile for the specified
/// component, as a copy (see below).
///
/// The returned code-block may be progressive, which is indicated by
/// the 'progressive' variable of the returned 'DataBlk' object. If a
/// code-block is progressive it means that in a later request to this
/// method for the same code-block it is possible to retrieve data which is
/// a better approximation, since meanwhile more data to decode for the
/// code-block could have been received. If the code-block is not
/// progressive then later calls to this method for the same code-block
/// will return the exact same data values.
///
/// The data returned by this method is always a copy of the internal
/// data of this object, if any, and it can be modified "in place" without
/// any problems after being returned. The 'offset' of the returned data is
/// 0, and the 'scanw' is the same as the code-block width. See the
/// 'DataBlk' class.
///
/// The 'ulx' and 'uly' members of the returned 'DataBlk' object contain
/// the coordinates of the top-left corner of the block, with respect to
/// the tile, not the subband.
///
///
/// The component for which to return the next code-block.
///
///
/// The vertical index of the code-block to return, in the
/// specified subband.
///
///
/// The horizontal index of the code-block to return, in the
/// specified subband.
///
///
/// The subband in which the code-block to return is.
///
///
/// If non-null this object will be used to return the new
/// code-block. If null a new one will be allocated and returned. If the
/// "data" array of the object is non-null it will be reused, if possible,
/// to return the data.
///
///
/// The next code-block in the current tile for component 'c', or
/// null if all code-blocks for the current tile have been returned.
///
///
///
///
///
public virtual DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
{
return getInternCodeBlock(c, m, n, sb, cblk);
}
/// Returns the specified code-block in the current tile for the specified
/// component (as a reference or copy).
///
/// The returned code-block may be progressive, which is indicated by
/// the 'progressive' variable of the returned 'DataBlk' object. If a
/// code-block is progressive it means that in a later request to this
/// method for the same code-block it is possible to retrieve data which is
/// a better approximation, since meanwhile more data to decode for the
/// code-block could have been received. If the code-block is not
/// progressive then later calls to this method for the same code-block
/// will return the exact same data values.
///
/// The data returned by this method can be the data in the internal
/// buffer of this object, if any, and thus can not be modified by the
/// caller. The 'offset' and 'scanw' of the returned data can be
/// arbitrary. See the 'DataBlk' class.
///
/// The 'ulx' and 'uly' members of the returned 'DataBlk' object contain
/// the coordinates of the top-left corner of the block, with respect to
/// the tile, not the subband.
///
///
/// The component for which to return the next code-block.
///
///
/// The vertical index of the code-block to return, in the
/// specified subband.
///
///
/// The horizontal index of the code-block to return, in the
/// specified subband.
///
///
/// The subband in which the code-block to return is.
///
///
/// If non-null this object will be used to return the new
/// code-block. If null a new one will be allocated and returned. If the
/// "data" array of the object is non-null it will be reused, if possible,
/// to return the data.
///
///
/// The requested code-block in the current tile for component 'c'.
///
///
///
///
///
public virtual DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
{
int i, j, k, wrap; // mi removed
int ulx, uly, w, h;
int[] data; // local copy of quantized data
int tmp;
//int limit;
// Get data block from entropy decoder
cblk = src.getInternCodeBlock(c, m, n, sb, cblk);
// If there are no ROIs in the tile, Or if we already got all blocks
bool noRoiInTile = false;
if (mss == null || mss.getTileCompVal(TileIdx, c) == null)
noRoiInTile = true;
if (noRoiInTile || cblk == null)
{
return cblk;
}
data = (int[]) cblk.Data;
ulx = cblk.ulx;
uly = cblk.uly;
w = cblk.w;
h = cblk.h;
// Scale coefficients according to magnitude. If the magnitude of a
// coefficient is lower than 2 pow 31-magbits then it is a background
// coeff and should be up-scaled
int boost = ((System.Int32) mss.getTileCompVal(TileIdx, c));
int mask = ((1 << sb.magbits) - 1) << (31 - sb.magbits);
int mask2 = (~ mask) & 0x7FFFFFFF;
wrap = cblk.scanw - w;
i = cblk.offset + cblk.scanw * (h - 1) + w - 1;
for (j = h; j > 0; j--)
{
for (k = w; k > 0; k--, i--)
{
tmp = data[i];
if ((tmp & mask) == 0)
{
// BG
data[i] = (tmp & unchecked((int) 0x80000000)) | (tmp << boost);
}
else
{
// ROI
if ((tmp & mask2) != 0)
{
// decoded more than magbits bit-planes, set
// quantization mid-interval approx. bit just after
// the magbits.
data[i] = (tmp & (~ mask2)) | (1 << (30 - sb.magbits));
}
}
}
i -= wrap;
}
return cblk;
}
/// Creates a ROIDeScaler object. The information needed to create the
/// object is the Entropy decoder used and the parameters.
///
///
/// The source of data that is to be descaled
///
///
/// The parameter list (or options).
///
///
/// The decoding specifications
///
///
/// If an error occurs while parsing
/// the options in 'pl'
///
///
public static ROIDeScaler createInstance(CBlkQuantDataSrcDec src, ParameterList pl, DecoderSpecs decSpec)
{
System.String noRoi;
//int i;
// Check parameters
pl.checkList(OPT_PREFIX, CSJ2K.j2k.util.ParameterList.toNameArray(pinfo));
// Check if no_roi specified in command line or no roi signalled
// in bit stream
noRoi = pl.getParameter("Rno_roi");
if (noRoi != null || decSpec.rois == null)
{
// no_roi specified in commandline!
return new ROIDeScaler(src, null);
}
return new ROIDeScaler(src, decSpec.rois);
}
}
}