#include "opj_includes.h"
#include "opj_common.h"
+// #define DEBUG_RATE_ALLOC
+
/* ----------------------------------------------------------------------- */
/* TODO MSD: */
* 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);
/**
*/
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
OPJ_UINT32 * p_data_written,
OPJ_UINT32 p_max_dest_size,
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_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);
+
/* ----------------------------------------------------------------------- */
/**
/* ----------------------------------------------------------------------- */
+static
void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd)
{
OPJ_UINT32 layno;
}
-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 */
+ tcd_tile->distolayer[layno] = 0;
for (compno = 0; compno < tcd_tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
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;
cblk->passes[cblk->numpassesinlayers - 1].distortiondec;
}
- tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */
+ tcd_tile->distolayer[layno] += layer->disto;
if (final) {
cblk->numpassesinlayers = n;
}
}
}
+ return layer_allocation_is_same;
}
+/** For m_quality_layer_alloc_strategy == FIXED_LAYER */
+static
void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno,
OPJ_UINT32 final)
{
OPJ_UINT32 compno, resno, bandno, precno, cblkno;
OPJ_INT32 value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */
- OPJ_INT32 matrice[10][10][3];
+ OPJ_INT32 matrice[J2K_TCD_MATRIX_MAX_LAYER_COUNT][J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT][3];
OPJ_UINT32 i, j, k;
opj_cp_t *cp = tcd->cp;
}
}
+/** Rate allocation for the following methods:
+ * - allocation by rate/distortio (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO)
+ * - allocation by fixed quality (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO)
+ */
+static
OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd,
OPJ_BYTE *dest,
OPJ_UINT32 * p_data_written,
OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno;
OPJ_UINT32 passno;
OPJ_FLOAT64 min, max;
- OPJ_FLOAT64 cumdisto[100]; /* fixed_quality */
- const OPJ_FLOAT64 K = 1; /* 1.1; fixed_quality */
+ OPJ_FLOAT64 cumdisto[100];
+ const OPJ_FLOAT64 K = 1;
OPJ_FLOAT64 maxSE = 0;
opj_cp_t *cp = tcd->cp;
min = DBL_MAX;
max = 0;
- tcd_tile->numpix = 0; /* fixed_quality */
+ tcd_tile->numpix = 0;
for (compno = 0; compno < tcd_tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
}
} /* passno */
- /* fixed_quality */
- tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
- tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+ {
+ const OPJ_SIZE_T cblk_pix_count = (OPJ_SIZE_T)((cblk->x1 - cblk->x0) *
+ (cblk->y1 - cblk->y0));
+ tcd_tile->numpix += cblk_pix_count;
+ tilec->numpix += cblk_pix_count;
+ }
} /* cbklno */
} /* precno */
} /* bandno */
/* index file */
if (cstr_info) {
opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno];
- tile_info->numpix = tcd_tile->numpix;
- tile_info->distotile = tcd_tile->distotile;
+ tile_info->numpix = (int)tcd_tile->numpix;
+ tile_info->distotile = (int)tcd_tile->distotile;
tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof(
OPJ_FLOAT64));
if (!tile_info->thresh) {
OPJ_FLOAT64 goodthresh = 0;
OPJ_FLOAT64 stable_thresh = 0;
OPJ_UINT32 i;
- OPJ_FLOAT64 distotarget; /* fixed_quality */
+ OPJ_FLOAT64 distotarget;
- /* fixed_quality */
distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10,
tcd_tcp->distoratio[layno] / 10));
/* Don't try to find an optimal threshold but rather take everything not included yet, if
- -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0)
- -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0)
+ -r xx,yy,zz,0 (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO and rates == NULL)
+ -q xx,yy,zz,0 (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO and distoratio == NULL)
==> possible to have some lossy layers and the last layer for sure lossless */
- if (((cp->m_specific_param.m_enc.m_disto_alloc == 1) &&
+ if (((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ RATE_DISTORTION_RATIO) &&
(tcd_tcp->rates[layno] > 0.0f)) ||
- ((cp->m_specific_param.m_enc.m_fixed_quality == 1) &&
+ ((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO) &&
(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;
}
for (i = 0; i < 128; ++i) {
- OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */
-
- thresh = (lo + hi) / 2;
-
- opj_tcd_makelayer(tcd, layno, thresh, 0);
+ OPJ_FLOAT64 distoachieved = 0;
+ 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
- if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */
- if (OPJ_IS_CINEMA(cp->rsiz)) {
+ 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_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO) {
+ 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,
+ p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos,
+ tcd->cur_pino,
THRESH_CALC, p_manager)) {
lo = thresh;
}
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, p_manager)) {
- /* 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;
}
opj_t2_destroy(t2);
} else {
- goodthresh = min;
+ /* Special value to indicate to use all passes */
+ goodthresh = -1;
}
if (cstr_info) { /* Threshold for Marcela Index */
opj_tcd_makelayer(tcd, layno, goodthresh, 1);
- /* fixed_quality */
cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] :
(cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
}
opj_free(tcd->tcd_image);
tcd->tcd_image = 00;
}
+
+ opj_free(tcd->used_component);
+
opj_free(tcd);
}
}
((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);*/
/* ----------------------------------------------------------------------- */
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;
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**/
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;
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) {
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) {
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];
/* 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)((
/*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);
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) {
}
}
- /** 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 -
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)) {
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);
}
/* +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 = 2 + (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) *
- (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32));
+ 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) {
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;
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;
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) */
}
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;
}
OPJ_UINT32 * p_data_written,
OPJ_UINT32 p_max_length,
opj_codestream_info_t *p_cstr_info,
+ opj_tcd_marker_info_t* p_marker_info,
opj_event_mgr_t *p_manager)
{
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 */
/* FIXME _ProfStart(PGROUP_T2); */
if (! opj_tcd_t2_encode(p_tcd, p_dest, p_data_written, p_max_length,
- p_cstr_info, p_manager)) {
+ p_cstr_info, p_marker_info, p_manager)) {
return OPJ_FALSE;
}
/* FIXME _ProfStop(PGROUP_T2); */
}
OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
- OPJ_UINT32 decoded_x0,
- OPJ_UINT32 decoded_y0,
- OPJ_UINT32 decoded_x1,
- OPJ_UINT32 decoded_y1,
+ 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,
)
{
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->decoded_x0 = decoded_x0;
- p_tcd->decoded_y0 = decoded_y0;
- p_tcd->decoded_x1 = decoded_x1;
- p_tcd->decoded_y1 = decoded_y1;
+ 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 >> */
}
/* 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); */
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;
}
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;
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) {
}
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) {
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));
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;
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;
}
check_pterm = OPJ_TRUE;
}
- for (compno = 0; compno < l_tile->numcomps; ++compno) {
+ 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);
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, l_tile_comp,
}
}
- ++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) {
}
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;
}
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 {
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));
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;
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 > (OPJ_FLOAT32)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;
l_current_ptr += l_stride;
}
}
-
- ++l_img_comp;
- ++l_tccp;
- ++l_tile_comp;
}
return OPJ_TRUE;
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) {
l_code_block->chunks = 00;
}
+ opj_aligned_free(l_code_block->decoded_data);
+ l_code_block->decoded_data = NULL;
+
++l_code_block;
}
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) {
}
}
-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;
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;
}
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;
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) {
}
} 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;
}
}
{
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;
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);
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;
}
}
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 */
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;
}
OPJ_UINT32 * p_data_written,
OPJ_UINT32 p_max_dest_size,
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;
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,
p_cstr_info->index_write = 0;
}
- if (l_cp->m_specific_param.m_enc.m_disto_alloc ||
- l_cp->m_specific_param.m_enc.m_fixed_quality) {
- /* fixed_quality */
- /* Normal Rate/distortion allocation */
+ if (l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ RATE_DISTORTION_RATIO ||
+ l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO) {
if (! opj_tcd_rateallocate(p_tcd, p_dest_data, &l_nb_written, p_max_dest_size,
p_cstr_info, p_manager)) {
return OPJ_FALSE;
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;
}
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;
/* with the tile coordinates */
OPJ_UINT32 tcx0 = opj_uint_max(
(OPJ_UINT32)tilec->x0,
- opj_uint_ceildiv(tcd->decoded_x0, image_comp->dx));
+ opj_uint_ceildiv(tcd->win_x0, image_comp->dx));
OPJ_UINT32 tcy0 = opj_uint_max(
(OPJ_UINT32)tilec->y0,
- opj_uint_ceildiv(tcd->decoded_y0, image_comp->dy));
+ opj_uint_ceildiv(tcd->win_y0, image_comp->dy));
OPJ_UINT32 tcx1 = opj_uint_min(
(OPJ_UINT32)tilec->x1,
- opj_uint_ceildiv(tcd->decoded_x1, image_comp->dx));
+ opj_uint_ceildiv(tcd->win_x1, image_comp->dx));
OPJ_UINT32 tcy1 = opj_uint_min(
(OPJ_UINT32)tilec->y1,
- opj_uint_ceildiv(tcd->decoded_y1, image_comp->dy));
+ 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 :
/* equation B-15 of the standard */
OPJ_UINT32 x0b = bandno & 1;
OPJ_UINT32 y0b = bandno >> 1;
- OPJ_UINT32 tbx0 = (nb == 0) ? tcx0 : opj_uint_ceildiv(tcx0 - (1U <<
- (nb - 1)) * x0b, 1U << nb);
- OPJ_UINT32 tby0 = (nb == 0) ? tcy0 : opj_uint_ceildiv(tcy0 - (1U <<
- (nb - 1)) * y0b, 1U << nb);
- OPJ_UINT32 tbx1 = (nb == 0) ? tcx1 : opj_uint_ceildiv(tcx1 - (1U <<
- (nb - 1)) * x0b, 1U << nb);
- OPJ_UINT32 tby1 = (nb == 0) ? tcy1 : opj_uint_ceildiv(tcy1 - (1U <<
- (nb - 1)) * y0b, 1U << nb);
+ 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) {
#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);
+ }
+}
+
+/* ----------------------------------------------------------------------- */