X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fopenjp2%2Ftcd.c;h=998baf9a5529b4ed9f7dc2f7b95cad577bcb3aff;hb=3d9bcd37534ce1166e1f0a7764faf69bea4d89b1;hp=dd9faced5e650911ebec090d1c87ce791e9e6274;hpb=3b1b0672663b59853b63d48f94b63ca497883527;p=openjpeg.git diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c index dd9faced..998baf9a 100644 --- a/src/lib/openjp2/tcd.c +++ b/src/lib/openjp2/tcd.c @@ -14,6 +14,7 @@ * Copyright (c) 2006-2007, Parvatha Elangovan * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,6 +42,8 @@ #include "opj_includes.h" #include "opj_common.h" +// #define DEBUG_RATE_ALLOC + /* ----------------------------------------------------------------------- */ /* TODO MSD: */ @@ -111,7 +114,7 @@ void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) * Initializes tile coding/decoding */ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, - OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, + OPJ_BOOL isEncoder, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager); /** @@ -142,6 +145,9 @@ static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * */ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct); +static +void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, + OPJ_UINT32 final); /** Free the memory allocated for encoding @@ -180,12 +186,19 @@ static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, OPJ_BYTE * p_dest_data, OPJ_UINT32 * p_data_written, OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info); + opj_codestream_info_t *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager); static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, OPJ_BYTE * p_dest_data, OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info); + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager); + + +static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *tcd, + OPJ_UINT32 compno); /* ----------------------------------------------------------------------- */ @@ -216,6 +229,7 @@ opj_tcd_t* opj_tcd_create(OPJ_BOOL p_is_decoder) /* ----------------------------------------------------------------------- */ +static void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) { OPJ_UINT32 layno; @@ -226,15 +240,21 @@ void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) } -void opj_tcd_makelayer(opj_tcd_t *tcd, - OPJ_UINT32 layno, - OPJ_FLOAT64 thresh, - OPJ_UINT32 final) +/* ----------------------------------------------------------------------- */ + +/** Returns OPJ_TRUE if the layer allocation is unchanged w.r.t to the previous + * invokation with a different threshold */ +static +OPJ_BOOL opj_tcd_makelayer(opj_tcd_t *tcd, + OPJ_UINT32 layno, + OPJ_FLOAT64 thresh, + OPJ_UINT32 final) { OPJ_UINT32 compno, resno, bandno, precno, cblkno; OPJ_UINT32 passno; opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + OPJ_BOOL layer_allocation_is_same = OPJ_TRUE; tcd_tile->distolayer[layno] = 0; /* fixed_quality */ @@ -266,32 +286,40 @@ void opj_tcd_makelayer(opj_tcd_t *tcd, n = cblk->numpassesinlayers; - for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { - OPJ_UINT32 dr; - OPJ_FLOAT64 dd; - opj_tcd_pass_t *pass = &cblk->passes[passno]; - - if (n == 0) { - dr = pass->rate; - dd = pass->distortiondec; - } else { - dr = pass->rate - cblk->passes[n - 1].rate; - dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; - } + if (thresh < 0) { + /* Special value to indicate to use all passes */ + n = cblk->totalpasses; + } else { + for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { + OPJ_UINT32 dr; + OPJ_FLOAT64 dd; + opj_tcd_pass_t *pass = &cblk->passes[passno]; + + if (n == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[n - 1].rate; + dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; + } - if (!dr) { - if (dd != 0) { + if (!dr) { + if (dd != 0) { + n = passno + 1; + } + continue; + } + if (thresh - (dd / dr) < + DBL_EPSILON) { /* do not rely on float equality, check with DBL_EPSILON margin */ n = passno + 1; } - continue; - } - if (thresh - (dd / dr) < - DBL_EPSILON) { /* do not rely on float equality, check with DBL_EPSILON margin */ - n = passno + 1; } } - layer->numpasses = n - cblk->numpassesinlayers; + if (layer->numpasses != n - cblk->numpassesinlayers) { + layer_allocation_is_same = OPJ_FALSE; + layer->numpasses = n - cblk->numpassesinlayers; + } if (!layer->numpasses) { layer->disto = 0; @@ -320,8 +348,10 @@ void opj_tcd_makelayer(opj_tcd_t *tcd, } } } + return layer_allocation_is_same; } +static void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final) { @@ -427,11 +457,17 @@ void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, } } +/** Rate allocation for the following methods: + * - allocation by rate/distortio (m_disto_alloc == 1) + * - allocation by fixed quality (m_fixed_quality == 1) + */ +static OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, - opj_codestream_info_t *cstr_info) + opj_codestream_info_t *cstr_info, + opj_event_mgr_t *p_manager) { OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno; OPJ_UINT32 passno; @@ -547,6 +583,7 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, (tcd_tcp->distoratio[layno] > 0.0))) { opj_t2_t*t2 = opj_t2_create(tcd->image, cp); OPJ_FLOAT64 thresh = 0; + OPJ_BOOL last_layer_allocation_ok = OPJ_FALSE; if (t2 == 00) { return OPJ_FALSE; @@ -554,16 +591,33 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, for (i = 0; i < 128; ++i) { OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */ + OPJ_BOOL layer_allocation_is_same; + + OPJ_FLOAT64 new_thresh = (lo + hi) / 2; + /* Stop iterating when the threshold has stabilized enough */ + /* 0.5 * 1e-5 is somewhat arbitrary, but has been selected */ + /* so that this doesn't change the results of the regression */ + /* test suite. */ + if (fabs(new_thresh - thresh) <= 0.5 * 1e-5 * thresh) { + break; + } + thresh = new_thresh; +#ifdef DEBUG_RATE_ALLOC + opj_event_msg(p_manager, EVT_INFO, "layno=%u, iter=%u, thresh=%g", + layno, i, new_thresh); +#endif - thresh = (lo + hi) / 2; - - opj_tcd_makelayer(tcd, layno, thresh, 0); - + layer_allocation_is_same = opj_tcd_makelayer(tcd, layno, thresh, 0) && i != 0; +#ifdef DEBUG_RATE_ALLOC + opj_event_msg(p_manager, EVT_INFO, "--> layer_allocation_is_same = %d", + layer_allocation_is_same); +#endif if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ - if (OPJ_IS_CINEMA(cp->rsiz)) { + if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) { if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, - p_data_written, maxlen, cstr_info, tcd->cur_tp_num, tcd->tp_pos, tcd->cur_pino, - THRESH_CALC)) { + p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, + tcd->cur_pino, + THRESH_CALC, p_manager)) { lo = thresh; continue; @@ -590,16 +644,41 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, } lo = thresh; } - } else { - if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, - p_data_written, maxlen, cstr_info, tcd->cur_tp_num, tcd->tp_pos, tcd->cur_pino, - THRESH_CALC)) { - /* TODO: what to do with l ??? seek / tell ??? */ - /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ + } else { /* Disto/rate based optimization */ + /* Check if the layer allocation done by opj_tcd_makelayer() + * is compatible of the maximum rate allocation. If not, + * retry with a higher threshold. + * If OK, try with a lower threshold. + * Call opj_t2_encode_packets() only if opj_tcd_makelayer() + * has resulted in different truncation points since its last + * call. */ + if ((layer_allocation_is_same && !last_layer_allocation_ok) || + (!layer_allocation_is_same && + ! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, + p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, + tcd->cur_pino, + THRESH_CALC, p_manager))) { + +#ifdef DEBUG_RATE_ALLOC + if (!layer_allocation_is_same) { + opj_event_msg(p_manager, EVT_INFO, + "--> check rate alloc failed (> maxlen=%u)\n", maxlen); + } +#endif + last_layer_allocation_ok = OPJ_FALSE; lo = thresh; continue; } +#ifdef DEBUG_RATE_ALLOC + if (!layer_allocation_is_same) { + opj_event_msg(p_manager, EVT_INFO, + "--> check rate alloc success (len=%u <= maxlen=%u)\n", *p_data_written, + maxlen); + } +#endif + + last_layer_allocation_ok = OPJ_TRUE; hi = thresh; stable_thresh = thresh; } @@ -609,7 +688,8 @@ OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, opj_t2_destroy(t2); } else { - goodthresh = min; + /* Special value to indicate to use all passes */ + goodthresh = -1; } if (cstr_info) { /* Threshold for Marcela Index */ @@ -665,6 +745,9 @@ void opj_tcd_destroy(opj_tcd_t *tcd) opj_free(tcd->tcd_image); tcd->tcd_image = 00; } + + opj_free(tcd->used_component); + opj_free(tcd); } } @@ -675,7 +758,7 @@ OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec) ((l_tilec->data_size_needed > l_tilec->data_size) && (l_tilec->ownsData == OPJ_FALSE))) { l_tilec->data = (OPJ_INT32 *) opj_image_data_alloc(l_tilec->data_size_needed); - if (! l_tilec->data) { + if (!l_tilec->data && l_tilec->data_size_needed != 0) { return OPJ_FALSE; } /*fprintf(stderr, "tAllocate data of tilec (int): %d x OPJ_UINT32n",l_data_size);*/ @@ -701,10 +784,9 @@ OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec) /* ----------------------------------------------------------------------- */ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, - OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, + OPJ_BOOL isEncoder, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager) { - OPJ_UINT32(*l_gain_ptr)(OPJ_UINT32) = 00; OPJ_UINT32 compno, resno, bandno, precno, cblkno; opj_tcp_t * l_tcp = 00; opj_cp_t * l_cp = 00; @@ -720,7 +802,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_UINT32 p, q; OPJ_UINT32 l_level_no; OPJ_UINT32 l_pdx, l_pdy; - OPJ_UINT32 l_gain; OPJ_INT32 l_x0b, l_y0b; OPJ_UINT32 l_tx0, l_ty0; /* extent of precincts , top left, bottom right**/ @@ -787,24 +868,9 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_tilec->y0 = opj_int_ceildiv(l_tile->y0, (OPJ_INT32)l_image_comp->dy); l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx); l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy); + l_tilec->compno = compno; /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ - /* compute l_data_size with overflow check */ - l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); - /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ - if ((l_data_size > 0U) && - ((((OPJ_UINT32) - 1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 - - l_tilec->y0))) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); - return OPJ_FALSE; - } - l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); - - if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); - return OPJ_FALSE; - } - l_data_size = l_data_size * (OPJ_UINT32)sizeof(OPJ_UINT32); l_tilec->numresolutions = l_tccp->numresolutions; if (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce) { l_tilec->minimum_num_resolutions = 1; @@ -813,15 +879,39 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_cp->m_specific_param.m_dec.m_reduce; } - l_tilec->data_size_needed = l_data_size; - if (p_tcd->m_is_decoder && !opj_alloc_tile_component_data(l_tilec)) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); - return OPJ_FALSE; + if (isEncoder) { + OPJ_SIZE_T l_tile_data_size; + + /* compute l_data_size with overflow check */ + OPJ_SIZE_T w = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0); + OPJ_SIZE_T h = (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); + + /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ + if (h > 0 && w > SIZE_MAX / h) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_tile_data_size = w * h; + + if (SIZE_MAX / sizeof(OPJ_UINT32) < l_tile_data_size) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_tile_data_size = l_tile_data_size * sizeof(OPJ_UINT32); + + l_tilec->data_size_needed = l_tile_data_size; } l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof( opj_tcd_resolution_t); + opj_image_data_free(l_tilec->data_win); + l_tilec->data_win = NULL; + l_tilec->win_x0 = 0; + l_tilec->win_y0 = 0; + l_tilec->win_x1 = 0; + l_tilec->win_y1 = 0; + if (l_tilec->resolutions == 00) { l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size); if (! l_tilec->resolutions) { @@ -850,11 +940,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_level_no = l_tilec->numresolutions; l_res = l_tilec->resolutions; l_step_size = l_tccp->stepsizes; - if (l_tccp->qmfbid == 0) { - l_gain_ptr = &opj_dwt_getgain_real; - } else { - l_gain_ptr = &opj_dwt_getgain; - } /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/ for (resno = 0; resno < l_tilec->numresolutions; ++resno) { @@ -870,6 +955,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); + /*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/ /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ l_pdx = l_tccp->prcw[resno]; @@ -878,8 +964,24 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ l_tl_prc_x_start = opj_int_floordivpow2(l_res->x0, (OPJ_INT32)l_pdx) << l_pdx; l_tl_prc_y_start = opj_int_floordivpow2(l_res->y0, (OPJ_INT32)l_pdy) << l_pdy; - l_br_prc_x_end = opj_int_ceildivpow2(l_res->x1, (OPJ_INT32)l_pdx) << l_pdx; - l_br_prc_y_end = opj_int_ceildivpow2(l_res->y1, (OPJ_INT32)l_pdy) << l_pdy; + { + OPJ_UINT32 tmp = ((OPJ_UINT32)opj_int_ceildivpow2(l_res->x1, + (OPJ_INT32)l_pdx)) << l_pdx; + if (tmp > (OPJ_UINT32)INT_MAX) { + opj_event_msg(manager, EVT_ERROR, "Integer overflow\n"); + return OPJ_FALSE; + } + l_br_prc_x_end = (OPJ_INT32)tmp; + } + { + OPJ_UINT32 tmp = ((OPJ_UINT32)opj_int_ceildivpow2(l_res->y1, + (OPJ_INT32)l_pdy)) << l_pdy; + if (tmp > (OPJ_UINT32)INT_MAX) { + opj_event_msg(manager, EVT_ERROR, "Integer overflow\n"); + return OPJ_FALSE; + } + l_br_prc_y_end = (OPJ_INT32)tmp; + } /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/ l_res->pw = (l_res->x0 == l_res->x1) ? 0U : (OPJ_UINT32)(( @@ -889,14 +991,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ if ((l_res->pw != 0U) && ((((OPJ_UINT32) - 1) / l_res->pw) < l_res->ph)) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); return OPJ_FALSE; } l_nb_precincts = l_res->pw * l_res->ph; if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t)) < l_nb_precincts) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); return OPJ_FALSE; } l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t); @@ -924,7 +1026,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_band = l_res->bands; for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band, ++l_step_size) { - OPJ_INT32 numbps; /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/ if (resno == 0) { @@ -960,11 +1061,24 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, } } - /** avoid an if with storing function pointer */ - l_gain = (*l_gain_ptr)(l_band->bandno); - numbps = (OPJ_INT32)(l_image_comp->prec + l_gain); - l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, - (OPJ_INT32)(numbps - l_step_size->expn)))) * fraction; + { + /* Table E-1 - Sub-band gains */ + /* BUG_WEIRD_TWO_INVK (look for this identifier in dwt.c): */ + /* the test (!isEncoder && l_tccp->qmfbid == 0) is strongly */ + /* linked to the use of two_invK instead of invK */ + const OPJ_INT32 log2_gain = (!isEncoder && + l_tccp->qmfbid == 0) ? 0 : (l_band->bandno == 0) ? 0 : + (l_band->bandno == 3) ? 2 : 1; + + /* Nominal dynamic range. Equation E-4 */ + const OPJ_INT32 Rb = (OPJ_INT32)l_image_comp->prec + log2_gain; + + /* Delta_b value of Equation E-3 in "E.1 Inverse quantization + * procedure" of the standard */ + l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, + (OPJ_INT32)(Rb - l_step_size->expn)))); + } + /* Mb value of Equation E-2 in "E.1 Inverse quantization * procedure" of the standard */ l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits - @@ -1040,6 +1154,12 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ + if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof_block) < + l_nb_code_blocks) { + opj_event_msg(manager, EVT_ERROR, + "Size of code block data exceeds system limits\n"); + return OPJ_FALSE; + } l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; if (!l_current_precinct->cblks.blocks && (l_nb_code_blocks > 0U)) { @@ -1141,14 +1261,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL opj_tcd_init_encode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager) { - return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, 1.0F, + return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, sizeof(opj_tcd_cblk_enc_t), p_manager); } OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager) { - return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, 0.5F, + return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, sizeof(opj_tcd_cblk_dec_t), p_manager); } @@ -1184,9 +1304,18 @@ static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * { OPJ_UINT32 l_data_size; - /* The +1 is needed for https://github.com/uclouvain/openjpeg/issues/835 */ - l_data_size = 1 + (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * - (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32)); + /* +1 is needed for https://github.com/uclouvain/openjpeg/issues/835 */ + /* and actually +2 required for https://github.com/uclouvain/openjpeg/issues/982 */ + /* and +7 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 3) */ + /* and +26 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 7) */ + /* and +28 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 44) */ + /* and +33 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 4) */ + /* and +63 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 4 -IMF 2K) */ + /* and +74 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 4 -n 8 -s 7,7 -I) */ + /* TODO: is there a theoretical upper-bound for the compressed code */ + /* block size ? */ + l_data_size = 74 + (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * + (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32)); if (l_data_size > p_code_block->data_size) { if (p_code_block->data) { @@ -1241,6 +1370,9 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t * OPJ_UINT32 l_numchunksalloc = p_code_block->numchunksalloc; OPJ_UINT32 i; + opj_aligned_free(p_code_block->decoded_data); + p_code_block->decoded_data = 00; + memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t)); p_code_block->segs = l_segs; p_code_block->m_current_max_segs = l_current_max_segs; @@ -1254,7 +1386,8 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t * return OPJ_TRUE; } -OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd) +OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd, + OPJ_BOOL take_into_account_partial_decoding) { OPJ_UINT32 i; OPJ_UINT32 l_data_size = 0; @@ -1268,6 +1401,7 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd) l_img_comp = p_tcd->image->comps; for (i = 0; i < p_tcd->image->numcomps; ++i) { + OPJ_UINT32 w, h; l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ l_remaining = l_img_comp->prec & 7; /* (%8) */ @@ -1280,8 +1414,17 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd) } l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; - l_temp = (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 - - l_res->y0)); /* x1*y1 can't overflow */ + if (take_into_account_partial_decoding && !p_tcd->whole_tile_decoding) { + w = l_res->win_x1 - l_res->win_x0; + h = l_res->win_y1 - l_res->win_y0; + } else { + w = (OPJ_UINT32)(l_res->x1 - l_res->x0); + h = (OPJ_UINT32)(l_res->y1 - l_res->y0); + } + if (h > 0 && UINT_MAX / w < h) { + return UINT_MAX; + } + l_temp = w * h; if (l_size_comp && UINT_MAX / l_size_comp < l_temp) { return UINT_MAX; } @@ -1303,7 +1446,9 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, OPJ_BYTE *p_dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 p_max_length, - opj_codestream_info_t *p_cstr_info) + opj_codestream_info_t *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager) { if (p_tcd->cur_tp_num == 0) { @@ -1330,7 +1475,8 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, p_cstr_info->tile[p_tile_no].pdy[i] = (int)l_tccp->prch[i]; } p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc(( - size_t)p_cstr_info->numcomps * (size_t)p_cstr_info->numlayers * l_num_packs, + OPJ_SIZE_T)p_cstr_info->numcomps * (OPJ_SIZE_T)p_cstr_info->numlayers * + l_num_packs, sizeof(opj_packet_info_t)); if (!p_cstr_info->tile[p_tile_no].packet) { /* FIXME event manager error callback */ @@ -1365,7 +1511,8 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, /* FIXME _ProfStop(PGROUP_T1); */ /* FIXME _ProfStart(PGROUP_RATE); */ - if (! opj_tcd_rate_allocate_encode(p_tcd, p_dest, p_max_length, p_cstr_info)) { + if (! opj_tcd_rate_allocate_encode(p_tcd, p_dest, p_max_length, + p_cstr_info, p_manager)) { return OPJ_FALSE; } /* FIXME _ProfStop(PGROUP_RATE); */ @@ -1380,7 +1527,7 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, /* FIXME _ProfStart(PGROUP_T2); */ if (! opj_tcd_t2_encode(p_tcd, p_dest, p_data_written, p_max_length, - p_cstr_info)) { + p_cstr_info, p_marker_info, p_manager)) { return OPJ_FALSE; } /* FIXME _ProfStop(PGROUP_T2); */ @@ -1391,6 +1538,12 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, } OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 win_x0, + OPJ_UINT32 win_y0, + OPJ_UINT32 win_x1, + OPJ_UINT32 win_y1, + OPJ_UINT32 numcomps_to_decode, + const OPJ_UINT32 *comps_indices, OPJ_BYTE *p_src, OPJ_UINT32 p_max_length, OPJ_UINT32 p_tile_no, @@ -1399,8 +1552,131 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd, ) { OPJ_UINT32 l_data_read; + OPJ_UINT32 compno; + p_tcd->tcd_tileno = p_tile_no; p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]); + p_tcd->win_x0 = win_x0; + p_tcd->win_y0 = win_y0; + p_tcd->win_x1 = win_x1; + p_tcd->win_y1 = win_y1; + p_tcd->whole_tile_decoding = OPJ_TRUE; + + opj_free(p_tcd->used_component); + p_tcd->used_component = NULL; + + if (numcomps_to_decode) { + OPJ_BOOL* used_component = (OPJ_BOOL*) opj_calloc(sizeof(OPJ_BOOL), + p_tcd->image->numcomps); + if (used_component == NULL) { + return OPJ_FALSE; + } + for (compno = 0; compno < numcomps_to_decode; compno++) { + used_component[ comps_indices[compno] ] = OPJ_TRUE; + } + + p_tcd->used_component = used_component; + } + + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + if (!opj_tcd_is_whole_tilecomp_decoding(p_tcd, compno)) { + p_tcd->whole_tile_decoding = OPJ_FALSE; + break; + } + } + + if (p_tcd->whole_tile_decoding) { + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_tcd_resolution_t *l_res = & + (tilec->resolutions[tilec->minimum_num_resolutions - 1]); + OPJ_SIZE_T l_data_size; + + /* compute l_data_size with overflow check */ + OPJ_SIZE_T res_w = (OPJ_SIZE_T)(l_res->x1 - l_res->x0); + OPJ_SIZE_T res_h = (OPJ_SIZE_T)(l_res->y1 - l_res->y0); + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ + if (res_h > 0 && res_w > SIZE_MAX / res_h) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size = res_w * res_h; + + if (SIZE_MAX / sizeof(OPJ_UINT32) < l_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size *= sizeof(OPJ_UINT32); + + tilec->data_size_needed = l_data_size; + + if (!opj_alloc_tile_component_data(tilec)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + } + } else { + /* Compute restricted tile-component and tile-resolution coordinates */ + /* of the window of interest, but defer the memory allocation until */ + /* we know the resno_decoded */ + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + OPJ_UINT32 resno; + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + tilec->win_x0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx)); + tilec->win_y0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy)); + tilec->win_x1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx)); + tilec->win_y1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy)); + if (tilec->win_x1 < tilec->win_x0 || + tilec->win_y1 < tilec->win_y0) { + /* We should not normally go there. The circumstance is when */ + /* the tile coordinates do not intersect the area of interest */ + /* Upper level logic should not even try to decode that tile */ + opj_event_msg(p_manager, EVT_ERROR, + "Invalid tilec->win_xxx values\n"); + return OPJ_FALSE; + } + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = tilec->resolutions + resno; + res->win_x0 = opj_uint_ceildivpow2(tilec->win_x0, + tilec->numresolutions - 1 - resno); + res->win_y0 = opj_uint_ceildivpow2(tilec->win_y0, + tilec->numresolutions - 1 - resno); + res->win_x1 = opj_uint_ceildivpow2(tilec->win_x1, + tilec->numresolutions - 1 - resno); + res->win_y1 = opj_uint_ceildivpow2(tilec->win_y1, + tilec->numresolutions - 1 - resno); + } + } + } #ifdef TODO_MSD /* FIXME */ /* INDEX >> */ @@ -1443,6 +1719,49 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd, } /* FIXME _ProfStop(PGROUP_T1); */ + + /* For subtile decoding, now we know the resno_decoded, we can allocate */ + /* the tile data buffer */ + if (!p_tcd->whole_tile_decoding) { + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + opj_tcd_resolution_t *res = tilec->resolutions + image_comp->resno_decoded; + OPJ_SIZE_T w = res->win_x1 - res->win_x0; + OPJ_SIZE_T h = res->win_y1 - res->win_y0; + OPJ_SIZE_T l_data_size; + + opj_image_data_free(tilec->data_win); + tilec->data_win = NULL; + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + if (w > 0 && h > 0) { + if (w > SIZE_MAX / h) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size = w * h; + if (l_data_size > SIZE_MAX / sizeof(OPJ_INT32)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size *= sizeof(OPJ_INT32); + + tilec->data_win = (OPJ_INT32*) opj_image_data_alloc(l_data_size); + if (tilec->data_win == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + } + } + } + /*----------------DWT---------------------*/ /* FIXME _ProfStart(PGROUP_DWT); */ @@ -1484,7 +1803,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, OPJ_UINT32 l_size_comp, l_remaining; OPJ_UINT32 l_stride, l_width, l_height; - l_data_size = opj_tcd_get_decoded_tile_size(p_tcd); + l_data_size = opj_tcd_get_decoded_tile_size(p_tcd, OPJ_TRUE); if (l_data_size == UINT_MAX || l_data_size > p_dest_length) { return OPJ_FALSE; } @@ -1493,12 +1812,23 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, l_img_comp = p_tcd->image->comps; for (i = 0; i < p_tcd->image->numcomps; ++i) { + const OPJ_INT32* l_src_data; l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ l_remaining = l_img_comp->prec & 7; /* (%8) */ l_res = l_tilec->resolutions + l_img_comp->resno_decoded; - l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); - l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); - l_stride = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0) - l_width; + if (p_tcd->whole_tile_decoding) { + l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); + l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); + l_stride = (OPJ_UINT32)(l_tilec->resolutions[l_tilec->minimum_num_resolutions - + 1].x1 - + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x0) - l_width; + l_src_data = l_tilec->data; + } else { + l_width = l_res->win_x1 - l_res->win_x0; + l_height = l_res->win_y1 - l_res->win_y0; + l_stride = 0; + l_src_data = l_tilec->data_win; + } if (l_remaining) { ++l_size_comp; @@ -1511,7 +1841,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, switch (l_size_comp) { case 1: { OPJ_CHAR * l_dest_ptr = (OPJ_CHAR *) p_dest; - const OPJ_INT32 * l_src_ptr = l_tilec->data; + const OPJ_INT32 * l_src_ptr = l_src_data; if (l_img_comp->sgnd) { for (j = 0; j < l_height; ++j) { @@ -1533,7 +1863,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, } break; case 2: { - const OPJ_INT32 * l_src_ptr = l_tilec->data; + const OPJ_INT32 * l_src_ptr = l_src_data; OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest; if (l_img_comp->sgnd) { @@ -1561,7 +1891,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, break; case 4: { OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest; - OPJ_INT32 * l_src_ptr = l_tilec->data; + const OPJ_INT32 * l_src_ptr = l_src_data; for (j = 0; j < l_height; ++j) { memcpy(l_dest_ptr, l_src_ptr, l_width * sizeof(OPJ_INT32)); @@ -1620,14 +1950,16 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd) l_res = l_tile_comp->resolutions; if (l_res) { - l_nb_resolutions = l_tile_comp->resolutions_size / sizeof(opj_tcd_resolution_t); + l_nb_resolutions = l_tile_comp->resolutions_size / (OPJ_UINT32)sizeof( + opj_tcd_resolution_t); for (resno = 0; resno < l_nb_resolutions; ++resno) { l_band = l_res->bands; for (bandno = 0; bandno < 3; ++bandno) { l_precinct = l_band->precincts; if (l_precinct) { - l_nb_precincts = l_band->precincts_data_size / sizeof(opj_tcd_precinct_t); + l_nb_precincts = l_band->precincts_data_size / (OPJ_UINT32)sizeof( + opj_tcd_precinct_t); for (precno = 0; precno < l_nb_precincts; ++precno) { opj_tgt_destroy(l_precinct->incltree); l_precinct->incltree = 00; @@ -1656,6 +1988,9 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd) l_tile_comp->data_size = 0; l_tile_comp->data_size_needed = 0; } + + opj_image_data_free(l_tile_comp->data_win); + ++l_tile_comp; } @@ -1682,6 +2017,7 @@ static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd, } if (! opj_t2_decode_packets( + p_tcd, l_t2, p_tcd->tcd_tileno, p_tcd->tcd_image->tiles, @@ -1718,14 +2054,17 @@ static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) check_pterm = OPJ_TRUE; } - for (compno = 0; compno < l_tile->numcomps; ++compno) { - opj_t1_decode_cblks(p_tcd->thread_pool, &ret, l_tile_comp, l_tccp, + for (compno = 0; compno < l_tile->numcomps; + ++compno, ++l_tile_comp, ++l_tccp) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + opj_t1_decode_cblks(p_tcd, &ret, l_tile_comp, l_tccp, p_manager, p_manager_mutex, check_pterm); if (!ret) { break; } - ++l_tile_comp; - ++l_tccp; } opj_thread_pool_wait_completion(p_tcd->thread_pool, 0); @@ -1744,64 +2083,108 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd) opj_tccp_t * l_tccp = p_tcd->tcp->tccps; opj_image_comp_t * l_img_comp = p_tcd->image->comps; - for (compno = 0; compno < l_tile->numcomps; compno++) { - /* - if (tcd->cp->reduce != 0) { - tcd->image->comps[compno].resno_decoded = - tile->comps[compno].numresolutions - tcd->cp->reduce - 1; - if (tcd->image->comps[compno].resno_decoded < 0) - { - return false; - } + for (compno = 0; compno < l_tile->numcomps; + compno++, ++l_tile_comp, ++l_img_comp, ++l_tccp) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; } - numres2decode = tcd->image->comps[compno].resno_decoded + 1; - if(numres2decode > 0){ - */ if (l_tccp->qmfbid == 1) { - if (! opj_dwt_decode(p_tcd->thread_pool, l_tile_comp, + if (! opj_dwt_decode(p_tcd, l_tile_comp, l_img_comp->resno_decoded + 1)) { return OPJ_FALSE; } } else { - if (! opj_dwt_decode_real(l_tile_comp, l_img_comp->resno_decoded + 1)) { + if (! opj_dwt_decode_real(p_tcd, l_tile_comp, + l_img_comp->resno_decoded + 1)) { return OPJ_FALSE; } } - ++l_tile_comp; - ++l_img_comp; - ++l_tccp; } return OPJ_TRUE; } + static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) { opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; opj_tcp_t * l_tcp = p_tcd->tcp; opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; - OPJ_UINT32 l_samples, i; + OPJ_SIZE_T l_samples; + OPJ_UINT32 i; - if (! l_tcp->mct) { + if (l_tcp->mct == 0 || p_tcd->used_component != NULL) { return OPJ_TRUE; } - l_samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) * - (l_tile_comp->y1 - l_tile_comp->y0)); + if (p_tcd->whole_tile_decoding) { + opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + + /* A bit inefficient: we process more data than needed if */ + /* resno_decoded < l_tile_comp->minimum_num_resolutions-1, */ + /* but we would need to take into account a stride then */ + l_samples = (OPJ_SIZE_T)(res_comp0->x1 - res_comp0->x0) * + (OPJ_SIZE_T)(res_comp0->y1 - res_comp0->y0); + if (l_tile->numcomps >= 3) { + if (l_tile_comp->minimum_num_resolutions != + l_tile->comps[1].minimum_num_resolutions || + l_tile_comp->minimum_num_resolutions != + l_tile->comps[2].minimum_num_resolutions) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + if (l_tile->numcomps >= 3) { + opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + /* testcase 1336.pdf.asan.47.376 */ + if (p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[1].resno_decoded || + p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[2].resno_decoded || + (OPJ_SIZE_T)(res_comp1->x1 - res_comp1->x0) * + (OPJ_SIZE_T)(res_comp1->y1 - res_comp1->y0) != l_samples || + (OPJ_SIZE_T)(res_comp2->x1 - res_comp2->x0) * + (OPJ_SIZE_T)(res_comp2->y1 - res_comp2->y0) != l_samples) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + } else { + opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions + + p_tcd->image->comps[0].resno_decoded; + + l_samples = (OPJ_SIZE_T)(res_comp0->win_x1 - res_comp0->win_x0) * + (OPJ_SIZE_T)(res_comp0->win_y1 - res_comp0->win_y0); + if (l_tile->numcomps >= 3) { + opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions + + p_tcd->image->comps[1].resno_decoded; + opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions + + p_tcd->image->comps[2].resno_decoded; + /* testcase 1336.pdf.asan.47.376 */ + if (p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[1].resno_decoded || + p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[2].resno_decoded || + (OPJ_SIZE_T)(res_comp1->win_x1 - res_comp1->win_x0) * + (OPJ_SIZE_T)(res_comp1->win_y1 - res_comp1->win_y0) != l_samples || + (OPJ_SIZE_T)(res_comp2->win_x1 - res_comp2->win_x0) * + (OPJ_SIZE_T)(res_comp2->win_y1 - res_comp2->win_y0) != l_samples) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + } if (l_tile->numcomps >= 3) { - /* testcase 1336.pdf.asan.47.376 */ - if ((l_tile->comps[0].x1 - l_tile->comps[0].x0) * (l_tile->comps[0].y1 - - l_tile->comps[0].y0) < (OPJ_INT32)l_samples || - (l_tile->comps[1].x1 - l_tile->comps[1].x0) * (l_tile->comps[1].y1 - - l_tile->comps[1].y0) < (OPJ_INT32)l_samples || - (l_tile->comps[2].x1 - l_tile->comps[2].x0) * (l_tile->comps[2].y1 - - l_tile->comps[2].y0) < (OPJ_INT32)l_samples) { - opj_event_msg(p_manager, EVT_ERROR, - "Tiles don't all have the same dimension. Skip the MCT step.\n"); - return OPJ_FALSE; - } else if (l_tcp->mct == 2) { + if (l_tcp->mct == 2) { OPJ_BYTE ** l_data; if (! l_tcp->m_mct_decoding_matrix) { @@ -1814,7 +2197,11 @@ static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) } for (i = 0; i < l_tile->numcomps; ++i) { - l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + if (p_tcd->whole_tile_decoding) { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + } else { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data_win; + } ++l_tile_comp; } @@ -1835,15 +2222,29 @@ static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) opj_free(l_data); } else { if (l_tcp->tccps->qmfbid == 1) { - opj_mct_decode(l_tile->comps[0].data, - l_tile->comps[1].data, - l_tile->comps[2].data, - l_samples); + if (p_tcd->whole_tile_decoding) { + opj_mct_decode(l_tile->comps[0].data, + l_tile->comps[1].data, + l_tile->comps[2].data, + l_samples); + } else { + opj_mct_decode(l_tile->comps[0].data_win, + l_tile->comps[1].data_win, + l_tile->comps[2].data_win, + l_samples); + } } else { - opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data, - (OPJ_FLOAT32*)l_tile->comps[1].data, - (OPJ_FLOAT32*)l_tile->comps[2].data, - l_samples); + if (p_tcd->whole_tile_decoding) { + opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data, + (OPJ_FLOAT32*)l_tile->comps[1].data, + (OPJ_FLOAT32*)l_tile->comps[2].data, + l_samples); + } else { + opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data_win, + (OPJ_FLOAT32*)l_tile->comps[1].data_win, + (OPJ_FLOAT32*)l_tile->comps[2].data_win, + l_samples); + } } } } else { @@ -1874,14 +2275,32 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) l_tccp = p_tcd->tcp->tccps; l_img_comp = p_tcd->image->comps; - for (compno = 0; compno < l_tile->numcomps; compno++) { + for (compno = 0; compno < l_tile->numcomps; + compno++, ++l_img_comp, ++l_tccp, ++l_tile_comp) { + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded; - l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); - l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); - l_stride = (OPJ_UINT32)(l_tile_comp->x1 - l_tile_comp->x0) - l_width; - assert(l_height == 0 || - l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/ + if (!p_tcd->whole_tile_decoding) { + l_width = l_res->win_x1 - l_res->win_x0; + l_height = l_res->win_y1 - l_res->win_y0; + l_stride = 0; + l_current_ptr = l_tile_comp->data_win; + } else { + l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); + l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); + l_stride = (OPJ_UINT32)( + l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x1 - + l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x0) + - l_width; + l_current_ptr = l_tile_comp->data; + + assert(l_height == 0 || + l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/ + } if (l_img_comp->sgnd) { l_min = -(1 << (l_img_comp->prec - 1)); @@ -1891,11 +2310,11 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) l_max = (OPJ_INT32)((1U << l_img_comp->prec) - 1); } - l_current_ptr = l_tile_comp->data; if (l_tccp->qmfbid == 1) { for (j = 0; j < l_height; ++j) { for (i = 0; i < l_width; ++i) { + /* TODO: do addition on int64 ? */ *l_current_ptr = opj_int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min, l_max); ++l_current_ptr; @@ -1906,13 +2325,14 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) for (j = 0; j < l_height; ++j) { for (i = 0; i < l_width; ++i) { OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr); - OPJ_INT32 l_value_int = (OPJ_INT32)opj_lrintf(l_value); - if (l_value > INT_MAX || - (l_value_int > 0 && l_tccp->m_dc_level_shift > 0 && - l_value_int > INT_MAX - l_tccp->m_dc_level_shift)) { + if (l_value > INT_MAX) { *l_current_ptr = l_max; + } else if (l_value < INT_MIN) { + *l_current_ptr = l_min; } else { - *l_current_ptr = opj_int_clamp( + /* Do addition on int64 to avoid overflows */ + OPJ_INT64 l_value_int = (OPJ_INT64)opj_lrintf(l_value); + *l_current_ptr = (OPJ_INT32)opj_int64_clamp( l_value_int + l_tccp->m_dc_level_shift, l_min, l_max); } ++l_current_ptr; @@ -1920,10 +2340,6 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) l_current_ptr += l_stride; } } - - ++l_img_comp; - ++l_tccp; - ++l_tile_comp; } return OPJ_TRUE; @@ -1946,7 +2362,8 @@ static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct) l_code_block->numbps, l_code_block->numlenbits, l_code_block->len, l_code_block->numnewpasses, l_code_block->real_num_segs, l_code_block->m_current_max_segs );*/ - l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_dec_t); + l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof( + opj_tcd_cblk_dec_t); /*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/ for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { @@ -1961,6 +2378,9 @@ static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct) l_code_block->chunks = 00; } + opj_aligned_free(l_code_block->decoded_data); + l_code_block->decoded_data = NULL; + ++l_code_block; } @@ -1978,7 +2398,8 @@ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct) opj_tcd_cblk_enc_t * l_code_block = p_precinct->cblks.enc; if (l_code_block) { - l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_enc_t); + l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof( + opj_tcd_cblk_enc_t); for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { if (l_code_block->data) { @@ -2006,9 +2427,10 @@ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct) } } -OPJ_UINT32 opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd) +OPJ_SIZE_T opj_tcd_get_encoder_input_buffer_size(opj_tcd_t *p_tcd) { - OPJ_UINT32 i, l_data_size = 0; + OPJ_UINT32 i; + OPJ_SIZE_T l_data_size = 0; opj_image_comp_t * l_img_comp = 00; opj_tcd_tilecomp_t * l_tilec = 00; OPJ_UINT32 l_size_comp, l_remaining; @@ -2027,8 +2449,8 @@ OPJ_UINT32 opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd) l_size_comp = 4; } - l_data_size += l_size_comp * (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) * - (l_tilec->y1 - l_tilec->y0)); + l_data_size += l_size_comp * ((OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) * + (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0)); ++l_img_comp; ++l_tilec; } @@ -2043,7 +2465,7 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd) opj_tccp_t * l_tccp = 00; opj_image_comp_t * l_img_comp = 00; opj_tcd_tile_t * l_tile; - OPJ_UINT32 l_nb_elem, i; + OPJ_SIZE_T l_nb_elem, i; OPJ_INT32 * l_current_ptr; l_tile = p_tcd->tcd_image->tiles; @@ -2053,8 +2475,8 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd) for (compno = 0; compno < l_tile->numcomps; compno++) { l_current_ptr = l_tile_comp->data; - l_nb_elem = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) * - (l_tile_comp->y1 - l_tile_comp->y0)); + l_nb_elem = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) * + (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0); if (l_tccp->qmfbid == 1) { for (i = 0; i < l_nb_elem; ++i) { @@ -2063,7 +2485,8 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd) } } else { for (i = 0; i < l_nb_elem; ++i) { - *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) * (1 << 11); + *((OPJ_FLOAT32 *) l_current_ptr) = (OPJ_FLOAT32)(*l_current_ptr - + l_tccp->m_dc_level_shift); ++l_current_ptr; } } @@ -2080,8 +2503,8 @@ static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd) { opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; - OPJ_UINT32 samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) * - (l_tile_comp->y1 - l_tile_comp->y0)); + OPJ_SIZE_T samples = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) * + (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0); OPJ_UINT32 i; OPJ_BYTE ** l_data = 00; opj_tcp_t * l_tcp = p_tcd->tcp; @@ -2121,8 +2544,11 @@ static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd) opj_free(l_data); } else if (l_tcp->tccps->qmfbid == 0) { - opj_mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data, - l_tile->comps[2].data, samples); + opj_mct_encode_real( + (OPJ_FLOAT32*)l_tile->comps[0].data, + (OPJ_FLOAT32*)l_tile->comps[1].data, + (OPJ_FLOAT32*)l_tile->comps[2].data, + samples); } else { opj_mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); @@ -2140,11 +2566,11 @@ static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd) for (compno = 0; compno < l_tile->numcomps; ++compno) { if (l_tccp->qmfbid == 1) { - if (! opj_dwt_encode(l_tile_comp)) { + if (! opj_dwt_encode(p_tcd, l_tile_comp)) { return OPJ_FALSE; } } else if (l_tccp->qmfbid == 0) { - if (! opj_dwt_encode_real(l_tile_comp)) { + if (! opj_dwt_encode_real(p_tcd, l_tile_comp)) { return OPJ_FALSE; } } @@ -2158,16 +2584,10 @@ static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd) static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd) { - opj_t1_t * l_t1; const OPJ_FLOAT64 * l_mct_norms; OPJ_UINT32 l_mct_numcomps = 0U; opj_tcp_t * l_tcp = p_tcd->tcp; - l_t1 = opj_t1_create(OPJ_TRUE); - if (l_t1 == 00) { - return OPJ_FALSE; - } - if (l_tcp->mct == 1) { l_mct_numcomps = 3U; /* irreversible encoding */ @@ -2181,13 +2601,9 @@ static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd) l_mct_norms = (const OPJ_FLOAT64 *)(l_tcp->mct_norms); } - if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles, l_tcp, l_mct_norms, - l_mct_numcomps)) { - opj_t1_destroy(l_t1); - return OPJ_FALSE; - } - - opj_t1_destroy(l_t1); + return opj_t1_encode_cblks(p_tcd, + p_tcd->tcd_image->tiles, l_tcp, l_mct_norms, + l_mct_numcomps); return OPJ_TRUE; } @@ -2196,7 +2612,9 @@ static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, OPJ_BYTE * p_dest_data, OPJ_UINT32 * p_data_written, OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info) + opj_codestream_info_t *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager) { opj_t2_t * l_t2; @@ -2214,10 +2632,12 @@ static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, p_data_written, p_max_dest_size, p_cstr_info, + p_marker_info, p_tcd->tp_num, p_tcd->tp_pos, p_tcd->cur_pino, - FINAL_PASS)) { + FINAL_PASS, + p_manager)) { opj_t2_destroy(l_t2); return OPJ_FALSE; } @@ -2232,7 +2652,8 @@ static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, OPJ_BYTE * p_dest_data, OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info) + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager) { opj_cp_t * l_cp = p_tcd->cp; OPJ_UINT32 l_nb_written = 0; @@ -2246,7 +2667,7 @@ static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, /* fixed_quality */ /* Normal Rate/distortion allocation */ if (! opj_tcd_rateallocate(p_tcd, p_dest_data, &l_nb_written, p_max_dest_size, - p_cstr_info)) { + p_cstr_info, p_manager)) { return OPJ_FALSE; } } else { @@ -2260,15 +2681,17 @@ static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd, OPJ_BYTE * p_src, - OPJ_UINT32 p_src_length) + OPJ_SIZE_T p_src_length) { - OPJ_UINT32 i, j, l_data_size = 0; + OPJ_UINT32 i; + OPJ_SIZE_T j; + OPJ_SIZE_T l_data_size = 0; opj_image_comp_t * l_img_comp = 00; opj_tcd_tilecomp_t * l_tilec = 00; OPJ_UINT32 l_size_comp, l_remaining; - OPJ_UINT32 l_nb_elem; + OPJ_SIZE_T l_nb_elem; - l_data_size = opj_tcd_get_encoded_tile_size(p_tcd); + l_data_size = opj_tcd_get_encoder_input_buffer_size(p_tcd); if (l_data_size != p_src_length) { return OPJ_FALSE; } @@ -2278,8 +2701,8 @@ OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd, for (i = 0; i < p_tcd->image->numcomps; ++i) { l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ l_remaining = l_img_comp->prec & 7; /* (%8) */ - l_nb_elem = (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - - l_tilec->y0)); + l_nb_elem = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) * + (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); if (l_remaining) { ++l_size_comp; @@ -2348,3 +2771,152 @@ OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band) { return (band->x1 - band->x0 == 0) || (band->y1 - band->y0 == 0); } + +OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd, + OPJ_UINT32 compno, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 band_x0, + OPJ_UINT32 band_y0, + OPJ_UINT32 band_x1, + OPJ_UINT32 band_y1) +{ + /* Note: those values for filter_margin are in part the result of */ + /* experimentation. The value 2 for QMFBID=1 (5x3 filter) can be linked */ + /* to the maximum left/right extension given in tables F.2 and F.3 of the */ + /* standard. The value 3 for QMFBID=0 (9x7 filter) is more suspicious, */ + /* since F.2 and F.3 would lead to 4 instead, so the current 3 might be */ + /* needed to be bumped to 4, in case inconsistencies are found while */ + /* decoding parts of irreversible coded images. */ + /* See opj_dwt_decode_partial_53 and opj_dwt_decode_partial_97 as well */ + OPJ_UINT32 filter_margin = (tcd->tcp->tccps[compno].qmfbid == 1) ? 2 : 3; + opj_tcd_tilecomp_t *tilec = &(tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(tcd->image->comps[compno]); + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 tcx0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(tcd->win_x0, image_comp->dx)); + OPJ_UINT32 tcy0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(tcd->win_y0, image_comp->dy)); + OPJ_UINT32 tcx1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(tcd->win_x1, image_comp->dx)); + OPJ_UINT32 tcy1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(tcd->win_y1, image_comp->dy)); + /* Compute number of decomposition for this band. See table F-1 */ + OPJ_UINT32 nb = (resno == 0) ? + tilec->numresolutions - 1 : + tilec->numresolutions - resno; + /* Map above tile-based coordinates to sub-band-based coordinates per */ + /* equation B-15 of the standard */ + OPJ_UINT32 x0b = bandno & 1; + OPJ_UINT32 y0b = bandno >> 1; + OPJ_UINT32 tbx0 = (nb == 0) ? tcx0 : + (tcx0 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx0 - (1U << (nb - 1)) * x0b, nb); + OPJ_UINT32 tby0 = (nb == 0) ? tcy0 : + (tcy0 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy0 - (1U << (nb - 1)) * y0b, nb); + OPJ_UINT32 tbx1 = (nb == 0) ? tcx1 : + (tcx1 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx1 - (1U << (nb - 1)) * x0b, nb); + OPJ_UINT32 tby1 = (nb == 0) ? tcy1 : + (tcy1 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy1 - (1U << (nb - 1)) * y0b, nb); + OPJ_BOOL intersects; + + if (tbx0 < filter_margin) { + tbx0 = 0; + } else { + tbx0 -= filter_margin; + } + if (tby0 < filter_margin) { + tby0 = 0; + } else { + tby0 -= filter_margin; + } + tbx1 = opj_uint_adds(tbx1, filter_margin); + tby1 = opj_uint_adds(tby1, filter_margin); + + intersects = band_x0 < tbx1 && band_y0 < tby1 && band_x1 > tbx0 && + band_y1 > tby0; + +#ifdef DEBUG_VERBOSE + printf("compno=%u resno=%u nb=%u bandno=%u x0b=%u y0b=%u band=%u,%u,%u,%u tb=%u,%u,%u,%u -> %u\n", + compno, resno, nb, bandno, x0b, y0b, + band_x0, band_y0, band_x1, band_y1, + tbx0, tby0, tbx1, tby1, intersects); +#endif + return intersects; +} + +/** Returns whether a tile componenent is fully decoded, taking into account + * p_tcd->win_* members. + * + * @param p_tcd TCD handle. + * @param compno Component number + * @return OPJ_TRUE whether the tile componenent is fully decoded + */ +static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *p_tcd, + OPJ_UINT32 compno) +{ + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 tcx0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx)); + OPJ_UINT32 tcy0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy)); + OPJ_UINT32 tcx1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx)); + OPJ_UINT32 tcy1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy)); + + OPJ_UINT32 shift = tilec->numresolutions - tilec->minimum_num_resolutions; + /* Tolerate small margin within the reduced resolution factor to consider if */ + /* the whole tile path must be taken */ + return (tcx0 >= (OPJ_UINT32)tilec->x0 && + tcy0 >= (OPJ_UINT32)tilec->y0 && + tcx1 <= (OPJ_UINT32)tilec->x1 && + tcy1 <= (OPJ_UINT32)tilec->y1 && + (shift >= 32 || + (((tcx0 - (OPJ_UINT32)tilec->x0) >> shift) == 0 && + ((tcy0 - (OPJ_UINT32)tilec->y0) >> shift) == 0 && + (((OPJ_UINT32)tilec->x1 - tcx1) >> shift) == 0 && + (((OPJ_UINT32)tilec->y1 - tcy1) >> shift) == 0))); +} + +/* ----------------------------------------------------------------------- */ + +opj_tcd_marker_info_t* opj_tcd_marker_info_create(OPJ_BOOL need_PLT) +{ + opj_tcd_marker_info_t *l_tcd_marker_info = + (opj_tcd_marker_info_t*) opj_calloc(1, sizeof(opj_tcd_marker_info_t)); + if (!l_tcd_marker_info) { + return NULL; + } + + l_tcd_marker_info->need_PLT = need_PLT; + + return l_tcd_marker_info; +} + +/* ----------------------------------------------------------------------- */ + +void opj_tcd_marker_info_destroy(opj_tcd_marker_info_t *p_tcd_marker_info) +{ + if (p_tcd_marker_info) { + opj_free(p_tcd_marker_info->p_packet_size); + opj_free(p_tcd_marker_info); + } +} + +/* ----------------------------------------------------------------------- */