📄 forwwtfull.java
字号:
}
if (sb2.gOrient == Subband.WT_ORIENT_LL) {
// Only low-pass steps left, no need to continue
// checking
break;
}
sb2 = sb2.getParent();
} while (sb2 != null);
// There is at least a high-pass step on the vertical
// decomposition => project to 0
apoy = 0;
break;
case Subband.WT_ORIENT_HH:
// There is at least a high-pass step on the horiz. and
// vertical decomposition => project to 0
apox = 0;
apoy = 0;
break;
default:
throw new Error("Internal JJ2000 error");
}
// NOTE: when calculating "floor()" by integer division the
// dividend and divisor must be positive, we ensure that by adding
// the divisor to the dividend and then substracting 1 to the
// result of the division
co.x = (sb.ulcx+sb.w-apox+sb.nomCBlkW-1) /
sb.nomCBlkW -((sb.ulcx-apox+sb.nomCBlkW)/sb.nomCBlkW-1);
co.y = (sb.ulcy+sb.h-apoy+sb.nomCBlkH-1) /
sb.nomCBlkH -((sb.ulcy-apoy+sb.nomCBlkH)/sb.nomCBlkH-1);
}
else {
co.x = 0;
co.y = 0;
}
return co;
}
/**
* Returns the next code-block in the current tile for the specified
* component. The order in which code-blocks are returned is not
* specified. However each code-block is returned only once and all
* code-blocks will be returned if the method is called 'N' times, where
* 'N' is the number of code-blocks in the tile. After all the code-blocks
* have been returned for the current tile calls to this method will
* return 'null'.
*
* <p>When changing the current tile (through 'setTile()' or 'nextTile()')
* this method will always return the first code-block, as if this method
* was never called before for the new current tile.</p>
*
* <p>The data returned by this method is the data in the internal buffer
* of this object, and thus can not be modified by the caller. The
* 'offset' and 'scanw' of the returned data have, in general, some
* non-zero value. The 'magbits' of the returned data is not set by this
* method and should be ignored. See the 'CBlkWTData' class.</p>
*
* <p>The 'ulx' and 'uly' members of the returned 'CBlkWTData' object
* contain the coordinates of the top-left corner of the block, with
* respect to the tile, not the subband.</p>
*
* @param c The component for which to return the next code-block.
*
* @param cblk If non-null this object will be used to return the new
* code-block. If null a new one will be allocated and returned.
*
* @return The next code-block in the current tile for component 'n', or
* null if all code-blocks for the current tile have been returned.
*
* @see CBlkWTData
* */
public CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk) {
int cbm,cbn,cn,cm;
int apox, apoy;
SubbandAn sb;
intData = (filters.getWTDataType(tIdx,c)==DataBlk.TYPE_INT);
//If the source image has not been decomposed
if(decomposedComps[c] == null) {
int k,w,h;
DataBlk bufblk;
Object dst_data;
w = getCompWidth(c);
h = getCompHeight(c);
//Get the source image data
if(intData){
decomposedComps[c] = new DataBlkInt(0,0,w,h);
bufblk = new DataBlkInt();
}
else {
decomposedComps[c] = new DataBlkFloat(0,0,w,h);
bufblk = new DataBlkFloat();
}
// Get data from source line by line (this diminishes the memory
// requirements on the data source)
dst_data = decomposedComps[c].getData();
bufblk.ulx = 0;
bufblk.w = w;
bufblk.h = 1;
for (k=0; k<h; k++) {
bufblk.uly = k;
bufblk.ulx = 0;
bufblk = src.getInternCompData(bufblk,c);
System.arraycopy(bufblk.getData(),bufblk.offset,
dst_data,k*w,w);
}
//Decompose source image
waveletTreeDecomposition(decomposedComps[c],
getSubbandTree(tIdx,c),c);
// Make the first subband the current one
currentSubband[c] = getNextSubband(c);
lastn[c] = -1;
lastm[c] = 0;
}
// Get the next code-block to "send"
do {
// Calculate number of code-blocks in current subband
ncblks = getNumCodeBlocks(currentSubband[c],ncblks);
// Goto next code-block
lastn[c]++;
if (lastn[c] == ncblks.x) { // Got to end of this row of
// code-blocks
lastn[c] = 0;
lastm[c]++;
}
if (lastm[c] < ncblks.y) {
// Not past the last code-block in the subband, we can return
// this code-block
break;
}
// If we get here we already sent all code-blocks in this subband,
// goto next subband
currentSubband[c] = getNextSubband(c);
lastn[c] = -1;
lastm[c] = 0;
if ( currentSubband[c] == null ) {
// We don't need the transformed data any more (a priori)
decomposedComps[c] = null;
// All code-blocks from all subbands in the current
// tile have been returned so we return a null
// reference
return null;
}
// Loop to find the next code-block
} while (true);
// Project code-block partition origin to subband. Since the origin is
// always 0 or 1, it projects to the low-pass side (throught the ceil
// operator) as itself (i.e. no change) and to the high-pass side
// (through the floor operator) as 0, always.
apox = pox;
apoy = poy;
Subband sb2;
switch (currentSubband[c].gOrient) {
case Subband.WT_ORIENT_LL:
// No need to project since all low-pass => nothing to do
break;
case Subband.WT_ORIENT_HL:
// There is at least a high-pass step on the horizontal
// decomposition => project to 0
apox = 0;
// We need to find out if there has been a high-pass step on the
// vertical decomposition
sb2 = currentSubband[c];
do {
if (sb2.orientation == Subband.WT_ORIENT_HH ||
sb2.orientation == Subband.WT_ORIENT_LH) {
// Vertical high-pass step => project to 0 and done
apoy = 0;
break;
}
if (sb2.gOrient == Subband.WT_ORIENT_LL) {
// Only low-pass steps left, no need to continue checking
break;
}
sb2 = sb2.getParent();
} while (sb2 != null);
break;
case Subband.WT_ORIENT_LH:
// We need to find out if there has been a high-pass step on the
// horizontal decomposition
sb2 = currentSubband[c];
do {
if (sb2.orientation == Subband.WT_ORIENT_HH ||
sb2.orientation == Subband.WT_ORIENT_HL) {
// Horizontal high-pass step => project to 0 and done
apox = 0;
break;
}
if (sb2.gOrient == Subband.WT_ORIENT_LL) {
// Only low-pass steps left, no need to continue checking
break;
}
sb2 = sb2.getParent();
} while (sb2 != null);
// There is at least a high-pass step on the vertical
// decomposition => project to 0
apoy = 0;
break;
case Subband.WT_ORIENT_HH:
// There is at least a high-pass step on the horiz. and vertical
// decomposition => project to 0
apox = 0;
apoy = 0;
break;
default:
throw new Error("Internal JJ2000 error");
}
// Initialize output code-block
if ( cblk==null ) {
if (intData) {
cblk = new CBlkWTDataInt();
}
else {
cblk = new CBlkWTDataFloat();
}
}
cbn = lastn[c];
cbm = lastm[c];
sb = currentSubband[c];
cblk.n = cbn;
cblk.m = cbm;
cblk.sb = sb;
// Calculate the indexes of first code-block in subband w/respect to
// the partitioning origin, to then calculate the position and size
// NOTE: when calculating "floor()" by integer division the dividend
// and divisor must be positive, we ensure that by adding the divisor
// to the dividend and then substracting 1 to the result of the
// division
cn = (sb.ulcx-apox+sb.nomCBlkW)/sb.nomCBlkW-1;
cm = (sb.ulcy-apoy+sb.nomCBlkH)/sb.nomCBlkH-1;
if (cbn == 0) { // Left-most code-block, starts where subband starts
cblk.ulx = sb.ulx;
}
else {
// Calculate starting canvas coordinate and convert to subb. coords
cblk.ulx = (cn+cbn)*sb.nomCBlkW - (sb.ulcx-apox) + sb.ulx;
}
if (cbm == 0) { // Bottom-most code-block, starts where subband starts
cblk.uly = sb.uly;
}
else {
cblk.uly = (cm+cbm)*sb.nomCBlkH - (sb.ulcy-apoy) + sb.uly;
}
if (cbn < ncblks.x-1) {
// Calculate where next code-block starts => width
cblk.w = (cn+cbn+1)*sb.nomCBlkW - (sb.ulcx-apox) + sb.ulx -
cblk.ulx;
}
else { // Right-most code-block, ends where subband ends
cblk.w = sb.ulx+sb.w-cblk.ulx;
}
if (cbm < ncblks.y-1) {
// Calculate where next code-block starts => height
cblk.h = (cm+cbm+1)*sb.nomCBlkH - (sb.ulcy-apoy) + sb.uly -
cblk.uly;
}
else { // Bottom-most code-block, ends where subband ends
cblk.h = sb.uly+sb.h-cblk.uly;
}
cblk.wmseScaling = 1f;
// Since we are in getNextInternCodeBlock() we can return a
// reference to the internal buffer, no need to copy. Just initialize
// the 'offset' and 'scanw'
cblk.offset = cblk.uly*decomposedComps[c].w+cblk.ulx;
cblk.scanw = decomposedComps[c].w;
// For the data just put a reference to our buffer
cblk.setData(decomposedComps[c].getData());
// Return code-block
return cblk;
}
/**
* Returns the next code-block in the current tile for the specified
* component, as a copy (see below). The order in which code-blocks are
* returned is not specified. However each code-block is returned only
* once and all code-blocks will be returned if the method is called 'N'
* times, where 'N' is the number of code-blocks in the tile. After all
* the code-blocks have been returned for the current tile calls to this
* method will return 'null'.
*
* <p>When changing the current tile (through 'setTile()' or 'nextTile()')
* this method will always return the first code-block, as if this method
* was never called before for the new current tile.</p>
*
* <p>The data returned by this method is always a copy of the internal
* data of this object, 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. The 'magbits'
* of the returned data is not set by this method and should be
* ignored. See the 'CBlkWTData' class.</p>
*
* <p>The 'ulx' and 'uly' members of the returned 'CBlkWTData' object
* contain the coordinates of the top-left corner of the block, with
* respect to the tile, not the subband.</p>
*
* @param c The component for which to return the next code-block.
*
* @param cblk 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.
*
* @return The next code-block in the current tile for component 'c', or
* null if all code-blocks for the current tile have been returned.
*
* @see CBlkWTData
* */
public CBlkWTData getNextCodeBlock(int c, CBlkWTData cblk) {
// We can not directly use getNextInternCodeBlock() since that returns
// a reference to the internal buffer, we have to copy that data
int j,k;
int w;
Object dst_data; // a int[] or float[] object
int[] dst_data_int;
float[] dst_data_float;
Object src_data; // a int[] or float[] object
intData = (filters.getWTDataType(tIdx,c)==DataBlk.TYPE_INT);
dst_data = null;
// Cache the data array, if any
if (cblk != null) {
dst_data = cblk.getData();
}
// Get the next code-block
cblk = getNextInternCodeBlock(c,cblk);
if (cblk == null) {
return null; // No more code-blocks in current tile for component
// c
}
// Ensure size of output buffer
if (intData) { // int data
dst_data_int = (int[]) dst_data;
if (dst_data_int == null || dst_data_int.length < cblk.w*cblk.h) {
dst_data = new int[cblk.w*cblk.h];
}
}
else { // float data
dst_data_float = (float[]) dst_data;
if (dst_data_float == null ||
dst_data_float.length < cblk.w*cblk.h) {
dst_data = new float[cblk.w*cblk.h];
}
}
// Copy data line by line
src_data = cblk.getData();
w = cblk.w;
for (j = w*(cblk.h-1), k = cblk.offset+(cblk.h-1)*cblk.scanw;
j >= 0; j -= w, k -= cblk.scanw) {
System.arraycopy(src_data,k,dst_data,j,w);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -