public override CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk)
{
int cbm, cbn, cn, cm;
int acb0x, acb0y;
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;
System.Object dst_data;
w = getTileCompWidth(tIdx, c);
h = getTileCompHeight(tIdx, 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].Data;
int lstart = getCompULX(c);
bufblk.ulx = lstart;
bufblk.w = w;
bufblk.h = 1;
int kk = getCompULY(c);
for (k = 0; k < h; k++, kk++)
{
bufblk.uly = kk;
bufblk.ulx = lstart;
bufblk = src.getInternCompData(bufblk, c);
// CONVERSION PROBLEM?
Array.Copy((System.Array)bufblk.Data, bufblk.offset, (System.Array)dst_data, k * w, w);
}
//Decompose source image
waveletTreeDecomposition(decomposedComps[c], getAnSubbandTree(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 = currentSubband[c].numCb;
// 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.
acb0x = cb0x;
acb0y = cb0y;
switch (currentSubband[c].sbandIdx)
{
case Subband.WT_ORIENT_LL:
// No need to project since all low-pass => nothing to do
break;
case Subband.WT_ORIENT_HL:
acb0x = 0;
break;
case Subband.WT_ORIENT_LH:
acb0y = 0;
break;
case Subband.WT_ORIENT_HH:
acb0x = 0;
acb0y = 0;
break;
default:
throw new System.InvalidOperationException("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 with 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 - acb0x + sb.nomCBlkW) / sb.nomCBlkW - 1;
cm = (sb.ulcy - acb0y + 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 - acb0x) + 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 - acb0y) + sb.uly;
}
if (cbn < ncblks.x - 1)
{
// Calculate where next code-block starts => width
cblk.w = (cn + cbn + 1) * sb.nomCBlkW - (sb.ulcx - acb0x) + 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 - acb0y) + 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.Data = decomposedComps[c].Data;
// Return code-block
return cblk;
}