int _jxr_r_TILE_DC(jxr_image_t image, struct rbitstream*str,
                   unsigned tx, unsigned ty)
{
    unsigned mx, my;
    unsigned mb_height;
    unsigned mb_width;
    unsigned char s0, s1, s2, s3;
    DEBUG("START TILE_DC at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));

    /* TILE_STARTCODE == 1 */
    s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
    s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
    s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
    s3 = _jxr_rbitstream_uint8(str); /* reserved */
    DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);

    _jxr_r_TILE_HEADER_DC(image, str, 0 /* alpha */, tx, ty);
    if (ALPHACHANNEL_FLAG(image))
        _jxr_r_TILE_HEADER_DC(image->alpha, str, 1, tx, ty);


    /* Now form and write out all the compressed data for the
    tile. This involves scanning the macroblocks, and the
    blocks within the macroblocks, generating bits as we go. */

    mb_height = EXTENDED_HEIGHT_BLOCKS(image);
    mb_width = EXTENDED_WIDTH_BLOCKS(image);

    if (TILING_FLAG(image)) {
        mb_height = image->tile_row_height[ty];
        mb_width = image->tile_column_width[tx];
    }

    for (my = 0 ; my < mb_height ; my += 1) {
        _jxr_r_rotate_mb_strip(image);
        image->cur_my = my;
        for (mx = 0 ; mx < mb_width ; mx += 1) {
            _jxr_r_MB_DC(image, str, 0, tx, ty, mx, my);
            if (image->bands_present == 3 /* DCONLY */)
                _jxr_complete_cur_dclp(image, tx, mx, my);
            if (ALPHACHANNEL_FLAG(image)) {
                _jxr_r_MB_DC(image->alpha, str, 1, tx, ty, mx, my);
                if (image->alpha->bands_present == 3 /* DCONLY */)
                    _jxr_complete_cur_dclp(image->alpha, tx, mx, my);
            }
        }
        
        if (ALPHACHANNEL_FLAG(image))
            backup_dc_strip(image->alpha, tx, ty, my);

        backup_dc_strip(image, tx, ty, my);
    }

    _jxr_rbitstream_syncbyte(str);
    DEBUG("END TILE_DC\n");

    return 0;
}
/*
* This function handles the special case that the FLEXBITS tile is
* escaped away. Do all the soft processing that is otherwise needed.
*/
int _jxr_r_TILE_FLEXBITS_ESCAPE(jxr_image_t image, unsigned tx, unsigned ty)
{
    DEBUG("START TILE_FLEXBITS_ESCAPE at tile=[%u %u]\n", tx, ty);

    int use_num_channels = image->num_channels;
    if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/)
        use_num_channels = 1;

    unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image);
    unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image);

    if (TILING_FLAG(image)) {
        mb_height = image->tile_row_height[ty];
        mb_width = image->tile_column_width[tx];
    }

    int mx, my;
    for (my = 0 ; my < (int) mb_height ; my += 1) {
        _jxr_r_rotate_mb_strip(image);
        image->cur_my = my;
        recover_dclphp_strip(image, tx, ty, my);

        for (mx = 0 ; mx < (int) mb_width ; mx += 1) {
            /* */
            int mbhp_pred_mode = MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode;
            int idx;
            for (idx = 0 ; idx < use_num_channels ; idx += 1) {
                DEBUG(" MB_FLEXBITS_ESCAPE: propagate HP predictions in MB_FLEXBITS\n");
                _jxr_propagate_hp_predictions(image, idx, tx, mx, mbhp_pred_mode);
            }
        }
        backup_hp_strip(image, tx, ty, my);
    }

    DEBUG("END TILE_FLEXBIT_ESCAPE\n");
    return 0;
}
int _jxr_r_TILE_FLEXBITS(jxr_image_t image, struct rbitstream*str,
                         unsigned tx, unsigned ty)
{
    DEBUG("START TILE_FLEXBITS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));

    /* TILE_STARTCODE == 1 */
    unsigned char s0, s1, s2, s3;
    s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
    s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
    s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
    s3 = _jxr_rbitstream_uint8(str); /* reserved */
    DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
    if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) {
        DEBUG(" TILE_FLEXBITS ERROR: Invalid marker.\n");
        return JXR_EC_ERROR;
    }

    image->trim_flexbits = 0;
    if (TRIM_FLEXBITS_FLAG(image)) {
        image->trim_flexbits =_jxr_rbitstream_uint4(str);
        DEBUG(" TRIM_FLEXBITS = %u\n", image->trim_flexbits);
    }

    int use_num_channels = image->num_channels;
    if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/)
        use_num_channels = 1;

    /* Now form and write out all the compressed data for the
    tile. This involves scanning the macroblocks, and the
    blocks within the macroblocks, generating bits as we go. */

    unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image);
    unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image);

    if (TILING_FLAG(image)) {
        mb_height = image->tile_row_height[ty];
        mb_width = image->tile_column_width[tx];
    }

    int mx, my;
    int plane_idx, num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1);
    for (my = 0 ; my < (int) mb_height ; my += 1) {
        _jxr_r_rotate_mb_strip(image);
        if (ALPHACHANNEL_FLAG(image)) {
            image->alpha->cur_my = my;
            recover_dclphp_strip(image->alpha, tx, ty, my);
        }
        image->cur_my = my;
        recover_dclphp_strip(image, tx, ty, my);

        for (mx = 0 ; mx < (int) mb_width ; mx += 1) 
        for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) {
            jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
            int channels = (plane_idx == 0 ? use_num_channels : 1);
            int rc = _jxr_r_MB_FLEXBITS(plane, str, 0, tx, ty, mx, my);
            if (rc < 0) {
                DEBUG("r_MB_FLEXBITS returned ERROR rc=%d\n", rc);
                return rc;
            }

            /* Now the HP values are complete, so run the propagation
            process. This involves recovering some bits of data saved
            by the HP tile. */
            int mbhp_pred_mode = MACROBLK_CUR(plane,0,tx,mx).mbhp_pred_mode;
            int idx;
            for (idx = 0 ; idx < channels ; idx += 1) {
                DEBUG(" MB_FLEXBITS: propagate HP predictions in MB_FLEXBITS\n");
                _jxr_propagate_hp_predictions(plane, idx, tx, mx, mbhp_pred_mode);
            }
        }
        if (ALPHACHANNEL_FLAG(image))
            backup_hp_strip(image->alpha, tx, ty, my);
        backup_hp_strip(image, tx, ty, my);
    }

    _jxr_rbitstream_syncbyte(str);
    DEBUG("END TILE_FLEXBITS bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
    return 0;
}
int _jxr_r_TILE_HP(jxr_image_t image, struct rbitstream*str,
                   unsigned tx, unsigned ty)
{
    DEBUG("START TILE_HIGHPASS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));

    /* TILE_STARTCODE == 1 */
    unsigned char s0, s1, s2, s3;
    s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
    s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
    s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
    s3 = _jxr_rbitstream_uint8(str); /* reserved */
    DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
    if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) {
        DEBUG(" TILE_HIGHPASS ERROR: Invalid marker.\n");
        return JXR_EC_ERROR;
    }

    _jxr_r_TILE_HEADER_HIGHPASS(image, str, 0 /* alpha */, tx, ty);
    if (ALPHACHANNEL_FLAG(image))
        _jxr_r_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty);

    /* Now form and write out all the compressed data for the
    tile. This involves scanning the macroblocks, and the
    blocks within the macroblocks, generating bits as we go. */

    unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image);
    unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image);

    if (TILING_FLAG(image)) {
        mb_height = image->tile_row_height[ty];
        mb_width = image->tile_column_width[tx];
    }

    unsigned mx, my;
    unsigned plane_idx, num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1);
    for (my = 0 ; my < mb_height ; my += 1) {
        _jxr_r_rotate_mb_strip(image);

        if (ALPHACHANNEL_FLAG(image)) {
            image->alpha->cur_my = my;
            recover_dclp_strip(image->alpha, tx, ty, my);
        }
        image->cur_my = my;
        recover_dclp_strip(image, tx, ty, my);

        for (mx = 0 ; mx < mb_width ; mx += 1) 
        for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) {
            /* The qp_index_hp table goes only into channel 0 */
            int qp_index_hp = 0;
            jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
            if (plane->num_hp_qps>1) {
                if (!plane->hp_use_lp_qp)
                    qp_index_hp = _jxr_DECODE_QP_INDEX(str, plane->num_hp_qps);
                else
                    qp_index_hp = MACROBLK_CUR_LP_QUANT(plane,0,tx,mx);
            }
            DEBUG(" HP_QP_INDEX for MBx=%d is %d\n", mx, qp_index_hp);
            int ch;
            for (ch = 0 ; ch < plane->num_channels ; ch += 1) {
                MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx) = plane->hp_quant_ch[ch][qp_index_hp];
                DEBUG(" HP_QUANT for MBx=%d ch=%d is %d\n", mx, ch, MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx));
            }

            int rc = _jxr_r_MB_CBP(plane, str, 0, tx, ty, mx, my);
            if (rc < 0) {
                DEBUG("r_MB_CBP returned ERROR rc=%d\n", rc);
                return rc;
            }
            rc = _jxr_r_MB_HP(plane, str, 0, tx, ty, mx, my);
            if (rc < 0) {
                DEBUG("r_MB_HP returned ERROR rc=%d\n", rc);
                return rc;
            }
        }
        if (ALPHACHANNEL_FLAG(image))
            backup_hp_strip(image->alpha, tx, ty, my);
        backup_hp_strip(image, tx, ty, my);
    }

    _jxr_rbitstream_syncbyte(str);
    DEBUG("END TILE_HIGHPASS\n");
    return 0;
}