/// <summary> This function gets a datablk from the entropy coder. The sample sin the
        /// block, which consists of  the quantized coefficients from the quantizer,
        /// are scaled by the values given for any ROIs specified.
        ///
        /// <p>The function calls on a ROIMaskGenerator to get the mask for scaling
        /// the coefficients in the current block.</p>
        ///
        /// </summary>
        /// <param name="c">The component for which to return the next code-block.
        ///
        /// </param>
        /// <param name="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.
        ///
        /// </param>
        /// <returns> The next code-block in the current tile for component 'n', or
        /// null if all code-blocks for the current tile have been returned.
        ///
        /// </returns>
        /// <seealso cref="CBlkWTData">
        ///
        /// </seealso>
        public virtual CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk)
        {
            int        mi, i, j, k, wrap;
            int        ulx, uly, w, h;
            DataBlkInt mask = roiMask; // local copy of mask

            int[]     maskData;        // local copy of mask data
            int[]     data;            // local copy of quantized data
            int       tmp;
            int       bitMask = 0x7FFFFFFF;
            SubbandAn root, sb;
            int       maxBits = 0;       // local copy
            bool      roiInTile;
            bool      sbInMask;
            int       nROIcoeff = 0;

            // Get codeblock's data from quantizer
            cblk = src.getNextCodeBlock(c, cblk);

            // If there is no ROI in the image, or if we already got all
            // code-blocks
            if (!roi || cblk == null)
            {
                return(cblk);
            }

            data     = (int[])cblk.Data;
            sb       = cblk.sb;
            ulx      = cblk.ulx;
            uly      = cblk.uly;
            w        = cblk.w;
            h        = cblk.h;
            sbInMask = (sb.resLvl <= useStartLevel);

            // Check that there is an array for the mask and set it to zero
            maskData = mask.DataInt;             // local copy of mask data
            if (maskData == null || w * h > maskData.Length)
            {
                maskData     = new int[w * h];
                mask.DataInt = maskData;
            }
            else
            {
                for (i = w * h - 1; i >= 0; i--)
                {
                    maskData[i] = 0;
                }
            }
            mask.ulx = ulx;
            mask.uly = uly;
            mask.w   = w;
            mask.h   = h;

            // Get ROI mask from generator
            root      = src.getAnSubbandTree(tIdx, c);
            maxBits   = maxMagBits[tIdx][c];
            roiInTile = mg.getROIMask(mask, root, maxBits, c);

            // If there is no ROI in this tile, return the code-block untouched
            if (!roiInTile && (!sbInMask))
            {
                cblk.nROIbp = 0;
                return(cblk);
            }

            // Update field containing the number of ROI magnitude bit-planes
            cblk.nROIbp = cblk.magbits;

            // If the entire subband belongs to the ROI mask, The code-block is
            // set to belong entirely to the ROI with the highest scaling value
            if (sbInMask)
            {
                // Scale the wmse so that instead of scaling the coefficients, the
                // wmse is scaled.
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                cblk.wmseScaling *= (float)(1 << (maxBits << 1));
                cblk.nROIcoeff    = w * h;
                return(cblk);
            }

            // In 'block aligned' mode, the code-block is set to belong entirely
            // to the ROI with the highest scaling value if one coefficient, at
            // least, belongs to the ROI
            if (blockAligned)
            {
                wrap = cblk.scanw - w;
                mi   = h * w - 1;
                i    = cblk.offset + cblk.scanw * (h - 1) + w - 1;
                int nroicoeff = 0;
                for (j = h; j > 0; j--)
                {
                    for (k = w - 1; k >= 0; k--, i--, mi--)
                    {
                        if (maskData[mi] != 0)
                        {
                            nroicoeff++;
                        }
                    }
                    i -= wrap;
                }
                if (nroicoeff != 0)
                {
                    // Include the subband
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    cblk.wmseScaling *= (float)(1 << (maxBits << 1));
                    cblk.nROIcoeff    = w * h;
                }
                return(cblk);
            }

            // Scale background coefficients
            bitMask = (((1 << cblk.magbits) - 1) << (31 - cblk.magbits));
            wrap    = cblk.scanw - w;
            mi      = h * w - 1;
            i       = cblk.offset + cblk.scanw * (h - 1) + w - 1;
            for (j = h; j > 0; j--)
            {
                for (k = w; k > 0; k--, i--, mi--)
                {
                    tmp = data[i];
                    if (maskData[mi] != 0)
                    {
                        // ROI coeff. We need to erase fractional bits to ensure
                        // that they do not conflict with BG coeffs. This is only
                        // strictly necessary for ROI coeffs. which non-fractional
                        // magnitude is zero, but much better BG quality can be
                        // achieved if done if reset to zero since coding zeros is
                        // much more efficient (the entropy coder knows nothing
                        // about ROI and cannot avoid coding the ROI fractional
                        // bits, otherwise this would not be necessary).
                        data[i] = (unchecked ((int)0x80000000) & tmp) | (tmp & bitMask);
                        nROIcoeff++;
                    }
                    else
                    {
                        // BG coeff. it is not necessary to erase fractional bits
                        data[i] = (unchecked ((int)0x80000000) & tmp) | ((tmp & 0x7FFFFFFF) >> maxBits);
                    }
                }
                i -= wrap;
            }

            // Modify the number of significant bit-planes in the code-block
            cblk.magbits += maxBits;

            // Store the number of ROI coefficients present in the code-block
            cblk.nROIcoeff = nROIcoeff;

            return(cblk);
        }